diff --git a/.gitignore b/.gitignore index 1d3bf8abe35ac..fa0b1458299ac 100644 --- a/.gitignore +++ b/.gitignore @@ -69,8 +69,6 @@ node-*-data/ pkg/catalog/test/ pkg/config/system_vars.go pkg/config/system_vars_test.go -pkg/udf/pythonservice/pyserver/udf/ -pkg/udf/pythonservice/pyserver/__pycache__/ path_to_file tester-log/ ut-report/ diff --git a/.golangci.yml b/.golangci.yml index 1d38a9fb11978..b8778e6ab54d9 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -35,20 +35,27 @@ linters: - $all - '!$test' - '!pkg/iceberg/adapter/iceberggo/**/*.go' - # Arrow IPC is isolated to the ingestion bridge and its external - # scan reader. Keep the dependency out of all other production - # packages, including the Iceberg-facing layers. + deny: + - pkg: github.com/apache/iceberg-go + desc: Iceberg dependency must stay behind pkg/iceberg/adapter/iceberggo + arrow-boundary: + list-mode: lax + files: + - $all + - '!$test' + - '!pkg/iceberg/adapter/iceberggo/**/*.go' + # Arrow belongs to the ingestion and external UDF boundaries. + # These owners do not also receive permission to import Iceberg. - '!**/pkg/container/arrowbridge/*.go' - '!**/pkg/sql/colexec/external/arrowio/*.go' - '!**/pkg/sql/colexec/external/reader_arrow.go' - '!**/pkg/sql/compile/compile.go' + - '!**/pkg/udf/python/*.go' deny: - - pkg: github.com/apache/iceberg-go - desc: Iceberg dependency must stay behind pkg/iceberg/adapter/iceberggo - pkg: github.com/apache/arrow-go - desc: Arrow dependency must not leak outside the Iceberg adapter + desc: Arrow dependency must stay behind an approved Arrow owner - pkg: github.com/apache/arrow/go - desc: Arrow dependency must not leak outside the Iceberg adapter + desc: Arrow dependency must stay behind an approved Arrow owner govet: disable: - fieldalignment diff --git a/cmd/mo-service/config.go b/cmd/mo-service/config.go index 228412712533f..3a4b07c5c8ce5 100644 --- a/cmd/mo-service/config.go +++ b/cmd/mo-service/config.go @@ -45,7 +45,7 @@ import ( "github.com/matrixorigin/matrixone/pkg/perfcounter" "github.com/matrixorigin/matrixone/pkg/proxy" "github.com/matrixorigin/matrixone/pkg/tnservice" - "github.com/matrixorigin/matrixone/pkg/udf/pythonservice" + "github.com/matrixorigin/matrixone/pkg/udf/python" "github.com/matrixorigin/matrixone/pkg/util/debug/goroutine" tomlutil "github.com/matrixorigin/matrixone/pkg/util/toml" "github.com/matrixorigin/matrixone/pkg/version" @@ -123,8 +123,8 @@ type Config struct { CN cnservice.Config `toml:"cn"` // ProxyConfig is the config of proxy. ProxyConfig proxy.Config `toml:"proxy"` - // PythonUdfServerConfig is the config of python udf server - PythonUdfServerConfig pythonservice.Config `toml:"python-udf-server"` + // PythonUdfWorkerConfig is the config of the Python UDF worker. + PythonUdfWorkerConfig python.Config `toml:"python-udf-worker"` // Observability parameters for the metric/trace Observability config.ObservabilityParameters `toml:"observability"` @@ -601,7 +601,7 @@ func (c *Config) mustGetServiceUUID() string { case metadata.ServiceType_PROXY: return c.ProxyConfig.UUID case metadata.ServiceType_PYTHON_UDF: - return c.PythonUdfServerConfig.UUID + return c.PythonUdfWorkerConfig.UUID } panic("impossible") } diff --git a/cmd/mo-service/main.go b/cmd/mo-service/main.go index 4f562b26c23ab..fcfa3af25a86f 100644 --- a/cmd/mo-service/main.go +++ b/cmd/mo-service/main.go @@ -52,7 +52,7 @@ import ( qclient "github.com/matrixorigin/matrixone/pkg/queryservice/client" "github.com/matrixorigin/matrixone/pkg/sql/compile" "github.com/matrixorigin/matrixone/pkg/tnservice" - "github.com/matrixorigin/matrixone/pkg/udf/pythonservice" + "github.com/matrixorigin/matrixone/pkg/udf/python" "github.com/matrixorigin/matrixone/pkg/util/debug/goroutine" "github.com/matrixorigin/matrixone/pkg/util/export" "github.com/matrixorigin/matrixone/pkg/util/export/table" @@ -300,7 +300,7 @@ func startService( case metadata.ServiceType_LOG: return startLogService(cfg, stopper, fs, shutdownC) case metadata.ServiceType_PYTHON_UDF: - return startPythonUdfService(cfg, stopper) + return startPythonUdfWorker(cfg, stopper) default: panic("unknown service type") } @@ -738,8 +738,8 @@ func waitProxyFileServiceRetry(ctx context.Context, delay time.Duration) error { } } -// startPythonUdfService starts the python udf service. -func startPythonUdfService(cfg *Config, stopper *stopper.Stopper) error { +// startPythonUdfWorker starts the Python UDF worker. +func startPythonUdfWorker(cfg *Config, stopper *stopper.Stopper) error { if err := waitClusterCondition(cfg.mustGetServiceUUID(), cfg.HAKeeperClient, waitHAKeeperRunning); err != nil { return err } @@ -752,22 +752,39 @@ func startPythonUdfService(cfg *Config, stopper *stopper.Stopper) error { finish(err) }) } - err := stopper.RunNamedTask("python-udf-service", func(ctx context.Context) { + err := stopper.RunNamedTask("python-udf-worker", func(ctx context.Context) { var closeErr error defer func() { finishTask(closeErr) }() roleCtx, cancelRole := serviceLifecycle.roleContext(ctx, serviceRolePython) defer cancelRole() - s, err := pythonservice.NewService(cfg.PythonUdfServerConfig) + s, err := python.NewSupervisor(cfg.PythonUdfWorkerConfig) if err != nil { panic(err) } if err := s.Start(); err != nil { panic(err) } - <-roleCtx.Done() - if err := s.Close(); err != nil { - closeErr = err - logutil.GetGlobalLogger().Error("failed to close python udf service", zap.Error(err)) + workerDone := s.Done() + select { + case <-roleCtx.Done(): + if err := s.Close(); err != nil { + closeErr = err + logutil.GetGlobalLogger().Error("failed to close Python UDF worker", zap.Error(err)) + } + case <-workerDone: + // A worker exit while the role is still running leaves CN with a + // configured but unusable Python runtime. Surface it as a fatal + // service event so the existing lifecycle supervisor drains CN + // before the worker dependency and does not accept partial service + // availability. A zero exit is still unexpected here. + if roleCtx.Err() == nil { + workerErr := s.Err() + if workerErr == nil { + workerErr = errors.New("process exited without an error") + } + closeErr = fmt.Errorf("python UDF worker exited unexpectedly: %w", workerErr) + serviceLifecycle.notifyFatal(closeErr) + } } }) if err != nil { diff --git a/docs/cn/stream_transport_fast_upload_plan.md b/docs/cn/stream_transport_fast_upload_plan.md index 8e3bdb6ff4bb4..cc7227e17f513 100644 --- a/docs/cn/stream_transport_fast_upload_plan.md +++ b/docs/cn/stream_transport_fast_upload_plan.md @@ -20,7 +20,7 @@ Phase 0 — Protobuf / gRPC contract New file `proto/datastream/v1/datastream.proto` (proto3, **not** gogoproto — this proto is shared with Java, so use standard `protoc-gen-go` + -`protoc-gen-go-grpc`, same toolchain as `pkg/udf/udf.proto`, which is the +`protoc-gen-go-grpc`, using the repository's current protobuf toolchain, which is the existing real-gRPC precedent in the repo; the main `proto/*.proto` files are gogo-generated and Java-hostile). diff --git a/docs/design/python_udf.md b/docs/design/python_udf.md new file mode 100644 index 0000000000000..a2b7e02dd11f5 --- /dev/null +++ b/docs/design/python_udf.md @@ -0,0 +1,112 @@ +# Python UDF implementation and rollout scope + +This describes the implemented, owner-authorized external Python adapter and its +PR acceptance boundary. The relevant current-stage Catalog, SQL/planner, +migration/restore, Python ABI, Flight, and resource contracts are consolidated +in the [versioned current-stage design](python_udf_current_stage.md). Broader +long-term designs continue to inform future work; this page does not approve a +production tenant-isolation model. + +## Owner-approved stage scope + +On 2026-09-24, feature owner `iamlinjunhong` approved this PR for testing and +development-stage acceptance. The user guide and SQL examples are recorded in +[issue #28132](https://github.com/matrixorigin/matrixone/issues/28132#issuecomment-5748253137). +This PR does not claim production rollout, sandbox isolation, protection for +untrusted Python, or authenticated/TLS Flight transport. Those remain separate +production acceptance gates. Python stays disabled in generic launch and requires +explicit opt-in in the test/development configurations. + +This stage decision is the feature owner's authorization for the current PR +scope; it is not a claim that Architecture, Security, SQL/Planner, Runtime, +Catalog, or Operator owners have approved the future production design. + +## Execution and identity + +CREATE/REPLACE validates Python syntax and the handler contract before publishing +a definition. The shared Catalog stores immutable typed revisions and complete +argument/return descriptors. Artifacts are digest-addressed, account-scoped and +published through FileService; worker execution receives the verified artifact +from CN. The worker needs no object-storage credentials or query-time package +installation. Old demo definitions are inert: explicitly recreate them using the +current DDL and SDK. Unknown definition, plan, Arrow, SDK or wire contracts fail +before user execution; no legacy fallback or automatic adapter is provided. + +Planning resolves an exact FunctionRef and RoutineCall. Prepared/cache reuse +validates the selected revision and the complete overload namespace state; see +[routine namespace validation](routine_namespace_validation.md). Execution never +resolves a mutable latest revision. Clone and restore preserve supported catalog +contracts and republish Python artifacts for the destination account. + +CN keeps native MO vectors. The expression framework dispatches typed Python calls +to ExternalRoutineEval; the parent evaluator owns argument evaluation, casts, +CASE/selection and NULL guards. The physical stage compacts selected rows, +admits bounded asynchronous work and scatters verified results, preserving empty +input, NULLs, zero arguments, nested calls and default VOLATILE semantics. + +The Gateway is a CN library, not a separately deployed service. It connects to +Arrow Flight served by the Python worker. No second Flight daemon is required. +A worker creates bounded handler subprocesses; each handler/module can be reused +only within the invocation's bounded burst. It does not pool user heaps across +invocations. SCALAR handlers receive `(ctx, scalar...)`; VECTOR handlers receive +`(ctx, arrays...)` and use `ctx.num_rows` for output shape. Arrow field/schema +metadata comes from the trusted adapter, not handler-supplied identity. + +## Completion and resources + +K bounds active Gateway invocations, H bounds handler execution slots, and W=1 +bounds stream batch progress. Admission, group/member state, terminal records and +per-account/per-owner quotas have independent owners and budgets. Protocol steps +include EndInput, InputConsumed, result ACK and Finish/FinishAck. Started work is +never transparently replayed. Cancellation and capability refresh waiters progress +independently; generation fences reject stale completions. + +Process cleanup must cover both termination and reaping. Handler sessions own +pipes, child/watchdog processes and H/quota until cleanup succeeds; partial +initialization transfers a failed session to the same bounded pending-cleanup +owner. Linux containers run `/usr/bin/tini -- python -u worker.py`; init adopts +orphaned descendants after their handler leader exits. An Operator command override +must retain this init process. Native Supervisor launches rely on the host's init +(or an explicit subreaper in a container test harness). + +## Enablement and deployment boundary + +Generic launch keeps Python disabled. The explicit worker-enabled launch and +ordinary BVT entry point enable the unisolated adapter. See +[Python BVT and local launch](../../test/distributed/cases/udf_python/README.md). +Compose configures a separate worker endpoint for each CN. The `PYTHON_UDF` +mo-service role wraps a Go Supervisor; the standalone worker image runs Python +under init. These are different launch forms for the same Flight service. + +Gateway and worker must match the current capability contract, including tzdata. +The worker image replaces its entire zoneinfo tree from the MO runtime base; +upgrading tzdata also changes the environment digest of definitions. Check existing +definitions before enabling an incompatible environment and explicitly rebuild +where required. Matching software version strings alone are not this check. + +`enabled` and `allow-unisolated` are explicit gates. This implementation does not +provide sandbox isolation or authenticated/TLS Flight transport. Same-Pod Operator +configuration binds the worker to loopback and controls Pod composition; it does +not add broad CN ingress grants. External worker exposure needs a separately +approved security/deployment design. Worker availability is a Python execution +condition, not evidence of production tenant isolation. + +## Verification and remaining scope + +The regression suite covers scalar/vector Arrow computation, types and malformed +values, guarded SQL positions and DML atomicity, revision/overload invalidation, +exact-descriptor DROP and cross-account snapshot restore. Runtime tests cover +ACK/Finish, cancellation, quotas, initialization/cleanup failure, worker death, +stale events and real Flight consumers. Operator status wire fixtures pin the +producer/consumer error contract. + +Linux PR validation uses the repository CGo wrapper, two CNs with distinct +Supervisor/worker endpoints, ordinary SQL/Python BVT, current worker image and +process-tree fault injection. Record the exact revision, selected tests, image +and terminal result with each run; unit or CNI echo tests are not complete +Operator rollout evidence. + +Sandbox, production deployment approval, imported dependency environments and +W>1/cumulative ACK enablement remain separate work. W=1 measurements do not prove +that a wider window has no benefit. This PR is related to issue #28132 and does +not close that issue's broader isolated-runtime acceptance criteria. diff --git a/docs/design/python_udf_current_stage.md b/docs/design/python_udf_current_stage.md new file mode 100644 index 0000000000000..994b8016729d2 --- /dev/null +++ b/docs/design/python_udf_current_stage.md @@ -0,0 +1,236 @@ +# Python UDF current-stage design contract + +| Field | Value | +| --- | --- | +| Design revision | `python-udf-current-stage-r1-2026-09-24` | +| Applies to | MatrixOne PR #29152, test/development-stage Python UDF | +| Implementation baseline reviewed | `9847da80d6c7096cb0460e46a5cf710e9714af3a` | +| Approval | Feature owner `iamlinjunhong` approved this exact revision for the current test/development stage on 2026-09-24 in [PR comment](https://github.com/matrixorigin/matrixone/pull/29152#issuecomment-5809313638). The immutable artifact and independent-review status are recorded in the [design approval record](python_udf_current_stage_approval.md). | +| Not covered | Production tenant isolation, sandbox, Operator rollout, or cross-version rollback/restore | + +This is the approved governing contract for the current PR stage. It consolidates +the shared Catalog, SQL/planner, Python ABI, Flight, and resource-lifecycle +decisions needed to review this implementation. It does not approve future +sandbox or production deployment. The test/development scope is explicit: +Python is opt-in and unisolated; old demo definitions are rejected and must be +recreated through the current DDL. There is no legacy Python adapter or +fallback execution path. + +## Identity, Catalog, and publication + +Python functions use the shared `mo_user_defined_function` identity namespace. +The current catalog upgrade adds `active_revision`, `namespace_version`, the +canonical input/return descriptors, and signature schema/fingerprint columns. +`mo_function_revisions` stores the immutable typed revision keyed by +`(function_id, revision)`, including language, full argument and return +descriptors, ABI/adapter/SDK/schema contracts, artifact and environment digests, +NULL policy, volatility, security mode, and definition fingerprint. Revision +publication and head activation occur in the caller's catalog transaction. +Python executes as `INVOKER`, is `VOLATILE`, may error, and is not leakproof. + +The artifact is an immutable, account-scoped FileService object addressed by +digest; each artifact is at most 1 MiB. CN resolves the exact account/digest +before Open, and the worker receives verified source bytes without object-store +credentials or query-time dependency installation. CREATE/REPLACE validates the +current contract before committing a catalog definition. Artifact publication +precedes catalog commit, so a failed validation/transaction can leave an +unreferenced content-addressed object. No artifact garbage collector or +per-account total artifact quota exists today; per-object size is bounded, total +retained artifact storage is not. This is an explicit test/development-stage +limitation, not a production storage-retention claim. + +The type descriptor is canonical over SQL type ID and applicable width, scale, +charset, offset-width, JSON, and temporal encodings. The trusted adapter builds +Arrow field/schema metadata from that descriptor; it validates both physical +Arrow type and the SQL value domain. Handler-provided metadata cannot redefine +the function type. CREATE/REPLACE compiles the submitted module and checks the +declared synchronous module-level handler; it does not execute top-level user +code or install packages. The environment digest includes the current runtime +environment, including tzdata. An environment mismatch fails closed; definitions +must be explicitly recreated for a changed contract. + +The current mappings encode JSON as `canonical_text` and DATE/DATETIME/TIMESTAMP +with `sql_zero_struct`; SQL zero temporal values remain explicit values and are +never rewritten as NULL. SCALAR handlers receive `(ctx, scalar...)`; VECTOR +handlers receive `(ctx, arrays...)`. The default NULL policy calls the handler +without filtering NULL rows; `RETURNS NULL ON NULL INPUT` removes those rows +before the call and scatters NULLs into their result positions. + +`REPLACE` preserves language and the exact Python argument/return descriptors; +changing language or signature requires DROP/CREATE. DROP/CREATE receives a new +identity. Old Python demo rows without a current revision head, unsupported +definition/SDK/plan contracts, and corrupt revision heads fail closed before +user code runs. They are not auto-migrated. No query resolves a mutable `latest` +revision or takes source from an executable plan. + +## SQL compatibility, plans, and migration + +The shared revision catalog is additive to the existing SQL UDF contract. +During a rolling tenant upgrade, SQL UDF writers continue using the legacy +`mo_user_defined_function` row while `mo_function_revisions` is absent. Once the +revision catalog is available, SQL writers publish the compatibility row and +revision in the same transaction. Readers use the legacy SQL row only when the +revision schema/head is absent or both head fields are zero. A non-zero but +missing or malformed revision is a catalog error; it never silently falls back. +The SQL UDF language, body, security, and evaluation semantics remain owned by +the existing SQL path. The Python demo's old execution behavior is not a +compatibility promise. + +Upgrade `4.0.7` (minimum source `4.0.6`) changes the shared function identity +columns/index and creates `mo_function_revisions`. The upgrade handler is gated +on common MORPC protocol 61 so a tenant migration does not widen catalog tables +while an old writer can still serve them. Python DDL independently probes the +required tenant schema and refuses creation/replacement until it is present; +worker capability negotiation is a separate exact-contract gate. This is +feature-level admission, not a requirement that every component have the same +software version string. + +The migration has no down handler. Do not manually remove the revision table, +columns, or index, and do not claim that restoring an old binary restores Python +execution. Binary rollback after applying this catalog migration is not a +supported recovery path in this contract; ordinary SQL behavior in that mixed +state has not been verified here. Python definitions must remain intact and +require a current-contract binary to execute. The current evidence does not +include a tested downgrade after Python definitions have been written. +The upgrade-compatibility CI checks were skipped on the reviewed exact head. + +Current-contract snapshot restore preserves the selected revision and +republishes its artifact into the destination account's namespace. The SQL +control function and source-account isolation are covered in +[`snapshot_restore.sql`](../../test/distributed/cases/udf_python/snapshot_restore.sql). +Cross-version restore and downgrade are outside the evidence and remain +unsupported until tested. Restore must not synthesize a revision from a legacy +Python row. + +The plan contains a typed `RoutineCall`, an exact `FunctionRef` (account, +database, identity, revision, namespace), a typed implementation oneof, and a +dependency envelope. Python source is not embedded in the executable plan. +Plan reuse validates both the exact selected revision and a fingerprint of the +complete same-name overload namespace across SQL and Python. The dependency +closure is capped at 1,024 routines and 1 MiB. This invalidates prepared/cache +plans when a newly added overload changes binding, even if the previously +selected identity still exists. Plans without the namespace fingerprint rebind; +an overflowed namespace read makes the plan non-reusable rather than accepting a +truncated fingerprint. Execution uses the bound exact reference and never +resolves by name. Namespace validation reads at most 65,536 candidates (one +extra detects overflow) and 64 MiB of decoded metadata; on overflow it forces +rebind without rejecting otherwise valid SQL. + +## SQL evaluation and result semantics + +`ExternalRoutineEval` is a physical expression evaluator in the existing MO +expression framework. The parent supplies the batch and CASE/selection mask; +the evaluator runs each bound argument expression, including planned casts, +once under that mask, applies +`RETURNS NULL ON NULL INPUT`, compacts selected rows, validates the returned +Arrow schema and SQL value domain, then scatters results to original row +positions. Unselected CASE branches are not invoked. Python's default +volatility prevents planning-time constant folding. Empty input, a batch with +no rows selected, and a batch whose rows are all removed by strict NULL +filtering return locally without acquiring Gateway K, a worker group, or a +ledger entry. Zero-argument VECTOR calls receive `ctx.num_rows` for output +shape. + +The ordinary Python BVT includes SELECT, WHERE, JOIN ON/outer-join predicates, +aggregate arguments, window ordering, nested calls, INSERT/UPDATE/DELETE, and +failure atomicity. It also covers scalar/vector modes, NULL policies, create, +replace, exact-overload invalidation, drop/recreate, Arrow compute, and +current-contract account restore. These are current tested placements; this +contract does not claim every possible SQL syntactic position without a case. + +## Flight protocol and terminal ownership + +Gateway is a CN library; the worker is the Flight server. There is no separately +deployed Gateway daemon. The current capability vector must match exactly +(wire protocol 1, ABI/adapter/SDK/definition/plan/type contracts, tzdata, +modes, NULL policies, frame/handler limits, and worker lease epoch). The worker +advertises `window_batches=1` and `cumulative_ack=false`. A mismatch fails +before handler execution; there is no old-worker fallback. Control envelopes +are limited to 1 MiB, JSON nesting to 64, and each fencing ID component to +256 bytes. + +After admission reserves the group/member, K, and ledger, the Gateway opens the +exchange. With W=1, each non-final batch follows +`InputBatch(i) → InputConsumed(i) → ResultBatch(i) → AcknowledgeResults(i)` +before the Gateway sends batch `i+1`. After sending the final +`InputBatch(last_seq)`, the Gateway sends `EndInput(last_seq)` and half-closes +its send direction; it then receives the final `InputConsumed`, result, and ACK, +followed by `Finish → AcknowledgeFinish(finish_id) → terminal success`. + +`EndInput` closes only the input direction; Flight send-half-close is normal +and the result direction remains readable. `InputConsumed` returns ownership of +the corresponding input backing. The result slot remains charged until it has +been validated and materialized in MO. W=1 permits one batch of progress at a +time. Finish is valid only after EndInput and acknowledgement of all result +sequences. The worker freezes success only after accepting the idempotent +Finish acknowledgement. If the ACK was accepted but its response was lost, the +Gateway retries only that same idempotent ACK; if confirmation remains unknown, +it reports `FINISH_UNCONFIRMED`. It never retries Open or replays work that may +have reached STARTED. + +The CN Gateway owns K, group/member admission, and its terminal ledger. A +member releases only its own resources; the group owner releases the group and +reservation. The current integration uses one invocation member per group. +Empty and all-NULL work is completed locally by the evaluator, without a remote +group. For admitted work, partial Open, cancellation, and close have one owner +and a terminal outcome. The worker owns H, child process/session cleanup, and +its own ledger. Generation/lease fences reject stale callbacks and messages. A +terminal TTL alone never grants a new execution epoch. On cancel, timeout, or +transport failure, Gateway cancels/closes the exchange before returning its +local K or ledger ownership; the worker retains H and cleanup ownership until +the child is terminated and reaped. STARTED work is not transparently replayed. + +Worker handler children are process-group scoped and must be terminated and +reaped by the worker's cleanup owner before H is returned. A failed or partial +cleanup retains bounded cleanup ownership instead of releasing H early. Linux +process-tree failure tests provide implementation evidence; this process model +does not confine a handler's access to the host or its Python heap. + +## Resource budgets and trust boundary + +Zero in an enabled CN client config means the runtime default, not unlimited. +The current defaults are: + +| Resource | Owner and default | Contract | +| --- | --- | --- | +| K, active invocations | CN Gateway: 8 per CN | Non-blocking admission; a full budget rejects rather than queueing while holding input vectors. | +| W, stream window | Gateway/worker: 1 batch | No multiple in-flight batches or cumulative ACK. | +| H, handler subprocesses | Worker: 8 total, 8/account, 4/owner | Worker constants and capability contract; admission is all-or-nothing. | +| Batch | CN/worker: 16 MiB and 65,536 rows | Each Arrow batch is bounded before transfer. | +| Invocation | CN/worker: 1,048,576 rows; CN result: 256 MiB | Result bound is per invocation. At K=8, retained result vectors alone can reach 2 GiB per CN. | +| Request | CN: 30 s default; worker ACK: 60 s | Configured handler timeout and protocol ACK timeout have distinct owners. | +| CN terminal state | 8,192 entries, 8 MiB, 10 min | Active entries plus tombstones and separately reserved closed-group fences are bounded. | +| Worker terminal state | 10,000 entries, 16 MiB, 5 min | Independent bound; worker values intentionally differ from CN values. | +| Worker pending cleanup | 10,000 invocations | Derived from worker ledger capacity; cleanup failure retains ownership rather than releasing H. | +| Same-invocation burst reuse | Worker: 64 batches, 64 MiB, or 30 s | The first reached limit ends reuse; statement deadline and started inputs do not reset. | + +The per-invocation result maximum multiplied by K is a deliberate worst-case +capacity implication, not a process-wide RSS limit. Arrow/IPC, pickle/pipe, +temporary snapshots, materialization, Python heap, queues, file descriptors, +and child processes have different owners; wire-byte limits do not cap arbitrary +Python heap growth. Artifact count and total FileService bytes are not capped. +The CN's completion retention is longer than the worker's (10 versus 5 minutes); +the limits are compatible, not equal. The CN retains its own terminal/group +fences and never transparently resends STARTED work after a worker tombstone +expires. +The adapter is unisolated, Flight has no TLS/authentication in this stage, and +the fencing tuple is not an authentication token. These limits support +test/development correctness and backpressure, not hostile-code containment. + +## Evidence and remaining limits + +| Contract | Evidence on the reviewed branch/head | Status | +| --- | --- | --- | +| Shared revision schema and SQL legacy fallback | `pkg/bootstrap/versions/v4_0_7/upgrade_test.go`; `pkg/frontend/python_udf_catalog_test.go` | Unit/schema contract covered; upgrade-compatibility CI was skipped. | +| Exact FunctionRef and overload invalidation | `pkg/frontend/routine_plan_validation_test.go`; `pkg/frontend/routine_namespace_test.go`; `test/distributed/cases/udf_python/overload_namespace.sql` | Unit and SQL prepared-plan cases present. | +| SQL expression placement and result semantics | `pkg/sql/colexec/external_routine_eval.go`; `test/distributed/cases/udf_python/relational_positions.sql`, `dml_positions.sql`, `vector_mode.sql` | Physical evaluator and ordinary BVT cases present. | +| Current-contract restore | `pkg/frontend/clone_database_source.go`; `pkg/frontend/snapshot_catalog_restore.go`; `snapshot_restore.sql` | Same-contract account restore case present; cross-version restore not verified. | +| Flight state, ACK, cancellation, resource limits | `pkg/udf/python/gateway_test.go`, `gateway_admission_test.go`, `capability_lifecycle_test.go`, `gateway_integration_test.go`, `pkg/udf/python/worker/test_worker.py`, `test_watchdog.py` | Unit, process, and real Flight cases present; this design does not substitute for implementation/lifecycle review. | +| Exact-head CI | PR #29152 validation reported shared build, Linux UT, SCA, coverage, and active multi-CN BVT passed | Upgrade-compatibility checks skipped; no downgrade evidence. | + +The reviewed change is not declared production-ready. Artifact GC/total-storage +quota, cross-version migration rollback/restore, authenticated transport, and +sandboxing remain explicit limits. The owner-approved acceptance is limited to +the test/development stage. This approval closes the current-stage design gate; +the reviewer must still complete the implementation/lifecycle review before the +PR review is complete. diff --git a/docs/design/python_udf_current_stage_approval.md b/docs/design/python_udf_current_stage_approval.md new file mode 100644 index 0000000000000..ae17966108032 --- /dev/null +++ b/docs/design/python_udf_current_stage_approval.md @@ -0,0 +1,67 @@ +# Python UDF current-stage design approval record + +| Field | Value | +| --- | --- | +| Record | `python-udf-current-stage-r1-2026-09-24-approval` | +| Issue | [MatrixOne #28132](https://github.com/matrixorigin/matrixone/issues/28132) | +| Implementation PR | [MatrixOne #29152](https://github.com/matrixorigin/matrixone/pull/29152) | +| Current-stage contract | [`python-udf-current-stage-r1-2026-09-24`](python_udf_current_stage.md) | +| Scope | Explicitly enabled test/development adapter; no production rollout or production-readiness claim | + +This record separates the immutable current-stage design artifact, the feature +owner's scope authorization, and independent technical approval facts. It is a +traceability record; it does not create an approval that is not present in the +PR or issue history. + +## Immutable artifacts + +The design content accepted for the current test/development stage was published +in the rebased PR history at commit [`c6f9c7682279816872fc3b3f7d5cf41ffe940acc`](https://github.com/matrixorigin/matrixone/commit/c6f9c7682279816872fc3b3f7d5cf41ffe940acc). +The corresponding pre-rebase review commit was +[`610d1e4dcfe2bad2ed1060babe0acc60c89b1c60`](https://github.com/matrixorigin/matrixone/commit/610d1e4dcfe2bad2ed1060babe0acc60c89b1c60). +The exact Git blob for +[`docs/design/python_udf_current_stage.md`](https://github.com/matrixorigin/matrixone/blob/c6f9c7682279816872fc3b3f7d5cf41ffe940acc/docs/design/python_udf_current_stage.md) +at both design commits is +`2adcb1ec63ced2dfbdedf192509b07d5b7c9db31`. + +The design was written against implementation baseline +[`9847da80d6c7096cb0460e46a5cf710e9714af3a`](https://github.com/matrixorigin/matrixone/commit/9847da80d6c7096cb0460e46a5cf710e9714af3a). +The rebase-equivalent implementation baseline in the final PR history is +[`1a26a2f9046643a284df488f57470b811cca747a`](https://github.com/matrixorigin/matrixone/commit/1a26a2f9046643a284df488f57470b811cca747a). +The pre-rebase exact review head was +[`92a89d81588159a918458b1a930bccc9d0e75d4b`](https://github.com/matrixorigin/matrixone/commit/92a89d81588159a918458b1a930bccc9d0e75d4b). +The repair commit carrying this record is the final documentation commit on +top of the rebased PR history; its exact remote head is verified at delivery. +The final current-stage design blob is +`994b8016729d2e87a6a706a2833eee7faf50c89b`; its only difference from the +approved design blob is the link to this traceability record. + +The namespace-validation companion is the implementation contract from commit +[`284a1d971a1d2c763c6aed425d52f751735c409f`](https://github.com/matrixorigin/matrixone/commit/284a1d971a1d2c763c6aed425d52f751735c409f), +with current-head blob `51ccfb771db19321d03b292cd3d7219f698a11b8`. + +## Approval ledger + +| Decision area | Evidence and scope | Status | +| --- | --- | --- | +| Feature-owner acceptance | [PR comment](https://github.com/matrixorigin/matrixone/pull/29152#issuecomment-5809313638) approves the exact current-stage contract for testing/development use. | Approved for this limited scope | +| Architecture review | No independent approval record naming the reviewer, exact design artifact, date, scope, and decision is present in the PR/issue history examined at pre-rebase head `92a89d81588159a918458b1a930bccc9d0e75d4b`. | Pending; not inferred | +| Security review | The contract records the unisolated, opt-in boundary and explicitly excludes sandboxing and authenticated/TLS Flight. That scope record is not a production security approval. | Pending for any production/security enablement; not inferred | +| SQL/Planner review | The current-stage document contains the shared Catalog, exact revision, overload, evaluation, migration, restore, and compatibility contract. No independent approval record for that exact artifact is present in the PR/issue history examined at the recorded pre-rebase head. | Pending; not inferred | +| Cloud/Operator review | The current-stage document records launch, init, endpoint, and rollout limits, and excludes Operator rollout acceptance. No independent approval record for production/operator rollout is present. | Pending; not inferred | + +The pending rows are external approval facts and are intentionally not replaced +by feature-owner authorization, passing CI, or implementation review. They must +remain separate from the test/development acceptance boundary. This PR does not +authorize production tenant isolation, sandboxing, authenticated transport, +Operator rollout, artifact garbage collection, total artifact quota, or +cross-version downgrade/restore. + +## Evidence boundary + +The design document's evidence table identifies the focused unit, process, Flight, +SQL/BVT, restore, and exact-head CI evidence. Upgrade-compatibility checks were +skipped at the recorded head; cross-version rollback/restore is unsupported in +this stage. Those gaps are recorded as limits and are not represented as passing +approval evidence. Full implementation/lifecycle review remains a separate PR +review step after the design record is accepted by the relevant reviewers. diff --git a/docs/design/routine_namespace_validation.md b/docs/design/routine_namespace_validation.md new file mode 100644 index 0000000000000..51ccfb771db19 --- /dev/null +++ b/docs/design/routine_namespace_validation.md @@ -0,0 +1,48 @@ +# Routine overload namespace validation + +A cached or prepared routine call depends on two distinct things: + +* the exact selected FunctionRef and immutable revision contracts; +* the complete candidate set for its account/database/name at binding time. + +The revision-local `namespace_version` stored on an identity/revision cannot be +used as the second dependency: CREATE of a sibling does not update that tuple. +Updating all sibling heads would make them disagree with immutable revisions. + +`RoutineCall.namespace_fingerprint` and `RoutinePlanDependency.namespace_fingerprint` +now carry a separate state fingerprint. The resolver and reuse validator read +all same-name candidates, across SQL/Python and signatures, in their catalog +read transaction (and with the explicit historical snapshot when applicable). +The internal reads are marked derived after BEGIN and restored before finishTxn, +so READ COMMITTED cannot advance the snapshot between enumeration and digest +capture. Database identity uses the same read transaction and snapshot tenant. +The selected ID locates the namespace; account context and the independently +validated database ID fence its scope. Execution continues to use the exact +FunctionRef, never a name or a latest-revision lookup. + +The query deduplicates namespaces before joining candidates, and projects fixed-width +SHA-256 hashes of text/JSON metadata instead of transferring source bodies. +The canonical encoding hashes a versioned JSON tuple per candidate: identity, +active revision, revision-local namespace, base arguments/body/language/return/ +database/SQL mode/security, plus effective revision arguments/body/language/ +return/security. Sorted fixed-length candidate digests form the namespace +state digest. Thus newly introduced better/ambiguous matches invalidate even +when the selected identity is unchanged. DROP, replacement, clone and restore +follow visible catalog state. Restoring exactly the same candidates need not +invalidate: this is not an event counter. Selected revision integrity and +security checks still run independently. + +There is no new persistent catalog or backfill. Older plans without the digest +cannot be reused; the normal bind path regenerates the dependency. A missing +selected identity invalidates rather than reporting catalog corruption. Empty +candidate results are distinct from malformed multi-result responses. + +Validation reads are bounded to 65,536 candidate rows (an extra row detects +overflow) and 64 MiB of decoded metadata per read. Exceeding either marks the plan non-reusable and forces rebind, +never accepts a truncated digest and does not reject otherwise valid SQL. This increases reuse validation cost with the +number of overloads and their definition size. It does not add worker RPCs or +per-row lookups. Dependency count/serialized-byte bounds remain in force. + +This replaces the earlier proposal to advance a separate mutable namespace +generation for every overload-set change. It preserves that proposal's cache +correctness property without introducing a second publication/restore index. diff --git a/etc/launch-tae-compose/README.md b/etc/launch-tae-compose/README.md index 0939446a1ecf5..eba459e079429 100644 --- a/etc/launch-tae-compose/README.md +++ b/etc/launch-tae-compose/README.md @@ -43,6 +43,11 @@ MatrixOne's trusted main-branch cache warmer keeps the Maven repository and wrapper distribution available to PR CI. Pull-request jobs restore that cache read-only; they never publish dependencies resolved from an untrusted head. +The compose BVT starts one Python UDF worker per CN. The worker image is shared +by both services, while the worker processes, addresses, and failure domains +remain separate (`cn-0` uses `python-udf-worker-cn0`, and `cn-1` uses +`python-udf-worker-cn1`). + ## Check log ```shell diff --git a/etc/launch-tae-compose/compose.yaml b/etc/launch-tae-compose/compose.yaml index 9b2136fa74139..3ca71f49f20c4 100644 --- a/etc/launch-tae-compose/compose.yaml +++ b/etc/launch-tae-compose/compose.yaml @@ -28,6 +28,22 @@ x-mo-common: &mo-common - NET_ADMIN tty: true +x-python-udf-worker: &python-udf-worker + image: matrixorigin/mo-python-udf-worker:latest + # The image is built by python-udf-worker-image in this Compose project. + # Do not race that local build with an unauthenticated registry pull. + pull_policy: never + restart: on-failure + profiles: + - launch + - launch-multi-cn + healthcheck: + test: ["CMD", "python", "healthcheck.py"] + interval: 2s + timeout: 3s + retries: 30 + start_period: 1s + services: cn-0: @@ -40,7 +56,10 @@ services: - launch - launch-multi-cn depends_on: - - tn + tn: + condition: service_started + python-udf-worker-cn0: + condition: service_healthy ports: - "6002" - "12345:12345" @@ -59,7 +78,10 @@ services: <<: *mo-common entrypoint: ["/bin/bash","-c","set -euo pipefail; exec /mo-service -debug-http :12345 -cfg /config/cn-1.toml > >(tee -a /log/cn-1.log) 2>&1"] depends_on: - - tn + tn: + condition: service_started + python-udf-worker-cn1: + condition: service_healthy ports: - "6002" - "22345:12345" @@ -146,6 +168,43 @@ services: aliases: - "logservice" + # Build the worker image once. The two CN-scoped worker services below use + # the resulting image and keep their process and failure domains separate. + python-udf-worker-image: + container_name: python-udf-worker-image + build: + context: ../../pkg/udf/python/worker + dockerfile: Dockerfile + image: matrixorigin/mo-python-udf-worker:latest + pull_policy: build + command: ["true"] + restart: "no" + profiles: + - launch + - launch-multi-cn + + python-udf-worker-cn0: + <<: *python-udf-worker + container_name: python-udf-worker-cn0 + depends_on: + python-udf-worker-image: + condition: service_completed_successfully + networks: + monet: + aliases: + - "python-udf-worker-cn0" + + python-udf-worker-cn1: + <<: *python-udf-worker + container_name: python-udf-worker-cn1 + depends_on: + python-udf-worker-image: + condition: service_completed_successfully + networks: + monet: + aliases: + - "python-udf-worker-cn1" + # --------------------------------------------------------------------- # jstfu: the datastream external table gRPC server (xtool/jstfu), needed # by test/distributed/cases/datastream. The BVT cases address it as diff --git a/etc/launch-tae-compose/config/cn-0.toml b/etc/launch-tae-compose/config/cn-0.toml index 215f9967f8938..0ea0b00c0449d 100644 --- a/etc/launch-tae-compose/config/cn-0.toml +++ b/etc/launch-tae-compose/config/cn-0.toml @@ -66,3 +66,10 @@ enable-write = true enable-delete = true enable-dml = true enable-maintenance = true + +[cn.python-udf-client] +enabled = true +allow-unisolated = true +server-address = "python-udf-worker-cn0:50051" +max-invocation-rows = 1048576 +max-invocation-result-bytes = 268435456 diff --git a/etc/launch-tae-compose/config/cn-1.toml b/etc/launch-tae-compose/config/cn-1.toml index d53336c99a27c..372d105e7869b 100644 --- a/etc/launch-tae-compose/config/cn-1.toml +++ b/etc/launch-tae-compose/config/cn-1.toml @@ -66,3 +66,10 @@ enable-write = true enable-delete = true enable-dml = true enable-maintenance = true + +[cn.python-udf-client] +enabled = true +allow-unisolated = true +server-address = "python-udf-worker-cn1:50051" +max-invocation-rows = 1048576 +max-invocation-result-bytes = 268435456 diff --git a/etc/launch-with-python-udf-server/cn.toml b/etc/launch-with-python-udf-server/cn.toml deleted file mode 100644 index 424dc2b13c7c8..0000000000000 --- a/etc/launch-with-python-udf-server/cn.toml +++ /dev/null @@ -1,12 +0,0 @@ -service-type = "CN" -data-dir = "./mo-data" - -[log] -level = "info" - -[cn] -uuid = "dd1dccb4-4d3c-41f8-b482-5251dc7a41bf" -port-base = 18000 - -[cn.python-udf-client] -server-address = "127.0.0.1:50051" diff --git a/etc/launch-with-python-udf-server/python-udf-server.toml b/etc/launch-with-python-udf-server/python-udf-server.toml deleted file mode 100644 index d1a7b10adb498..0000000000000 --- a/etc/launch-with-python-udf-server/python-udf-server.toml +++ /dev/null @@ -1,6 +0,0 @@ -service-type = "PYTHON_UDF" - -[python-udf-server] -uuid = "dd1dccb4-4d3c-41f8-b482-5251dc7a41b2" -address = "127.0.0.1:50051" -path = "pkg/udf/pythonservice/pyserver" diff --git a/etc/launch-with-python-udf-worker/cn.toml b/etc/launch-with-python-udf-worker/cn.toml new file mode 100644 index 0000000000000..5cd29947a566a --- /dev/null +++ b/etc/launch-with-python-udf-worker/cn.toml @@ -0,0 +1,29 @@ +service-type = "CN" +data-dir = "./mo-data" + +# Opt into the checksum-free DISK-V2 backend. The cluster-wide default remains +# DISK (CRC-framed) for backward compatibility with existing data dirs; this +# config explicitly selects DISK-V2 for a fresh deployment. +[[fileservice]] +name = "LOCAL" +backend = "DISK-V2" +data-dir = "./mo-data/local2" + +[[fileservice]] +name = "SHARED" +backend = "DISK-V2" +data-dir = "./mo-data/shared2" + +[log] +level = "info" + +[cn] +uuid = "dd1dccb4-4d3c-41f8-b482-5251dc7a41bf" +port-base = 18000 + +[cn.python-udf-client] +enabled = true +allow-unisolated = true +server-address = "127.0.0.1:50051" +max-invocation-rows = 1048576 +max-invocation-result-bytes = 268435456 diff --git a/etc/launch-with-python-udf-server/launch.toml b/etc/launch-with-python-udf-worker/launch.toml similarity index 54% rename from etc/launch-with-python-udf-server/launch.toml rename to etc/launch-with-python-udf-worker/launch.toml index 1b75cdaf1d3b1..610a771783707 100644 --- a/etc/launch-with-python-udf-server/launch.toml +++ b/etc/launch-with-python-udf-worker/launch.toml @@ -7,10 +7,9 @@ tnservices = [ ] cnservices = [ - "./etc/launch-with-python-udf-server/cn.toml" + "./etc/launch-with-python-udf-worker/cn.toml" ] python-udf-services = [ - "./etc/launch-with-python-udf-server/python-udf-server.toml" + "./etc/launch-with-python-udf-worker/python-udf-worker.toml" ] - diff --git a/etc/v1/launch-with-python-udf-server/python-udf-server.toml b/etc/launch-with-python-udf-worker/python-udf-worker.toml similarity index 59% rename from etc/v1/launch-with-python-udf-server/python-udf-server.toml rename to etc/launch-with-python-udf-worker/python-udf-worker.toml index d1a7b10adb498..21a661af1af09 100644 --- a/etc/v1/launch-with-python-udf-server/python-udf-server.toml +++ b/etc/launch-with-python-udf-worker/python-udf-worker.toml @@ -1,6 +1,7 @@ service-type = "PYTHON_UDF" -[python-udf-server] +[python-udf-worker] uuid = "dd1dccb4-4d3c-41f8-b482-5251dc7a41b2" address = "127.0.0.1:50051" -path = "pkg/udf/pythonservice/pyserver" +path = "pkg/udf/python/worker" +python = "python3" diff --git a/etc/launch/cn.toml b/etc/launch/cn.toml index f989f16a9bff6..6348ab7e7361d 100644 --- a/etc/launch/cn.toml +++ b/etc/launch/cn.toml @@ -49,3 +49,7 @@ enable-write = true enable-delete = true enable-dml = true enable-maintenance = true + +[cn.python-udf-client] +enabled = false +server-address = "127.0.0.1:50051" diff --git a/etc/launch/launch.toml b/etc/launch/launch.toml index ddc12393f2e9c..08b71744ce4e2 100644 --- a/etc/launch/launch.toml +++ b/etc/launch/launch.toml @@ -9,4 +9,3 @@ tnservices = [ cnservices = [ "./etc/launch/cn.toml" ] - diff --git a/etc/v1/launch-with-python-udf-server/cn.toml b/etc/v1/launch-with-python-udf-server/cn.toml deleted file mode 100644 index 424dc2b13c7c8..0000000000000 --- a/etc/v1/launch-with-python-udf-server/cn.toml +++ /dev/null @@ -1,12 +0,0 @@ -service-type = "CN" -data-dir = "./mo-data" - -[log] -level = "info" - -[cn] -uuid = "dd1dccb4-4d3c-41f8-b482-5251dc7a41bf" -port-base = 18000 - -[cn.python-udf-client] -server-address = "127.0.0.1:50051" diff --git a/etc/v1/launch-with-python-udf-server/launch.toml b/etc/v1/launch-with-python-udf-server/launch.toml deleted file mode 100644 index 64d2458f05442..0000000000000 --- a/etc/v1/launch-with-python-udf-server/launch.toml +++ /dev/null @@ -1,15 +0,0 @@ -logservices = [ - "./etc/v1/launch/log.toml", -] - -tnservices = [ - "./etc/v1/launch/tn.toml" -] - -cnservices = [ - "./etc/v1/launch-with-python-udf-server/cn.toml" -] - -python-udf-services = [ - "./etc/v1/launch-with-python-udf-server/python-udf-server.toml" -] diff --git a/optools/bvt_ut/Dockerfile b/optools/bvt_ut/Dockerfile index 0cacfeda66ab7..f0f32188e2d78 100644 --- a/optools/bvt_ut/Dockerfile +++ b/optools/bvt_ut/Dockerfile @@ -10,6 +10,17 @@ ENV ENABLE_UT="false" RUN go env -w GOPROXY="${GOPROXY}" +# The ordinary launch BVT starts the Python UDF worker together with the +# MatrixOne services. Keep its environment pinned to the same contract used by +# the compose worker image. +RUN apt-get update && \ + apt-get install -y --no-install-recommends python3-pip && \ + rm -rf /var/lib/apt/lists/* + +COPY pkg/udf/python/worker/requirements.txt /tmp/python-udf-requirements.txt +RUN python3 -m pip install --break-system-packages --no-cache-dir --only-binary=:all: \ + -r /tmp/python-udf-requirements.txt + RUN mkdir -p /matrixone-test WORKDIR /matrixone-test diff --git a/optools/bvt_ut/entrypoint.sh b/optools/bvt_ut/entrypoint.sh index d57a599fd34f1..581c5b715de95 100755 --- a/optools/bvt_ut/entrypoint.sh +++ b/optools/bvt_ut/entrypoint.sh @@ -4,18 +4,32 @@ set -euo pipefail SECONDS=0 -# mv log to mount path +# Move logs to the mounted path without masking the original CI failure when +# preparation or compilation stops before one of the normal artifacts exists. function packLog() { - mv /matrixone-test/mo-service.log /matrixone-test/tester-log - mv /matrixone-test/mo-tester/report /matrixone-test/tester-log - mv /root/scratch /matrixone-test/tester-log + local log_dir=/matrixone-test/tester-log + if ! mkdir -p "$log_dir"; then + echo "failed to create $log_dir; preserving the original CI failure" >&2 + return 0 + fi + for artifact in \ + /matrixone-test/mo-service.log \ + /matrixone-test/mo-tester/report \ + /root/scratch; do + if [[ ! -e "$artifact" ]]; then + continue + fi + if ! mv "$artifact" "$log_dir"; then + echo "failed to archive $artifact" >&2 + fi + done duration=$SECONDS echo "$(($duration / 60)) minutes and $(($duration % 60)) seconds elapsed." } function prepare() { - mkdir /root/scratch + mkdir -p /root/scratch echo ">>>>>>>>>>>>>>>>>>>>>>>> show locale" echo `locale` @@ -40,7 +54,11 @@ function run_bvt() { make build echo ">>>>>>>>>>>>>>>>>>>>>>>> start mo service" - ./optools/run_bvt.sh ./ "${LAUNCH}" + # Source the launcher so this entrypoint owns the service children until + # mo-tester finishes. A standalone run_bvt.sh invocation still returns + # with services alive for callers that launch the tester separately. + source ./optools/run_bvt.sh ./ "${LAUNCH}" + trap 'cleanup_all; packLog' EXIT echo ">>>>>>>>>>>>>>>>>>>>>>>> start bvt" # use test/distributed/cases as default test cases @@ -63,4 +81,4 @@ function bvt_ut() { run_bvt } -bvt_ut \ No newline at end of file +bvt_ut diff --git a/optools/compose_bvt/compose_bvt.sh b/optools/compose_bvt/compose_bvt.sh index dce8d7ca4ccb8..b729250898e8d 100755 --- a/optools/compose_bvt/compose_bvt.sh +++ b/optools/compose_bvt/compose_bvt.sh @@ -1,29 +1,56 @@ #!/bin/bash -set -e +set -euo pipefail + +if (( $# < 2 )); then + echo "usage: $0 " >&2 + exit 2 +fi MO_WORKSPACE=$1 COMPOSE_LAUNCH=$2 +COMPOSE_FILE="${MO_WORKSPACE}/etc/launch-tae-compose/compose.yaml" function export_logs() { - cd ${MO_WORKSPACE} - curl http://localhost:12345/debug/pprof/goroutine\?debug=2 -o docker-compose-log/cn-0-dump-stacks - curl http://localhost:22345/debug/pprof/goroutine\?debug=2 -o docker-compose-log/cn-1-dump-stacks + cd -- "${MO_WORKSPACE}" || return 0 + curl --fail --silent --show-error "http://localhost:12345/debug/pprof/goroutine?debug=2" \ + -o docker-compose-log/cn-0-dump-stacks || true + curl --fail --silent --show-error "http://localhost:22345/debug/pprof/goroutine?debug=2" \ + -o docker-compose-log/cn-1-dump-stacks || true +} + +function cleanup_compose() { + # Preserve the tester's exit status while making service teardown + # best-effort. This trap owns every service started by this script, + # including both CN-local Python workers. + set +e + export_logs + docker compose -f "${COMPOSE_FILE}" --profile "${COMPOSE_LAUNCH}" down --remove-orphans } function compose_bvt() { - trap "export_logs" EXIT + trap cleanup_compose EXIT - cd ${MO_WORKSPACE} + cd -- "${MO_WORKSPACE}" - docker compose -f etc/launch-tae-compose/compose.yaml --profile "${COMPOSE_LAUNCH}" up -d --build + docker compose -f "${COMPOSE_FILE}" --profile "${COMPOSE_LAUNCH}" up -d --build docker build -t matrixorigin/compose-tester:local -f optools/compose_bvt/Dockerfile.tester . - docker run -it --name compose-tester --privileged --network launch-tae-compose_monet -v ${MO_WORKSPACE}/docker-compose-log:/test --rm matrixorigin/compose-tester:local - exit 0 + docker run -it --name compose-tester --privileged --network launch-tae-compose_monet \ + -v "${MO_WORKSPACE}/docker-compose-log:/test" --rm matrixorigin/compose-tester:local } #create the dir for export logs -rm -rf ${MO_WORKSPACE}/docker-compose-log && mkdir -p ${MO_WORKSPACE}/docker-compose-log +python3 - "${MO_WORKSPACE}/docker-compose-log" <<'PY' +import pathlib +import shutil +import sys + +target = pathlib.Path(sys.argv[1]).resolve() +if target == target.parent or target == pathlib.Path("/"): + raise SystemExit(f"refusing unsafe log directory: {target}") +shutil.rmtree(target, ignore_errors=True) +target.mkdir(parents=True, exist_ok=True) +PY compose_bvt diff --git a/optools/compose_bvt/entrypoint.sh b/optools/compose_bvt/entrypoint.sh index edff22b51a6f0..797faa5633cd1 100755 --- a/optools/compose_bvt/entrypoint.sh +++ b/optools/compose_bvt/entrypoint.sh @@ -6,7 +6,11 @@ SECONDS=0 # mv log to mount path function packLog() { - mv /mo-tester/report /test/ + if [[ -e /mo-tester/report ]]; then + mv /mo-tester/report /test/ + else + echo "mo-tester did not produce a report; preserving the original test status" >&2 + fi duration=$SECONDS echo "$(($duration / 60)) minutes and $(($duration % 60)) seconds elapsed." diff --git a/optools/images/Dockerfile b/optools/images/Dockerfile index 7dce55c96b564..07e59859da7b7 100644 --- a/optools/images/Dockerfile +++ b/optools/images/Dockerfile @@ -55,10 +55,18 @@ RUN if [ "$TYPECHECK" = "1" ]; then \ FROM matrixorigin/ubuntu:22.04 +# The Python UDF capability contract includes the IANA timezone database +# version. The worker image and the CN image must advertise the same version +# before Python execution is admitted; the minimal MatrixOne runtime image +# does not contain tzdata by default. +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends tzdata \ + && rm -rf /var/lib/apt/lists/* + COPY --from=builder /go/src/github.com/matrixorigin/matrixone/mo-service /mo-service COPY --from=builder /go/src/github.com/matrixorigin/matrixone/etc /etc -COPY --from=builder /go/src/github.com/matrixorigin/matrixone/thirdparties/install/lib/*.so /usr/local/lib -COPY --from=builder /go/src/github.com/matrixorigin/matrixone/cgo/*.so /usr/local/lib +COPY --from=builder /go/src/github.com/matrixorigin/matrixone/thirdparties/install/lib/*.so /usr/local/lib/ +COPY --from=builder /go/src/github.com/matrixorigin/matrixone/cgo/*.so /usr/local/lib/ COPY --from=builder /go/src/github.com/matrixorigin/matrixone/pkg/monlp/tokenizer/dict /usr/local/share/jieba ENV MO_JIEBA_DICT_DIR=/usr/local/share/jieba diff --git a/optools/images/Dockerfile.ci b/optools/images/Dockerfile.ci index 289971ec8fbaa..e0ec9cc331a08 100644 --- a/optools/images/Dockerfile.ci +++ b/optools/images/Dockerfile.ci @@ -65,6 +65,13 @@ COPY --from=builder /go/pkg/mod /go/pkg/mod FROM ${RUNTIME_IMAGE} +# Python UDF admission compares the system IANA database with the worker. +# Keep every runtime assembly path aligned with optools/images/Dockerfile +# and pkg/udf/python/worker/Dockerfile, including shared-build artifacts. +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends tzdata \ + && rm -rf /var/lib/apt/lists/* + COPY --from=builder /go/src/github.com/matrixorigin/matrixone/mo-service /mo-service COPY --from=builder /go/src/github.com/matrixorigin/matrixone/etc /etc COPY --from=builder /go/src/github.com/matrixorigin/matrixone/thirdparties/install/lib/*.so /usr/local/lib diff --git a/optools/images/Dockerfile.prebuilt b/optools/images/Dockerfile.prebuilt index f7d706d8e086c..dd876f57243e9 100644 --- a/optools/images/Dockerfile.prebuilt +++ b/optools/images/Dockerfile.prebuilt @@ -13,6 +13,13 @@ ARG RUNTIME_IMAGE=matrixorigin/ubuntu:22.04 FROM ${RUNTIME_IMAGE} +# Python UDF admission compares the system IANA database with the worker. +# Keep every runtime assembly path aligned with optools/images/Dockerfile +# and pkg/udf/python/worker/Dockerfile, including shared-build artifacts. +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends tzdata \ + && rm -rf /var/lib/apt/lists/* + COPY --chmod=0755 mo-service /mo-service COPY etc /etc COPY lib/*.so /usr/local/lib/ diff --git a/optools/images/pythonserver/Dockerfile b/optools/images/pythonserver/Dockerfile deleted file mode 100644 index f729b5f7718df..0000000000000 --- a/optools/images/pythonserver/Dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -# run from root path for debug: -# docker build -t mo-python-udf-server -f ./optools/images/pythonserver/Dockerfile ./pkg/udf/pythonservice/pyserver/ -# docker run -d --network host mo-python-udf-server - -FROM python:3.9-bookworm - -RUN useradd -m -s /bin/bash mo - -WORKDIR /home/mo - -# only for debug -#RUN cp /etc/apt/sources.list.d/debian.sources /etc/apt/sources.list.d/ali.sources \ -# && sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list.d/ali.sources \ -# && apt-get update \ -# && apt-get install -y vim - -COPY . . - -RUN pip install -r requirements/base.txt -RUN pip install -r requirements/pytorch.txt - -USER mo - -EXPOSE 50051 - -CMD [ "/bin/bash", "-c", "python -u server.py >> server.log 2>&1" ] \ No newline at end of file diff --git a/optools/run_bvt.sh b/optools/run_bvt.sh index 0a46252e8912f..ea243b05d4ed9 100755 --- a/optools/run_bvt.sh +++ b/optools/run_bvt.sh @@ -16,28 +16,188 @@ set -o nounset +if (( $# < 2 )); then + echo "usage: $0 [proxy-args ...]" >&2 + exit 2 +fi + MO_WORKSPACE=$1 LAUNCH=$2 -PROXY=${3:-} +shift 2 +PROXY_ARGS=("$@") +LAUNCH_CONFIG=$LAUNCH +MO_PID="" +JSTFU_PID="" + +function collect_descendants() { + local parent="$1" + local child + for child in $(pgrep -P "$parent" 2>/dev/null || true); do + BVT_CHILD_PIDS+=("$child") + collect_descendants "$child" + done +} + +function cleanup_mo() { + if [[ -z "$MO_PID" ]]; then + return + fi + local pid="$MO_PID" + local -a BVT_CHILD_PIDS=() + collect_descendants "$pid" + if process_is_alive "$MO_PID"; then + kill -TERM "$MO_PID" 2>/dev/null || true + for _ in {1..30}; do + if ! process_is_alive "$MO_PID"; then + break + fi + sleep 1 + done + if process_is_alive "$MO_PID"; then + kill -KILL "$MO_PID" 2>/dev/null || true + fi + fi + if ((${#BVT_CHILD_PIDS[@]} > 0)); then + for child in "${BVT_CHILD_PIDS[@]}"; do + kill -KILL "$child" 2>/dev/null || true + done + fi + wait "$pid" 2>/dev/null || true + MO_PID="" +} + +function cleanup_jstfu() { + if [[ -z "$JSTFU_PID" ]]; then + return + fi + if process_is_alive "$JSTFU_PID"; then + kill -TERM "$JSTFU_PID" 2>/dev/null || true + for _ in {1..15}; do + if ! process_is_alive "$JSTFU_PID"; then + break + fi + sleep 1 + done + if process_is_alive "$JSTFU_PID"; then + kill -KILL "$JSTFU_PID" 2>/dev/null || true + fi + fi + wait "$JSTFU_PID" 2>/dev/null || true + JSTFU_PID="" +} + +function cleanup_all() { + cleanup_jstfu + cleanup_mo +} + +trap 'cleanup_all; exit 130' INT +trap 'cleanup_all; exit 143' TERM function launch_mo() { - cd $MO_WORKSPACE - ./mo-service -debug-http=:12345 -launch ./etc/$LAUNCH/launch.toml $PROXY &>mo-service.log & + cd "$MO_WORKSPACE" + # Ordinary launch BVT remains the single CI entry point, but its Python + # cases opt into the worker-enabled manifest explicitly. The generic + # etc/launch manifest stays safe for users who start mo-service directly. + LAUNCH_CONFIG=$LAUNCH + if [[ "$LAUNCH" == "launch" ]]; then + LAUNCH_CONFIG=launch-with-python-udf-worker + fi + if ((${#PROXY_ARGS[@]} > 0)); then + ./mo-service -debug-http=:12345 -launch "./etc/${LAUNCH_CONFIG}/launch.toml" "${PROXY_ARGS[@]}" &>mo-service.log & + else + ./mo-service -debug-http=:12345 -launch "./etc/${LAUNCH_CONFIG}/launch.toml" &>mo-service.log & + fi + MO_PID=$! } # this will wait mo all system init completed function wait_system_init() { for num in {1..300} do - if MYSQL_PWD=111 mysql -h 127.0.0.1 -P 6001 -u dump -e "show databases;"; then - echo "ok, cost $num seconds" - return 0 + if [[ -z "$MO_PID" ]] || ! process_is_alive "$MO_PID"; then + echo "MatrixOne exited before SQL readiness" >&2 + tail -n 160 "$MO_WORKSPACE/mo-service.log" >&2 || true + return 1 + fi + if MYSQL_PWD=111 mysql --connect-timeout=2 -h 127.0.0.1 -P 6001 -u dump -e "show databases;"; then + if process_is_alive "$MO_PID"; then + echo "ok, cost $num seconds" + return 0 + fi + echo "MatrixOne exited while SQL readiness was being verified" >&2 + tail -n 160 "$MO_WORKSPACE/mo-service.log" >&2 || true + return 1 fi sleep 1 done return 1 } +function process_is_alive() { + local pid="$1" + local state + if ! kill -0 "$pid" 2>/dev/null; then + return 1 + fi + state=$(ps -o stat= -p "$pid" 2>/dev/null || true) + state=${state//[[:space:]]/} + [[ -n "$state" && "$state" != Z* ]] +} + +# MySQL readiness only proves that the CN frontend accepted connections. The +# worker is a separately started service, so Python UDF DDL/execution can still +# race its Flight listener. Keep this in the existing BVT launcher instead of +# adding a second CI job or making every SQL case retry its first call. +function wait_python_udf_worker() { + if [[ "$LAUNCH_CONFIG" != "launch-with-python-udf-worker" ]]; then + return 0 + fi + for num in {1..120} + do + if [[ -n "$MO_PID" ]] && ! process_is_alive "$MO_PID"; then + echo "MatrixOne exited before Python UDF worker became ready" >&2 + tail -n 160 "$MO_WORKSPACE/mo-service.log" >&2 || true + return 1 + fi + if python3 - <<'PY' +import json +import signal + +import pyarrow.flight as flight + + +def _timeout(_signum, _frame): + raise TimeoutError("capability probe timed out") + + +signal.signal(signal.SIGALRM, _timeout) +signal.alarm(2) +try: + client = flight.FlightClient("grpc://127.0.0.1:50051") + reader = client.do_action( + flight.Action("GetPythonCapabilities", b'{"protocol_version":1}') + ) + result = next(iter(reader), None) + if result is None: + raise RuntimeError("empty capability response") + response = json.loads(bytes(result.body)) + if response.get("protocol_version") != 1: + raise RuntimeError("unsupported capability protocol version") +finally: + signal.alarm(0) +PY + then + echo "Python UDF capability handshake is ready, cost $num seconds" + return 0 + fi + sleep 1 + done + echo "Python UDF capability handshake did not become ready on 127.0.0.1:50051" >&2 + tail -n 160 "$MO_WORKSPACE/mo-service.log" >&2 || true + return 1 +} + # Start the jstfu datastream server (xtool/jstfu) that # test/distributed/cases/datastream talks to on 127.0.0.1:4444. In this # launch deployment MO runs on the host, so a host jstfu is reachable from @@ -46,7 +206,7 @@ function wait_system_init() { # the Maven wrapper bootstraps its own Maven, and the pom emits Java 8 # bytecode on any JDK. function launch_jstfu() { - cd $MO_WORKSPACE + cd "$MO_WORKSPACE" if bash -c 'exec 3<>/dev/tcp/127.0.0.1/4444' 2>/dev/null; then echo "jstfu already listening on :4444, skip" return 0 @@ -59,6 +219,7 @@ function launch_jstfu() { } fi nohup ./optools/jstfu_bvt.sh "$MO_WORKSPACE/test/distributed/resources" 127.0.0.1:6001 &>jstfu.log & + JSTFU_PID=$! for _ in {1..30}; do if bash -c 'exec 3<>/dev/tcp/127.0.0.1/4444' 2>/dev/null; then echo "jstfu ready on :4444" @@ -72,6 +233,49 @@ function launch_jstfu() { } launch_mo -launch_jstfu || exit $? -wait_system_init -exit $? +if [[ "${SKIP_JSTFU:-false}" == "true" ]]; then + echo "skip jstfu for this BVT suite" +else + # Keep the command in an if condition. The BVT entrypoint sources this + # file with `set -e`; a bare failing function call would exit before the + # cleanup block below can reclaim the already-started services. + if launch_jstfu; then + : + else + status=$? + cleanup_all + if [[ "${BASH_SOURCE[0]}" != "$0" ]]; then + return "$status" + fi + exit "$status" + fi +fi +if wait_system_init; then + : +else + status=$? + cleanup_all + if [[ "${BASH_SOURCE[0]}" != "$0" ]]; then + return "$status" + fi + exit "$status" +fi +if wait_python_udf_worker; then + : +else + status=$? + cleanup_all + if [[ "${BASH_SOURCE[0]}" != "$0" ]]; then + return "$status" + fi + exit "$status" +fi + +# This script is a launcher: its caller runs mo-tester after this command +# returns. Keep the services alive on a successful return; signal and startup +# failure paths above own cleanup because no caller can use the deployment in +# those cases. +if [[ "${BASH_SOURCE[0]}" != "$0" ]]; then + return 0 +fi +exit 0 diff --git a/optools/run_bvt_group.sh b/optools/run_bvt_group.sh index 1984aac8bfb6b..17566dd4e5bbf 100644 --- a/optools/run_bvt_group.sh +++ b/optools/run_bvt_group.sh @@ -26,22 +26,19 @@ if ! [[ "${group_id}" =~ ^[01]$ ]]; then fi declare -a included_scripts=() -declare -a resource_args=() if [[ -n "${resource_dir}" ]]; then resource_dir=$(cd "${resource_dir}" && pwd) - resource_args=(-s "${resource_dir}") fi while IFS= read -r script_path; do relative_path=${script_path#"${case_root}/"} [[ "${relative_path}" == *optimistic* ]] && continue top_level=${relative_path%%/*} - case "${top_level}" in array|auto_increment|benchmark|dataXtest|ddl|disttae|fake_pk|function|git4data|hint|join|keyword|load_data|mo_cloud|optimizer|pg_cast|plugin|prepare|procedure|query_result|sample|save_query_result|sequence|snapshot|sql_inject|stage|system|system_variable|temporary|tenant|tenxcloud_xx|time_window|union|util|vector|view) assigned_group=0 ;; - analyze|charset_collation|comment|cte|database|distinct|dml|dtype|expression|feature_limit|foreign_key|fulltext|geo|iceberg|log|metadata|operator|pessimistic_transaction|pitr|plan_cache|publication_subscription|qexec|recursive_cte|replace_statement|result_count|security|set|sql_source_type|statement_query_type|subquery|table|task|udf|window|zz_accesscontrol|zz_statement_query_type) + analyze|charset_collation|comment|cte|database|distinct|dml|dtype|expression|feature_limit|foreign_key|fulltext|geo|iceberg|log|metadata|operator|pessimistic_transaction|pitr|plan_cache|publication_subscription|qexec|recursive_cte|replace_statement|result_count|security|set|sql_source_type|statement_query_type|subquery|table|task|udf|udf_python|window|zz_accesscontrol|zz_statement_query_type) assigned_group=1 ;; *) @@ -69,4 +66,8 @@ fi printf '%s\n' "${included_scripts[@]}" cd "${tester_dir}" -./run.sh -n -g -o -p "${case_root}" -i "${include_list}" "${resource_args[@]}" +if [[ -n "${resource_dir}" ]]; then + ./run.sh -n -g -o -p "${case_root}" -i "${include_list}" -s "${resource_dir}" +else + ./run.sh -n -g -o -p "${case_root}" -i "${include_list}" +fi diff --git a/optools/run_ut.sh b/optools/run_ut.sh index 50495017ae1bb..80cf3dbfc3d52 100755 --- a/optools/run_ut.sh +++ b/optools/run_ut.sh @@ -135,6 +135,58 @@ CGO_CFLAGS="-I${BUILD_WKSP}/cgo -I${THIRDPARTIES_INSTALL_DIR}/include" CGO_LDFLAGS="-Wl,-rpath,${THIRDPARTIES_INSTALL_DIR}/lib:${BUILD_WKSP}/cgo -L${THIRDPARTIES_INSTALL_DIR}/lib -L${BUILD_WKSP}/cgo -lmo -lusearch_c -lm" LD_LIBRARY_PATH="${THIRDPARTIES_INSTALL_DIR}/lib:${BUILD_WKSP}/cgo" +PYTHON_UDF_DEPS_DIR="" + +function cleanup_python_udf_dependencies(){ + if [[ -n "${PYTHON_UDF_DEPS_DIR}" ]]; then + rm -rf -- "${PYTHON_UDF_DEPS_DIR}" + PYTHON_UDF_DEPS_DIR="" + fi +} + +# UT starts the real Python UDF worker from the host's python3 executable. +# Keep the fallback dependency installation outside the worktree and clean it +# up even when the run exits through one of the script's signal handlers. +trap cleanup_python_udf_dependencies EXIT + +function prepare_python_udf_dependencies(){ + local python3_bin + python3_bin=$(command -v python3 || true) + if [[ -z "${python3_bin}" ]]; then + logger "ERR" "python3 is required for Python UDF UTs" + return 1 + fi + + if "${python3_bin}" -c 'import pyarrow' >/dev/null 2>&1; then + logger "INF" "Python UDF UT dependencies are already available" + return 0 + fi + + if ! "${python3_bin}" -m pip --version >/dev/null 2>&1; then + logger "ERR" "python3 cannot import pyarrow and its pip module is unavailable" + return 1 + fi + + PYTHON_UDF_DEPS_DIR=$(mktemp -d "${TMPDIR:-/tmp}/matrixone-ut-python.XXXXXX") || { + logger "ERR" "failed to create the temporary Python UDF dependency directory" + return 1 + } + if ! "${python3_bin}" -m pip install \ + --isolated --disable-pip-version-check --no-input --no-cache-dir \ + --only-binary=:all: --target "${PYTHON_UDF_DEPS_DIR}" \ + -r "${BUILD_WKSP}/pkg/udf/python/worker/requirements.txt"; then + logger "ERR" "failed to install Python UDF UT dependencies" + return 1 + fi + + export PYTHONPATH="${PYTHON_UDF_DEPS_DIR}${PYTHONPATH:+:${PYTHONPATH}}" + if ! "${python3_bin}" -c 'import pyarrow' >/dev/null 2>&1; then + logger "ERR" "Python UDF dependency bootstrap completed but pyarrow is still unavailable" + return 1 + fi + logger "INF" "Python UDF UT dependencies installed in ${PYTHON_UDF_DEPS_DIR}" +} + if [[ -n "${MO_CL_CUDA:-}" ]] ; then if [[ ${MO_CL_CUDA} == "1" ]] ; then if [[ -z "${CONDA_PREFIX:-}" ]] ; then @@ -2169,6 +2221,23 @@ function run_tests(){ fi mark_ut_stage "routing" "validate shard and package partition" finish 0 + # The Python UDF package belongs to the light stage. Split shards execute + # only their selected stage groups; preparing a repository-relative + # requirements file in a synthetic heavy-plan harness is both unnecessary + # and invalid because that harness intentionally contains no pkg tree. + if should_run_ut_stage light; then + mark_ut_stage "prepare" "prepare Python UDF dependencies" start + prepare_python_udf_dependencies + local python_udf_dependency_status=$? + mark_ut_stage "prepare" "prepare Python UDF dependencies" finish "${python_udf_dependency_status}" + if (( python_udf_dependency_status != 0 )); then + UT_TEST_STATUS=1 + return 0 + fi + else + logger "INF" "Skip Python UDF dependency preparation for UT_SHARD=${UT_SHARD}" + fi + mark_ut_stage "prepare" "clean go test cache" start logger "INF" "Clean go test cache" local testcache_status=0 diff --git a/optools/ut_holder_test.go b/optools/ut_holder_test.go index f6a77fa6ca871..a6b9bc5f00f6b 100644 --- a/optools/ut_holder_test.go +++ b/optools/ut_holder_test.go @@ -40,7 +40,9 @@ func TestUTAdmissionHolderEvidence(t *testing.T) { if err := os.WriteFile(path, []byte(strings.Join(tt.events, "\n")), 0600); err != nil { t.Fatal(err) } - out, err := exec.Command("python3", "summarize_ut_setup.py", path).CombinedOutput() + cmd := exec.Command("python3", "summarize_ut_setup.py", path) + cmd.Env = pythonStdlibEnvironment() + out, err := cmd.CombinedOutput() if err != nil { t.Fatalf("summary: %v\n%s", err, out) } @@ -54,3 +56,65 @@ func TestUTAdmissionHolderEvidence(t *testing.T) { }) } } + +func TestPythonStdlibEnvironmentUsesConfiguredRuntimeLibraryPath(t *testing.T) { + t.Setenv("pythonLocation", "/python/toolcache") + t.Setenv("LD_LIBRARY_PATH", "/matrixone/cgo") + t.Setenv("PYTHONPATH", "/matrixone/python") + t.Setenv("PYTHONHOME", "/matrixone/python-home") + t.Setenv("PYTHONUSERBASE", "/matrixone/user-site") + t.Setenv("PYTHONSTARTUP", "/matrixone/startup.py") + t.Setenv("PYTHONINSPECT", "1") + t.Setenv("MO_UT_ENV_SENTINEL", "preserved") + + env := pythonStdlibEnvironment() + values := make(map[string]string, len(env)) + for _, entry := range env { + key, value, _ := strings.Cut(entry, "=") + values[key] = value + } + if values["PATH"] == "" { + t.Fatal("sanitized Python environment lost PATH") + } + if got, want := values["MO_UT_ENV_SENTINEL"], "preserved"; got != want { + t.Fatalf("sanitized Python environment changed unrelated variable: got %q, want %q", got, want) + } + if got, want := values["LD_LIBRARY_PATH"], filepath.Join("/python/toolcache", "lib"); got != want { + t.Fatalf("Python runtime loader path = %q, want %q", got, want) + } + for _, forbidden := range []string{ + "PYTHONPATH", "PYTHONHOME", "PYTHONUSERBASE", "PYTHONSTARTUP", "PYTHONINSPECT", + } { + if _, ok := values[forbidden]; ok { + t.Fatalf("Python stdlib helper inherited %q", forbidden) + } + } +} + +func TestPythonStdlibEnvironmentDropsNativeLoaderPathWithoutPythonLocation(t *testing.T) { + t.Setenv("pythonLocation", "") + t.Setenv("LD_LIBRARY_PATH", "/matrixone/cgo") + if got := pythonStdlibEnvironment(); strings.Contains(strings.Join(got, "\n"), "LD_LIBRARY_PATH=") { + t.Fatalf("Python stdlib helper inherited MatrixOne loader path: %q", got) + } +} + +// pythonStdlibEnvironment keeps the configured interpreter's matching runtime +// library available while preventing MatrixOne's native libraries and Python +// import overrides from changing a standard-library-only report parser. +func pythonStdlibEnvironment() []string { + env := make([]string, 0, len(os.Environ())) + for _, entry := range os.Environ() { + key, _, _ := strings.Cut(entry, "=") + switch key { + case "LD_LIBRARY_PATH", "PYTHONHOME", "PYTHONPATH", "PYTHONUSERBASE", "PYTHONSTARTUP", "PYTHONINSPECT": + continue + default: + env = append(env, entry) + } + } + if pythonLocation := os.Getenv("pythonLocation"); pythonLocation != "" { + env = append(env, "LD_LIBRARY_PATH="+filepath.Join(pythonLocation, "lib")) + } + return env +} diff --git a/optools/ut_schedule_test.go b/optools/ut_schedule_test.go index 069850ad1f602..502b6e2a36c1c 100644 --- a/optools/ut_schedule_test.go +++ b/optools/ut_schedule_test.go @@ -101,6 +101,27 @@ func scheduleHarnessWithMockTransform(t *testing.T, script, mock string, transfo if err := os.WriteFile(filepath.Join(dir, "go"), []byte(mock), 0755); err != nil { t.Fatal(err) } + // The scheduler fixture has no repository package tree, so it cannot run + // the real dependency bootstrap. Simulate only the already-prepared + // pyarrow probe and pass every other Python invocation to the host + // interpreter so the existing report/heartbeat helpers keep their coverage. + python3, err := exec.LookPath("python3") + if err != nil { + python3 = "" + } + pythonStub := `#!/bin/bash +if [[ "$#" == 2 && "$1" == -c && "$2" == "import pyarrow" ]]; then + exit 0 +fi +if [[ -n "${MATRIXONE_TEST_REAL_PYTHON3:-}" ]]; then + exec "${MATRIXONE_TEST_REAL_PYTHON3}" "$@" +fi +echo "python3 is unavailable in the scheduler harness" >&2 +exit 127 +` + if err := os.WriteFile(filepath.Join(dir, "python3"), []byte(pythonStub), 0755); err != nil { + t.Fatal(err) + } ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() cmd := exec.CommandContext(ctx, "bash", "-c", script) @@ -108,6 +129,9 @@ func scheduleHarnessWithMockTransform(t *testing.T, script, mock string, transfo cmd.WaitDelay = 3 * time.Second cmd.Dir = dir cmd.Env = append(os.Environ(), "PATH="+dir+string(os.PathListSeparator)+os.Getenv("PATH"), "UT_WORKDIR="+root, "CASE_DIR="+root, "UT_LINK_PARALLEL=0") + if python3 != "" { + cmd.Env = append(cmd.Env, "MATRIXONE_TEST_REAL_PYTHON3="+python3) + } cmd.Env = append(cmd.Env, variables...) out, err := cmd.CombinedOutput() if ctx.Err() != nil { diff --git a/pkg/bootstrap/service_statistics_upgrade_test.go b/pkg/bootstrap/service_statistics_upgrade_test.go index 8ccec6da847ce..f29e4de8cad14 100644 --- a/pkg/bootstrap/service_statistics_upgrade_test.go +++ b/pkg/bootstrap/service_statistics_upgrade_test.go @@ -186,9 +186,13 @@ func TestStatisticsUpgradeOldWorkerCannotCompleteNewTask(t *testing.T) { return executor.Result{AffectedRows: 1}, nil }, txnOp) + // Model the pre-PR 4.0.7 binary explicitly. Its handler had no + // tenant entries, so it could complete the offset-only task without + // running the current Python catalog migrations. + legacy407 := newTestVersionHandler("4.0.7", "4.0.6", versions.Yes, versions.Yes, 0) old := newServiceForTest("", &memLocker{}, clock.NewHLCClock(func() int64 { return 0 }, 0), nil, exec, - func(s *service) { s.handles = append(s.handles, v4_0_7.Handler) }) + func(s *service) { s.handles = append(s.handles, legacy407) }) defer old.stopper.Stop() // Both the worker admission code and this restored 4.0.7 handler are // unchanged from the old binary; no new-worker-only offset check is used. @@ -197,6 +201,11 @@ func TestStatisticsUpgradeOldWorkerCannotCompleteNewTask(t *testing.T) { require.Equal(t, test.oldCanClaim, hasWork) require.Equal(t, test.oldCanClaim, claimed) require.Equal(t, test.oldCanClaim, ready) + wantLegacyCalls := uint64(0) + if test.oldCanClaim { + wantLegacyCalls = 1 + } + require.Equal(t, wantLegacyCalls, legacy407.callHandleTenantUpgrade.Load()) require.Equal(t, legacy, definition) require.Zero(t, creates) diff --git a/pkg/bootstrap/versions/v4_0_7/tenant_upgrade_list.go b/pkg/bootstrap/versions/v4_0_7/tenant_upgrade_list.go index 6ead4552b581c..921df76c80311 100644 --- a/pkg/bootstrap/versions/v4_0_7/tenant_upgrade_list.go +++ b/pkg/bootstrap/versions/v4_0_7/tenant_upgrade_list.go @@ -14,10 +14,146 @@ package v4_0_7 -import "github.com/matrixorigin/matrixone/pkg/bootstrap/versions" +import ( + "fmt" + + "github.com/matrixorigin/matrixone/pkg/bootstrap/versions" + "github.com/matrixorigin/matrixone/pkg/catalog" + "github.com/matrixorigin/matrixone/pkg/common/moerr" + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/defines" + "github.com/matrixorigin/matrixone/pkg/util/executor" +) // The index metadata provenance migration is NOT an entry: the set of tables it alters is // only known at runtime (one metadata table per index, per account), which a fixed UpgSql // cannot express. It runs from HandleTenantUpgrade, the same escape hatch v4_0_6 uses for // upgradeLegacyForeignKeyMetadata. -var tenantUpgEntries = []versions.UpgradeEntry{} +var tenantUpgEntries = []versions.UpgradeEntry{ + addPythonRevisionHeadColumn("active_revision", "bigint unsigned not null default 0"), + addPythonRevisionHeadColumn("namespace_version", "bigint unsigned not null default 0"), + addPythonSignatureColumn("canonical_input_descriptor", fmt.Sprintf("varchar(%d) not null default ''", types.MaxStringSize), "arg_types"), + addPythonSignatureColumn("return_descriptor", fmt.Sprintf("varchar(%d) not null default ''", types.MaxStringSize), "canonical_input_descriptor"), + addPythonSignatureColumn("signature_key_schema_version", "int not null default 0", "return_descriptor"), + addPythonSignatureColumn("signature_fingerprint", "varchar(128) not null default ''", "signature_key_schema_version"), + addPythonSignatureIndex(), + dropLegacyPythonSignatureIndex(), + { + Schema: catalog.MO_CATALOG, + TableName: "mo_function_revisions", + UpgType: versions.CREATE_NEW_TABLE, + UpgSql: fmt.Sprintf(`create table mo_catalog.mo_function_revisions ( + function_id bigint unsigned not null, + revision bigint unsigned not null, + namespace_version bigint unsigned not null, + name varchar(100) not null, + args json not null, + arg_types varchar(%d) not null default '', + rettype varchar(20) not null, + body text not null, + language varchar(20) not null, + definition_schema_version int not null default 0, + abi_contract varchar(64) not null default '', + adapter_version varchar(64) not null default '', + artifact_digest varchar(128) not null default '', + environment_digest varchar(128) not null default '', + sdk_version varchar(64) not null default '', + null_policy varchar(64) not null default '', + volatility varchar(20) not null default 'VOLATILE', + definition_fingerprint varchar(128) not null default '', + created_time timestamp, + security_type varchar(10) not null default 'DEFINER', + primary key(function_id, revision) + )`, types.MaxStringSize), + RequiredProtocolVersion: defines.MORPCVersion48, + CheckFunc: func(txn executor.TxnExecutor, accountID uint32) (bool, error) { + return versions.CheckTableDefinition(txn, accountID, catalog.MO_CATALOG, "mo_function_revisions") + }, + }, +} + +// addPythonSignatureIndex makes the shared function namespace distinguish the +// exact current Python descriptor while preserving the historical logical +// arg_types column for SQL UDFs and catalog readers. +func addPythonSignatureIndex() versions.UpgradeEntry { + return versions.UpgradeEntry{ + Schema: catalog.MO_CATALOG, + TableName: "mo_user_defined_function", + UpgType: versions.ADD_INDEX, + UpgSql: "create unique index name_db_arg_types_descriptor on mo_catalog.mo_user_defined_function(name, db, arg_types, canonical_input_descriptor)", + RequiredProtocolVersion: defines.MORPCVersion48, + CheckFunc: func(txn executor.TxnExecutor, accountID uint32) (bool, error) { + return versions.CheckIndexDefinition( + txn, accountID, catalog.MO_CATALOG, "mo_user_defined_function", "name_db_arg_types_descriptor", + ) + }, + } +} + +func dropLegacyPythonSignatureIndex() versions.UpgradeEntry { + return versions.UpgradeEntry{ + Schema: catalog.MO_CATALOG, + TableName: "mo_user_defined_function", + UpgType: versions.DROP_INDEX, + UpgSql: "alter table mo_catalog.mo_user_defined_function drop index name_db_arg_types", + RequiredProtocolVersion: defines.MORPCVersion48, + CheckFunc: func(txn executor.TxnExecutor, accountID uint32) (bool, error) { + exists, err := versions.CheckIndexDefinition( + txn, accountID, catalog.MO_CATALOG, "mo_user_defined_function", "name_db_arg_types", + ) + return !exists, err + }, + } +} + +func addPythonRevisionHeadColumn(name, definition string) versions.UpgradeEntry { + return versions.UpgradeEntry{ + Schema: catalog.MO_CATALOG, + TableName: "mo_user_defined_function", + UpgType: versions.ADD_COLUMN, + UpgSql: fmt.Sprintf( + "alter table mo_catalog.mo_user_defined_function add column %s %s after function_id", + name, definition, + ), + RequiredProtocolVersion: defines.MORPCVersion48, + CheckFunc: func(txn executor.TxnExecutor, accountID uint32) (bool, error) { + column, err := versions.CheckTableColumn(txn, accountID, catalog.MO_CATALOG, "mo_user_defined_function", name) + if err != nil { + return false, err + } + if !column.IsExits { + return false, nil + } + if column.ColType == "" { + return false, moerr.NewInternalErrorNoCtxf("catalog column %s has no type", name) + } + return true, nil + }, + } +} + +func addPythonSignatureColumn(name, definition, after string) versions.UpgradeEntry { + return versions.UpgradeEntry{ + Schema: catalog.MO_CATALOG, + TableName: "mo_user_defined_function", + UpgType: versions.ADD_COLUMN, + UpgSql: fmt.Sprintf( + "alter table mo_catalog.mo_user_defined_function add column %s %s after %s", + name, definition, after, + ), + RequiredProtocolVersion: defines.MORPCVersion48, + CheckFunc: func(txn executor.TxnExecutor, accountID uint32) (bool, error) { + column, err := versions.CheckTableColumn(txn, accountID, catalog.MO_CATALOG, "mo_user_defined_function", name) + if err != nil { + return false, err + } + if !column.IsExits { + return false, nil + } + if column.ColType == "" { + return false, moerr.NewInternalErrorNoCtxf("catalog column %s has no type", name) + } + return true, nil + }, + } +} diff --git a/pkg/bootstrap/versions/v4_0_7/upgrade_test.go b/pkg/bootstrap/versions/v4_0_7/upgrade_test.go new file mode 100644 index 0000000000000..b65bd179adc80 --- /dev/null +++ b/pkg/bootstrap/versions/v4_0_7/upgrade_test.go @@ -0,0 +1,105 @@ +// Copyright 2026 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 v4_0_7 + +import ( + "strings" + "testing" + + "github.com/matrixorigin/matrixone/pkg/bootstrap/versions" + "github.com/matrixorigin/matrixone/pkg/catalog" + "github.com/matrixorigin/matrixone/pkg/defines" +) + +func TestPythonFunctionRevisionUpgradeContract(t *testing.T) { + metadata := Handler.Metadata() + if metadata.Version != "4.0.7" || metadata.MinUpgradeVersion != "4.0.6" { + t.Fatalf("unexpected version metadata: %+v", metadata) + } + if metadata.UpgradeCluster != versions.Yes || metadata.UpgradeTenant != versions.Yes { + t.Fatalf("4.0.7 must run both cluster and tenant upgrades: %+v", metadata) + } + if metadata.VersionOffset != uint32(len(tenantUpgEntries)) { + t.Fatalf("version offset %d does not match tenant entries %d", metadata.VersionOffset, len(tenantUpgEntries)) + } + if metadata.RequiredProtocolVersion != defines.MORPCVersion61 { + t.Fatalf("unexpected 4.0.7 protocol gate: %v", metadata.RequiredProtocolVersion) + } + + if len(tenantUpgEntries) != 9 { + t.Fatalf("expected six UDF identity columns, index replacement, and one revision table, got %d entries", len(tenantUpgEntries)) + } + for _, name := range []string{ + "active_revision", "namespace_version", "canonical_input_descriptor", + "return_descriptor", "signature_key_schema_version", "signature_fingerprint", + } { + var found bool + for _, entry := range tenantUpgEntries { + if entry.TableName == "mo_user_defined_function" && strings.Contains(strings.ToLower(entry.UpgSql), "add column "+name) { + found = true + if entry.UpgType != versions.ADD_COLUMN || entry.Schema != catalog.MO_CATALOG { + t.Fatalf("unexpected upgrade entry for %s: %+v", name, entry) + } + break + } + } + if !found { + t.Fatalf("missing mo_user_defined_function.%s upgrade", name) + } + } + + var addIndex, dropIndex, revision *versions.UpgradeEntry + for i := range tenantUpgEntries { + entry := &tenantUpgEntries[i] + lower := strings.ToLower(entry.UpgSql) + switch { + case strings.Contains(lower, "name_db_arg_types_descriptor"): + addIndex = entry + case strings.Contains(lower, "drop index name_db_arg_types"): + dropIndex = entry + case entry.TableName == "mo_function_revisions": + revision = entry + } + } + if addIndex == nil || addIndex.UpgType != versions.ADD_INDEX || addIndex.RequiredProtocolVersion != defines.MORPCVersion48 { + t.Fatalf("missing current Python signature index upgrade: %+v", addIndex) + } + if !strings.Contains(strings.ToLower(addIndex.UpgSql), "canonical_input_descriptor") { + t.Fatalf("current Python signature index omits exact descriptor: %s", addIndex.UpgSql) + } + if dropIndex == nil || dropIndex.UpgType != versions.DROP_INDEX || dropIndex.RequiredProtocolVersion != defines.MORPCVersion48 { + t.Fatalf("missing legacy signature index removal: %+v", dropIndex) + } + if revision == nil { + t.Fatal("missing Python revision table upgrade") + } + if revision.Schema != catalog.MO_CATALOG || revision.TableName != "mo_function_revisions" { + t.Fatalf("unexpected revision catalog identity: %+v", revision) + } + if revision.UpgType != versions.CREATE_NEW_TABLE || revision.RequiredProtocolVersion != defines.MORPCVersion48 { + t.Fatalf("unexpected revision catalog upgrade: %+v", revision) + } + lowerDDL := strings.ToLower(revision.UpgSql) + for _, column := range []string{ + "function_id", "revision", "namespace_version", "arg_types", + "definition_schema_version", "abi_contract", "adapter_version", + "artifact_digest", "environment_digest", "sdk_version", "null_policy", + "volatility", "definition_fingerprint", "primary key(function_id, revision)", + } { + if !strings.Contains(lowerDDL, column) { + t.Fatalf("revision catalog DDL missing %q: %s", column, revision.UpgSql) + } + } +} diff --git a/pkg/cnservice/options.go b/pkg/cnservice/options.go index 047edb1924633..3818760d65f2c 100644 --- a/pkg/cnservice/options.go +++ b/pkg/cnservice/options.go @@ -107,7 +107,7 @@ func WithMessageHandle(f func(ctx context.Context, lockService lockservice.LockService, queryClient qclient.QueryClient, hakeeper logservice.CNHAKeeperClient, - udfService udf.Service, + udfService udf.Runtime, cli client.TxnClient, aicm *defines.AutoIncrCacheManager, mAcquirer func() morpc.Message) error) Option { diff --git a/pkg/cnservice/python_runtime.go b/pkg/cnservice/python_runtime.go new file mode 100644 index 0000000000000..9adc8ccd83c35 --- /dev/null +++ b/pkg/cnservice/python_runtime.go @@ -0,0 +1,115 @@ +// Copyright 2026 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 cnservice + +import ( + "context" + + "github.com/matrixorigin/matrixone/pkg/udf/udferr" + "github.com/matrixorigin/matrixone/pkg/util/errutil" + "go.uber.org/zap" + + "github.com/matrixorigin/matrixone/pkg/common/mpool" + "github.com/matrixorigin/matrixone/pkg/container/vector" + "github.com/matrixorigin/matrixone/pkg/fileservice" + "github.com/matrixorigin/matrixone/pkg/udf" + "github.com/matrixorigin/matrixone/pkg/udf/python" +) + +// buildCNRuntime builds the language registry used by the CN. A Python +// initialization failure is kept as a language-scoped unavailable runtime so +// the feature gate remains fail-closed without taking ordinary SQL down with +// it. Config validation still happens before NewService and remains fatal for +// malformed CN configuration. +func buildCNRuntime(cfg python.ClientConfig, fileService fileservice.FileService, logger *zap.Logger) (udf.Runtime, error) { + if !cfg.Enabled { + return udf.NewRuntime() + } + + artifactStore, err := python.NewFileArtifactStore(fileService, python.DefaultMaxArtifactBytes) + if err != nil { + logPythonRuntimeDegraded(logger, err) + return udf.NewRuntime(&unavailablePythonRuntime{cause: err}) + } + runtime, err := python.NewGatewayWithArtifactStore(cfg, artifactStore) + if err != nil { + logPythonRuntimeDegraded(logger, err) + return udf.NewRuntime(&unavailablePythonRuntime{cause: err}) + } + return udf.NewRuntime(runtime) +} + +func logPythonRuntimeDegraded(logger *zap.Logger, err error) { + if logger != nil { + logger.Warn("python udf runtime is unavailable; ordinary SQL remains enabled", zap.Error(err)) + } +} + +// unavailablePythonRuntime preserves a stable language entry in the registry +// after initialization failed. It prevents a caller from mistaking an +// enabled-but-broken feature for a legacy fallback: every Python operation is +// rejected before user code, while StatusSnapshot exposes UNAVAILABLE. +type unavailablePythonRuntime struct { + cause error +} + +var _ udf.Runtime = (*unavailablePythonRuntime)(nil) +var _ udf.RuntimeReadiness = (*unavailablePythonRuntime)(nil) +var _ udf.RuntimeDefinitionValidator = (*unavailablePythonRuntime)(nil) +var _ udf.RuntimeStatusProvider = (*unavailablePythonRuntime)(nil) + +func (r *unavailablePythonRuntime) Language() string { return udf.LanguagePython } + +func (r *unavailablePythonRuntime) unavailableError() error { + if r == nil || r.cause == nil { + return udferr.Newf("RESOURCE_UNAVAILABLE: Python UDF runtime initialization failed") + } + return errutil.Wrapf(r.cause, "RESOURCE_UNAVAILABLE: Python UDF runtime initialization failed") +} + +func (r *unavailablePythonRuntime) Execute(context.Context, *udf.Invocation, vector.FunctionResultWrapper, *mpool.MPool) error { + return r.unavailableError() +} + +func (r *unavailablePythonRuntime) CheckLanguageReady(ctx context.Context, language string) error { + if language != udf.LanguagePython { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: unsupported readiness language %q", language) + } + if ctx != nil { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + } + return r.unavailableError() +} + +func (r *unavailablePythonRuntime) ValidateDefinition(ctx context.Context, definition *udf.RoutineDefinition) error { + if definition == nil || definition.Language != udf.LanguagePython { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: invalid Python definition") + } + return r.CheckLanguageReady(ctx, udf.LanguagePython) +} + +func (r *unavailablePythonRuntime) StatusSnapshot(context.Context, string) udf.RuntimeStatusSnapshot { + return udf.RuntimeStatusSnapshot{ + Language: udf.LanguagePython, + Enabled: true, + Ready: false, + ErrorClass: udf.RuntimeStatusUnavailable, + Reason: udf.RuntimeStatusReasonWorkerUnavailable, + } +} diff --git a/pkg/cnservice/python_runtime_test.go b/pkg/cnservice/python_runtime_test.go new file mode 100644 index 0000000000000..1052bdffd7396 --- /dev/null +++ b/pkg/cnservice/python_runtime_test.go @@ -0,0 +1,134 @@ +// Copyright 2026 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 cnservice + +import ( + "context" + "testing" + + "github.com/matrixorigin/matrixone/pkg/pb/metadata" + "github.com/matrixorigin/matrixone/pkg/pb/query" + "github.com/matrixorigin/matrixone/pkg/udf" + "github.com/matrixorigin/matrixone/pkg/udf/python" + "github.com/stretchr/testify/require" +) + +func TestBuildCNRuntimeDegradesPythonWhenArtifactServiceIsUnavailable(t *testing.T) { + cfg := python.ClientConfig{ + Enabled: true, + AllowUnisolated: true, + ServerAddress: "127.0.0.1:50051", + } + runtime, err := buildCNRuntime(cfg, nil, nil) + require.NoError(t, err) + + readiness, ok := runtime.(udf.RuntimeReadiness) + require.True(t, ok) + require.ErrorContains(t, readiness.CheckLanguageReady(context.Background(), udf.LanguagePython), "RESOURCE_UNAVAILABLE") + + status, ok := runtime.(udf.RuntimeStatusProvider) + require.True(t, ok) + snapshot := status.StatusSnapshot(context.Background(), udf.LanguagePython) + require.True(t, snapshot.Enabled) + require.False(t, snapshot.Ready) + require.Equal(t, udf.RuntimeStatusUnavailable, snapshot.ErrorClass) +} + +func TestBuildCNRuntimeDisabledDoesNotCreatePythonRuntime(t *testing.T) { + runtime, err := buildCNRuntime(python.ClientConfig{}, nil, nil) + require.NoError(t, err) + readiness, ok := runtime.(udf.RuntimeReadiness) + require.True(t, ok) + require.ErrorContains(t, readiness.CheckLanguageReady(context.Background(), udf.LanguagePython), "not enabled") +} + +func TestUnavailablePythonRuntimeRejectsOperationsWithoutAWorker(t *testing.T) { + runtime := &unavailablePythonRuntime{} + require.Equal(t, udf.LanguagePython, runtime.Language()) + require.ErrorContains(t, runtime.Execute( + context.Background(), nil, nil, nil, + ), "Python UDF runtime initialization failed") + require.ErrorContains(t, runtime.CheckLanguageReady(context.Background(), "sql"), "unsupported readiness language") + require.ErrorContains(t, runtime.CheckLanguageReady(context.Background(), udf.LanguagePython), "RESOURCE_UNAVAILABLE") + + canceled, cancel := context.WithCancel(context.Background()) + cancel() + require.ErrorIs(t, runtime.CheckLanguageReady(canceled, udf.LanguagePython), context.Canceled) + require.ErrorContains(t, runtime.ValidateDefinition(context.Background(), nil), "invalid Python definition") + require.ErrorContains(t, runtime.ValidateDefinition(context.Background(), &udf.RoutineDefinition{Language: "sql"}), "invalid Python definition") + require.Equal(t, udf.RuntimeStatusUnavailable, + runtime.StatusSnapshot(context.Background(), "sql").ErrorClass) +} + +type pythonStatusRuntime struct { + udf.Runtime + snapshot udf.RuntimeStatusSnapshot +} + +func (r *pythonStatusRuntime) StatusSnapshot(context.Context, string) udf.RuntimeStatusSnapshot { + return r.snapshot +} + +type pythonRuntimeWithoutStatus struct{ udf.Runtime } + +func TestGetPythonUdfStatusReturnsCNLocalBoundedRuntimeState(t *testing.T) { + status := udf.RuntimeStatusSnapshot{ + Language: udf.LanguagePython, + Enabled: true, + AllowUnisolated: true, + Ready: true, + ProtocolVersion: 1, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + SDKVersion: udf.PythonSDKVersion, + DefinitionSchemaVersion: 1, + PlanContractVersion: 1, + TypeDescriptorContract: "arrow-sql-v1", + TimezoneDatabaseVersion: "2026c", + WindowBatches: 1, + MaxExecutionFrameBytes: 1 << 30, + MaxHandlerProcesses: 8, + MaxAccountHandlerProcesses: 8, + MaxOwnerHandlerProcesses: 4, + LeaseEpoch: 42, + Modes: []string{"SCALAR", "VECTOR"}, + NullPolicies: []string{"CALLED_ON_NULL_INPUT", "RETURNS_NULL_ON_NULL_INPUT"}, + } + s := &service{ + metadata: metadata.CNStore{UUID: "cn-local"}, + udfService: &pythonStatusRuntime{Runtime: &unavailablePythonRuntime{}, snapshot: status}, + } + response := &query.Response{} + require.NoError(t, s.handleGetPythonUdfStatus(context.Background(), nil, response, nil)) + got := response.GetPythonUdfStatus + require.Equal(t, "cn-local", got.CNUUID) + require.Equal(t, udf.LanguagePython, got.Language) + require.True(t, got.Enabled) + require.True(t, got.AllowUnisolated) + require.True(t, got.Ready) + require.Equal(t, int32(1), got.ProtocolVersion) + require.Equal(t, udf.PythonABIContract, got.ABIContract) + require.Equal(t, uint64(42), got.LeaseEpoch) + require.Equal(t, []string{"SCALAR", "VECTOR"}, got.Modes) + require.Equal(t, []string{"CALLED_ON_NULL_INPUT", "RETURNS_NULL_ON_NULL_INPUT"}, got.NullPolicies) + + // The query service has a stable fail-closed status if an older/custom + // Runtime implementation does not provide the bounded status contract. + s.udfService = pythonRuntimeWithoutStatus{} + response = &query.Response{} + require.NoError(t, s.handleGetPythonUdfStatus(context.Background(), nil, response, nil)) + require.Equal(t, udf.RuntimeStatusUnavailable, response.GetPythonUdfStatus.ErrorClass) + require.Equal(t, udf.RuntimeStatusReasonStatusUnavailable, response.GetPythonUdfStatus.Reason) +} diff --git a/pkg/cnservice/server.go b/pkg/cnservice/server.go index 4972d264b965f..ccb3533e75da7 100644 --- a/pkg/cnservice/server.go +++ b/pkg/cnservice/server.go @@ -71,7 +71,6 @@ import ( "github.com/matrixorigin/matrixone/pkg/txn/rpc" "github.com/matrixorigin/matrixone/pkg/txn/trace" "github.com/matrixorigin/matrixone/pkg/udf" - "github.com/matrixorigin/matrixone/pkg/udf/pythonservice" "github.com/matrixorigin/matrixone/pkg/util/address" "github.com/matrixorigin/matrixone/pkg/util/executor" v2 "github.com/matrixorigin/matrixone/pkg/util/metric/v2" @@ -179,7 +178,7 @@ func NewService( lockService lockservice.LockService, queryClient qclient.QueryClient, hakeeper logservice.CNHAKeeperClient, - udfService udf.Service, + udfService udf.Runtime, cli client.TxnClient, aicm *defines.AutoIncrCacheManager, messageAcquirer func() morpc.Message) error { @@ -239,20 +238,14 @@ func NewService( MaxSize: pu.SV.AutoIncrCacheSize, } - // init UdfService - var udfServices []udf.Service - // add python client to handle python udf - if srv.cfg.PythonUdfClient.ServerAddress != "" { - var pc *pythonservice.Client - pc, err = pythonservice.NewClient(srv.cfg.PythonUdfClient) - if err != nil { - panic(err) - } - udfServices = append(udfServices, pc) - } - srv.udfService, err = udf.NewService(udfServices...) + // init UdfService. Python is an opt-in feature and its transport or + // artifact dependencies must not turn an otherwise usable CN into a + // process-wide crash loop. buildCNRuntime keeps the language gate visible + // to CREATE/EXECUTE while ordinary SQL continues with the runtime in an + // explicit UNAVAILABLE state. + srv.udfService, err = buildCNRuntime(srv.cfg.PythonUdfClient, srv.fileService, srv.logger) if err != nil { - panic(err) + return nil, err } srv.CNMemoryThrottler = rscthrottler.NewMemThrottler( @@ -784,6 +777,9 @@ func (s *service) stopRPCs() error { if s.queryClient != nil { err = errors.Join(err, s.queryClient.Close()) } + if closer, ok := s.udfService.(udf.RuntimeCloser); ok { + err = errors.Join(err, closer.Close()) + } if s.timestampWaiter != nil { s.timestampWaiter.Close() } diff --git a/pkg/cnservice/server_query.go b/pkg/cnservice/server_query.go index 5d233ef66f30a..91e17fa9d6e77 100644 --- a/pkg/cnservice/server_query.go +++ b/pkg/cnservice/server_query.go @@ -47,6 +47,7 @@ import ( "github.com/matrixorigin/matrixone/pkg/sql/plan/function/ctl" "github.com/matrixorigin/matrixone/pkg/taskservice" "github.com/matrixorigin/matrixone/pkg/txn/client" + "github.com/matrixorigin/matrixone/pkg/udf" "github.com/matrixorigin/matrixone/pkg/util/fault" "github.com/matrixorigin/matrixone/pkg/vm/engine" "github.com/matrixorigin/matrixone/pkg/vm/engine/disttae" @@ -178,6 +179,7 @@ func (s *service) initQueryCommandHandler() { s.addQueryCommandHandler(query.CmdMethod_ISCPDrainConsumer, s.handleISCPDrainConsumer) s.addQueryCommandHandler(query.CmdMethod_IcebergCacheInvalidate, s.handleIcebergCacheInvalidate) s.addQueryCommandHandler(query.CmdMethod_MongoDBClientRetire, s.handleMongoDBClientRetire) + s.addQueryCommandHandler(query.CmdMethod_GetPythonUdfStatus, s.handleGetPythonUdfStatus) } func (s *service) addQueryCommandHandler( @@ -671,6 +673,50 @@ func (s *service) handleGetPipelineInfo(ctx context.Context, req *query.Request, return nil } +// handleGetPythonUdfStatus exposes the CN-local runtime state to the Operator. +// The runtime provider owns the capability handshake and returns only a +// bounded summary; this handler never accepts source or creates invocation +// state. Returning a status payload for a disabled or mismatched runtime lets +// the Operator fail closed for Python while ordinary CN query traffic remains +// available. +func (s *service) handleGetPythonUdfStatus(ctx context.Context, _ *query.Request, resp *query.Response, _ *morpc.Buffer) error { + status := udf.RuntimeStatusSnapshot{ + Language: udf.LanguagePython, + ErrorClass: udf.RuntimeStatusUnavailable, + Reason: udf.RuntimeStatusReasonStatusUnavailable, + } + if provider, ok := s.udfService.(udf.RuntimeStatusProvider); ok { + status = provider.StatusSnapshot(ctx, udf.LanguagePython) + } + resp.GetPythonUdfStatus = query.GetPythonUdfStatusResponse{ + CNUUID: s.metadata.UUID, + Language: status.Language, + Enabled: status.Enabled, + AllowUnisolated: status.AllowUnisolated, + Ready: status.Ready, + ErrorClass: status.ErrorClass, + Reason: status.Reason, + ProtocolVersion: status.ProtocolVersion, + ABIContract: status.ABIContract, + AdapterVersion: status.AdapterVersion, + SDKVersion: status.SDKVersion, + DefinitionSchemaVersion: status.DefinitionSchemaVersion, + PlanContractVersion: status.PlanContractVersion, + TypeDescriptorContract: status.TypeDescriptorContract, + TimezoneDatabaseVersion: status.TimezoneDatabaseVersion, + WindowBatches: status.WindowBatches, + CumulativeAck: status.CumulativeAck, + MaxExecutionFrameBytes: status.MaxExecutionFrameBytes, + MaxHandlerProcesses: status.MaxHandlerProcesses, + MaxAccountHandlerProcesses: status.MaxAccountHandlerProcesses, + MaxOwnerHandlerProcesses: status.MaxOwnerHandlerProcesses, + LeaseEpoch: status.LeaseEpoch, + Modes: append([]string(nil), status.Modes...), + NullPolicies: append([]string(nil), status.NullPolicies...), + } + return nil +} + func (s *service) handleMigrateConnFrom( ctx context.Context, req *query.Request, resp *query.Response, _ *morpc.Buffer, ) error { diff --git a/pkg/cnservice/server_test.go b/pkg/cnservice/server_test.go index 478fc8e933292..50dd1fc1fda0a 100644 --- a/pkg/cnservice/server_test.go +++ b/pkg/cnservice/server_test.go @@ -403,7 +403,7 @@ func Test_InitServer(t *testing.T) { lockService lockservice.LockService, queryClient qclient.QueryClient, hakeeper logservice.CNHAKeeperClient, - udfService udf.Service, + udfService udf.Runtime, cli client.TxnClient, aicm *defines.AutoIncrCacheManager, mAcquirer func() morpc.Message) error { @@ -1250,7 +1250,7 @@ func TestPipelineAdmissionRejectsRequestAlreadyReadDuringClose(t *testing.T) { lockservice.LockService, qclient.QueryClient, logservice.CNHAKeeperClient, - udf.Service, + udf.Runtime, client.TxnClient, *defines.AutoIncrCacheManager, func() morpc.Message, @@ -1350,7 +1350,7 @@ func TestFragmentedPipelineCacheSurvivesHandlerRelease(t *testing.T) { _ lockservice.LockService, _ qclient.QueryClient, _ logservice.CNHAKeeperClient, - _ udf.Service, + _ udf.Runtime, _ client.TxnClient, _ *defines.AutoIncrCacheManager, _ func() morpc.Message, @@ -1476,7 +1476,7 @@ func TestServiceCloseCancelsAdmittedPipeline(t *testing.T) { _ lockservice.LockService, _ qclient.QueryClient, _ logservice.CNHAKeeperClient, - _ udf.Service, + _ udf.Runtime, _ client.TxnClient, _ *defines.AutoIncrCacheManager, _ func() morpc.Message, diff --git a/pkg/cnservice/types.go b/pkg/cnservice/types.go index d81776f7d5b01..a57f63e1cd1b1 100644 --- a/pkg/cnservice/types.go +++ b/pkg/cnservice/types.go @@ -55,7 +55,7 @@ import ( "github.com/matrixorigin/matrixone/pkg/txn/rpc" "github.com/matrixorigin/matrixone/pkg/txn/trace" "github.com/matrixorigin/matrixone/pkg/udf" - "github.com/matrixorigin/matrixone/pkg/udf/pythonservice" + "github.com/matrixorigin/matrixone/pkg/udf/python" "github.com/matrixorigin/matrixone/pkg/util" "github.com/matrixorigin/matrixone/pkg/util/address" "github.com/matrixorigin/matrixone/pkg/util/executor" @@ -330,7 +330,7 @@ type Config struct { // "working", "draining" and "drained". InitWorkState string `toml:"init-work-state"` - PythonUdfClient pythonservice.ClientConfig `toml:"python-udf-client"` + PythonUdfClient python.ClientConfig `toml:"python-udf-client"` // LogtailUpdateWorkerFactor is the times of CPU number of this node // to start update workers. @@ -503,6 +503,9 @@ func (c *Config) Validate() error { if err := c.Sirius.validate(); err != nil { return err } + if err := c.PythonUdfClient.Validate(); err != nil { + return err + } if !metadata.ValidStateString(c.InitWorkState) { c.InitWorkState = metadata.WorkState_Working.String() @@ -770,7 +773,7 @@ type service struct { lockService lockservice.LockService, queryClient qclient.QueryClient, hakeeper logservice.CNHAKeeperClient, - udfService udf.Service, + udfService udf.Runtime, cli client.TxnClient, aicm *defines.AutoIncrCacheManager, messageAcquirer func() morpc.Message) error @@ -803,7 +806,7 @@ type service struct { queryClient qclient.QueryClient queryWork queryWorkLifecycle // udfService is used to handle non-sql udf - udfService udf.Service + udfService udf.Runtime bootstrapMu sync.RWMutex bootstrapService bootstrap.Service diff --git a/pkg/cnservice/types_test.go b/pkg/cnservice/types_test.go index f4c118a732e27..bc89f062d7aac 100644 --- a/pkg/cnservice/types_test.go +++ b/pkg/cnservice/types_test.go @@ -18,7 +18,9 @@ import ( "testing" "time" + moruntime "github.com/matrixorigin/matrixone/pkg/common/runtime" "github.com/matrixorigin/matrixone/pkg/logservice" + "github.com/matrixorigin/matrixone/pkg/pb/metadata" "github.com/stretchr/testify/require" ) @@ -47,3 +49,27 @@ func TestValidateHeartbeatDurations(t *testing.T) { cfg.HAKeeper.HeatbeatTimeout.Duration = -time.Nanosecond require.ErrorContains(t, cfg.Validate(), "hakeeper heartbeat timeout") } + +func TestValidatePythonUdfClientContract(t *testing.T) { + service := "python-udf-config-" + t.Name() + rt := moruntime.NewRuntime(metadata.ServiceType_CN, service, nil) + moruntime.SetupServiceBasedRuntime(service, rt) + + disabled := Config{UUID: service} + require.NoError(t, disabled.Validate()) + + requiresOptIn := Config{UUID: service} + requiresOptIn.PythonUdfClient.Enabled = true + require.ErrorContains(t, requiresOptIn.Validate(), "allow-unisolated") + + requiresAddress := Config{UUID: service} + requiresAddress.PythonUdfClient.Enabled = true + requiresAddress.PythonUdfClient.AllowUnisolated = true + require.ErrorContains(t, requiresAddress.Validate(), "missing python udf address") + + valid := Config{UUID: service} + valid.PythonUdfClient.Enabled = true + valid.PythonUdfClient.AllowUnisolated = true + valid.PythonUdfClient.ServerAddress = "127.0.0.1:50051" + require.NoError(t, valid.Validate()) +} diff --git a/pkg/config/configuration.go b/pkg/config/configuration.go index 390c5dd26ebcc..f57a5ab606b3a 100644 --- a/pkg/config/configuration.go +++ b/pkg/config/configuration.go @@ -1452,7 +1452,7 @@ type ParameterUnit struct { // QueryClient instance QueryClient qclient.QueryClient - UdfService udf.Service + UdfService udf.Runtime // HAKeeper client, which is used to get connection ID // from HAKeeper currently. diff --git a/pkg/container/vector/functionTools.go b/pkg/container/vector/functionTools.go index c2026d938eed3..88af90eb0d337 100644 --- a/pkg/container/vector/functionTools.go +++ b/pkg/container/vector/functionTools.go @@ -533,6 +533,11 @@ type FunctionResultWrapper interface { SetResultVector(vec *Vector) GetResultVector() *Vector + // ResultLength is the number of logical values produced through the + // FunctionResult append contract. For fixed-width results the vector is + // pre-sized before execution, so Vector.Length alone describes capacity, + // not whether the producer actually populated every row. + ResultLength() int Free() PreExtendAndReset(size int) error } @@ -794,6 +799,16 @@ func (fr *FunctionResult[T]) GetResultVector() *Vector { return fr.vec } +func (fr *FunctionResult[T]) ResultLength() int { + if fr == nil || fr.vec == nil { + return 0 + } + if fr.isVarlena { + return fr.vec.Length() + } + return int(fr.length) +} + func (fr *FunctionResult[T]) ConvertToStrParameter() FunctionParameterWrapper[types.Varlena] { return GenerateFunctionStrParameter(fr.vec) } diff --git a/pkg/embed/config.go b/pkg/embed/config.go index 36ae8c0ebd5e5..258722d101dc6 100644 --- a/pkg/embed/config.go +++ b/pkg/embed/config.go @@ -40,7 +40,7 @@ import ( "github.com/matrixorigin/matrixone/pkg/perfcounter" "github.com/matrixorigin/matrixone/pkg/proxy" "github.com/matrixorigin/matrixone/pkg/tnservice" - "github.com/matrixorigin/matrixone/pkg/udf/pythonservice" + "github.com/matrixorigin/matrixone/pkg/udf/python" "github.com/matrixorigin/matrixone/pkg/util" "github.com/matrixorigin/matrixone/pkg/util/debug/goroutine" tomlutil "github.com/matrixorigin/matrixone/pkg/util/toml" @@ -94,8 +94,8 @@ type ServiceConfig struct { CN cnservice.Config `toml:"cn"` // ProxyConfig is the config of proxy. ProxyConfig proxy.Config `toml:"proxy"` - // PythonUdfServerConfig is the config of python udf server - PythonUdfServerConfig pythonservice.Config `toml:"python-udf-server"` + // PythonUdfWorkerConfig is the config of the Python UDF worker. + PythonUdfWorkerConfig python.Config `toml:"python-udf-worker"` // Observability parameters for the metric/trace Observability config.ObservabilityParameters `toml:"observability"` diff --git a/pkg/frontend/authenticate.go b/pkg/frontend/authenticate.go index 333dd2781bf71..cf33f0dd9d83f 100644 --- a/pkg/frontend/authenticate.go +++ b/pkg/frontend/authenticate.go @@ -30,6 +30,8 @@ import ( "sync/atomic" "time" + "github.com/matrixorigin/matrixone/pkg/util/errutil" + "github.com/tidwall/btree" "golang.org/x/sync/errgroup" @@ -66,6 +68,8 @@ import ( "github.com/matrixorigin/matrixone/pkg/stage" "github.com/matrixorigin/matrixone/pkg/stage/stageutil" "github.com/matrixorigin/matrixone/pkg/taskservice" + "github.com/matrixorigin/matrixone/pkg/udf" + pythonudf "github.com/matrixorigin/matrixone/pkg/udf/python" "github.com/matrixorigin/matrixone/pkg/util/metric/mometric" v2 "github.com/matrixorigin/matrixone/pkg/util/metric/v2" "github.com/matrixorigin/matrixone/pkg/util/sysview" @@ -933,6 +937,7 @@ var ( "mo_role_grant": 0, "mo_role_privs": 0, "mo_user_defined_function": 0, + "mo_function_revisions": 0, "mo_stored_procedure": 0, "mo_mysql_compatibility_mode": 0, "mo_stages": 0, @@ -974,6 +979,7 @@ var ( "mo_role_grant": 0, "mo_role_privs": 0, "mo_user_defined_function": 0, + "mo_function_revisions": 0, "mo_stored_procedure": 0, "mo_mysql_compatibility_mode": 0, catalog.MOAutoIncrTable: 0, @@ -1035,6 +1041,7 @@ var ( MoCatalogMoRoleGrantDDL, MoCatalogMoRolePrivsDDL, MoCatalogMoUserDefinedFunctionDDL, + MoCatalogMoFunctionRevisionDDL, MoCatalogMoMysqlCompatibilityModeDDL, MoCatalogMoSnapshotsDDL, MoCatalogMoPubsDDL, @@ -1087,6 +1094,7 @@ var ( `drop table if exists mo_catalog.mo_role_grant;`, `drop table if exists mo_catalog.mo_role_privs;`, `drop table if exists mo_catalog.mo_user_defined_function;`, + `drop table if exists mo_catalog.mo_function_revisions;`, `drop table if exists mo_catalog.mo_stored_procedure;`, `drop table if exists mo_catalog.mo_stages;`, `drop view if exists mo_catalog.mo_sessions;`, @@ -1136,6 +1144,34 @@ var ( comment) values ('%s','%s', '%s', '%s','%s', '%s');` initMoUserDefinedFunctionFormat = `insert into mo_catalog.mo_user_defined_function( + name, + owner, + args, + arg_types, + canonical_input_descriptor, + return_descriptor, + signature_key_schema_version, + signature_fingerprint, + retType, + body, + language, + db, + definer, + modified_time, + created_time, + type, + security_type, + comment, + character_set_client, + collation_connection, + database_collation, + sql_mode) values ("%s",%d,'%s','%s',"%s","%s",%d,"%s","%s","%s","%s","%s","%s","%s","%s","%s","%s","%s","%s","%s","%s","%s");` + + // SQL UDF creation keeps the pre-Python catalog write shape. During a + // rolling upgrade an ordinary SQL writer may still target a catalog that + // has not received the Python identity columns. Python creation is gated on + // the current catalog contract and uses initMoUserDefinedFunctionFormat. + initMoUserDefinedFunctionSQLFormat = `insert into mo_catalog.mo_user_defined_function( name, owner, args, @@ -1553,7 +1589,22 @@ const ( checkUdfWithDb = `select function_id,body from mo_catalog.mo_user_defined_function where db = "%s" order by function_id;` - checkUdfExistence = `select function_id from mo_catalog.mo_user_defined_function where name = "%s" and db = "%s" and arg_types = %s order by function_id;` + // SQL keeps this query on columns that existed before the Python identity + // fields. That lets ordinary SQL UDF creation continue during a rolling + // catalog upgrade while the Python path uses the current exact-descriptor + // query below after its readiness gate succeeds. + checkUdfExistence = `select function_id, args, language, arg_types from mo_catalog.mo_user_defined_function where name = "%s" and db = "%s" order by function_id;` + checkPythonUdfExistence = `select function_id, args, language, arg_types, canonical_input_descriptor from mo_catalog.mo_user_defined_function where name = "%s" and db = "%s" order by function_id;` + + // These schema probes are the write gate for the current Python catalog + // contract. They deliberately reference every column used by the Python + // writer. COUNT keeps one result row even when the catalog is empty; a + // literal LIMIT 0 is optimized away by BackgroundExec and does not expose a + // result-set schema. A frontend in a rolling upgrade must reject Python + // publication before it creates or changes a routine when the tenant has + // not reached this schema. + pythonUdfCatalogIdentitySchemaCheck = `select count(active_revision), count(namespace_version), count(canonical_input_descriptor), count(return_descriptor), count(signature_key_schema_version), count(signature_fingerprint) from mo_catalog.mo_user_defined_function;` + functionRevisionCatalogSchemaCheck = `select count(function_id), count(revision), count(namespace_version), count(name), count(args), count(arg_types), count(rettype), count(body), count(language), count(definition_schema_version), count(abi_contract), count(adapter_version), count(artifact_digest), count(environment_digest), count(sdk_version), count(null_policy), count(volatility), count(definition_fingerprint), count(created_time), count(security_type) from mo_catalog.mo_function_revisions;` checkStoredProcedureArgs = `select proc_id, args from mo_catalog.mo_stored_procedure where name = "%s" and db = "%s" order by proc_id;` @@ -1597,7 +1648,8 @@ const ( deleteUserFromMoUserGrantFormat = `delete from mo_catalog.mo_user_grant where user_id = %d;` // delete user defined function from mo_user_defined_function - deleteUserDefinedFunctionFormat = `delete from mo_catalog.mo_user_defined_function where function_id = %d;` + deleteUserDefinedFunctionFormat = `delete from mo_catalog.mo_user_defined_function where function_id = %d;` + deleteUserDefinedFunctionRevisionsFormat = `delete from mo_catalog.mo_function_revisions where function_id = %d;` // delete stored procedure from mo_user_defined_function deleteStoredProcedureFormat = `delete from mo_catalog.mo_stored_procedure where proc_id = %d;` @@ -1676,6 +1728,24 @@ var ( } ) +// deleteUserDefinedFunctionRevisionsIfPresent removes the immutable Python +// revisions belonging to a function identity. The revision table was added by +// the current catalog upgrade and is not part of the legacy SQL UDF contract. +// A mixed-version tenant must therefore still be able to drop an ordinary SQL +// UDF while that table is absent. Once the table exists, every error other than +// the explicit missing-table condition is returned so a failed revision +// cleanup cannot be hidden by deleting the identity row. +func deleteUserDefinedFunctionRevisionsIfPresent(ctx context.Context, bh BackgroundExec, functionID int64) error { + err := bh.Exec(ctx, fmt.Sprintf(deleteUserDefinedFunctionRevisionsFormat, functionID)) + if err == nil { + return nil + } + if moerr.IsMoErrCode(err, moerr.ErrNoSuchTable) || strings.Contains(strings.ToLower(err.Error()), "no such table") { + return nil + } + return err +} + func init() { tables := make([]string, 0) for tbl := range predefinedTables { @@ -4917,7 +4987,6 @@ type rmPkg func(path string) error func doDropFunction(ctx context.Context, ses *Session, df *tree.DropFunction, rm rmPkg) (err error) { var sql string var argstr string - var bodyStr string var checkDatabase string var dbName string var dbExists bool @@ -4988,10 +5057,6 @@ func doDropFunction(ctx context.Context, ses *Session, df *tree.DropFunction, rm if err != nil { return err } - bodyStr, err = erArray[0].GetString(ctx, i, 2) - if err != nil { - return err - } argList := make([]*function.Arg, 0) json.Unmarshal([]byte(argstr), &argList) if len(argList) == len(df.Args) { @@ -5006,6 +5071,20 @@ func doDropFunction(ctx context.Context, ses *Session, df *tree.DropFunction, rm if !match { continue } + // The historical args column intentionally stores only logical + // type names. A current Python body carries the exact Arrow + // descriptors, so use those descriptors when selecting an + // overload for DROP. Otherwise two DECIMAL or bounded string + // overloads would be indistinguishable and DROP could remove the + // wrong immutable identity. A non-current body is left on the + // logical path so an old demo can still be explicitly removed. + body, err := erArray[0].GetString(ctx, i, 2) + if err != nil { + return err + } + if !pythonDropSignatureMatches(df.Args, body) { + continue + } handleArgMatch := func() (rtnErr error) { sql = fmt.Sprintf(deleteUserDefinedFunctionFormat, funcId) @@ -5013,11 +5092,10 @@ func doDropFunction(ctx context.Context, ses *Session, df *tree.DropFunction, rm if rtnErr != nil { return rtnErr } - u := &function.NonSqlUdfBody{} - if json.Unmarshal([]byte(bodyStr), u) == nil && u.Import { - rm(u.Body) + rtnErr = deleteUserDefinedFunctionRevisionsIfPresent(ctx, bh, funcId) + if rtnErr != nil { + return rtnErr } - return rtnErr } err = handleArgMatch() @@ -5038,9 +5116,38 @@ func doDropFunction(ctx context.Context, ses *Session, df *tree.DropFunction, rm return moerr.NewNoUDFNoCtx(string(df.Name.Name.ObjectName)) } +// pythonDropSignatureMatches recognizes the current Python catalog body and +// compares its exact Arrow input descriptors with a DROP declaration. A +// body that is not the current Python contract returns true so the caller can +// retain the historical logical matching needed to explicitly remove an old +// demo definition; such a body is never admitted for execution. +func pythonDropSignatureMatches(args tree.FunctionArgs, rawBody string) bool { + body, err := function.DecodePythonRoutineBody(rawBody) + if err != nil { + return true + } + if len(body.ArgTypes) != len(args) { + return false + } + for index, arg := range args { + argDecl, ok := arg.(*tree.FunctionArgDecl) + if !ok || argDecl == nil { + return false + } + typ, err := plan2.GetFunctionTypeFromAst(argDecl.Type) + if err != nil { + return false + } + descriptor, err := function.NewPythonTypeDescriptor(typ) + if err != nil || descriptor != body.ArgTypes[index] { + return false + } + } + return true +} + func doDropFunctionWithDB(ctx context.Context, ses *Session, stmt tree.Statement, rm rmPkg) (err error) { var sql string - var bodyStr string var funcId int64 var erArray []ExecResult var dbName string @@ -5081,11 +5188,6 @@ func doDropFunctionWithDB(ctx context.Context, ses *Session, stmt tree.Statement if err != nil { return err } - bodyStr, err = erArray[0].GetString(ctx, i, 1) - if err != nil { - return err - } - handleArgMatch := func() (rtnErr error) { sql = fmt.Sprintf(deleteUserDefinedFunctionFormat, funcId) @@ -5093,10 +5195,9 @@ func doDropFunctionWithDB(ctx context.Context, ses *Session, stmt tree.Statement if rtnErr != nil { return rtnErr } - - u := &function.NonSqlUdfBody{} - if json.Unmarshal([]byte(bodyStr), u) == nil && u.Import { - rm(u.Body) + rtnErr = deleteUserDefinedFunctionRevisionsIfPresent(ctx, bh, funcId) + if rtnErr != nil { + return rtnErr } return rtnErr @@ -11504,17 +11605,182 @@ func Upload(ses FeSession, execCtx *ExecCtx, localPath string, storageDir string return ioVector.FilePath, nil } +func ensurePythonUdfCatalogReady(ctx context.Context, bh BackgroundExec) error { + probes := []struct { + query string + expectedCols uint64 + }{ + {query: pythonUdfCatalogIdentitySchemaCheck, expectedCols: 6}, + {query: functionRevisionCatalogSchemaCheck, expectedCols: 20}, + } + for _, probe := range probes { + query := probe.query + bh.ClearExecResultSet() + if err := bh.Exec(ctx, query); err != nil { + return moerr.NewNotSupportedNoCtxf( + "Python UDF catalog contract is not ready; upgrade the tenant before creating or replacing Python UDFs: %v", + err, + ) + } + results, err := getResultSet(ctx, bh) + if err != nil { + return moerr.NewNotSupportedNoCtxf( + "Python UDF catalog contract is not ready; catalog probe returned an invalid result: %v", + err, + ) + } + result, resultErr := exactlyOneCatalogRow(ctx, results, "Python UDF catalog schema probe") + if resultErr != nil { + return moerr.NewNotSupportedNoCtxf( + "Python UDF catalog contract is not ready; catalog probe returned an invalid shape: %v", + resultErr, + ) + } + if result.GetColumnCount() != probe.expectedCols { + return moerr.NewNotSupportedNoCtxf( + "Python UDF catalog contract is not ready; catalog probe returned %d columns, expected %d", + result.GetColumnCount(), probe.expectedCols, + ) + } + } + return nil +} + +// functionRevisionCatalogAvailable reports whether the current shared +// revision table can be used by the SQL UDF writer. Ordinary SQL UDFs remain +// writable during a rolling upgrade before v4_0_7 reaches every tenant; once +// the table is present, revision publication is part of the same caller-owned +// transaction as the legacy compatibility row. +func functionRevisionCatalogAvailable(ctx context.Context, bh BackgroundExec) (bool, error) { + bh.ClearExecResultSet() + if err := bh.Exec(ctx, functionRevisionCatalogSchemaCheck); err != nil { + if isMissingCatalogObjectError(err) { + return false, nil + } + return false, err + } + // The aggregate probe must return one row. Anything else indicates a broken + // executor/result contract and must reach the caller; only an explicitly + // missing catalog object is a supported rolling-upgrade path. + results, err := getResultSet(ctx, bh) + if err != nil { + return false, err + } + if _, err := exactlyOneCatalogRow(ctx, results, "function revision catalog schema probe"); err != nil { + return false, err + } + return true, nil +} + +func isMissingCatalogObjectError(err error) bool { + if err == nil { + return false + } + message := strings.ToLower(err.Error()) + return moerr.IsMoErrCode(err, moerr.ErrNoSuchTable) || + strings.Contains(message, "no such table") || + strings.Contains(message, "table does not exist") || + strings.Contains(message, "unknown column") +} + +func ensurePythonUdfRuntimeReady(ctx context.Context, ses *Session) error { + pu := getPuIfPresent(ses.GetService()) + if pu == nil || pu.UdfService == nil { + return moerr.NewNotSupportedNoCtx("Python UDF feature is disabled") + } + readiness, ok := pu.UdfService.(udf.RuntimeReadiness) + if !ok { + return moerr.NewNotSupportedNoCtx("Python UDF runtime does not expose the current contract") + } + if _, ok := pu.UdfService.(udf.RuntimeDefinitionValidator); !ok { + return moerr.NewNotSupportedNoCtx("Python UDF runtime does not expose definition validation") + } + return readiness.CheckLanguageReady(ctx, udf.LanguagePython) +} + +// validatePythonUdfDefinitionAtCreate runs after the immutable artifact has +// been published and before the Catalog transaction writes the new identity +// or revision. The source is transient input to the validator; the Gateway +// resolves the same account-scoped digest before sending it to the worker. +func validatePythonUdfDefinitionAtCreate( + ctx context.Context, + ses *Session, + tenant *TenantInfo, + body function.PythonRoutineBody, +) error { + pu := getPuIfPresent(ses.GetService()) + if pu == nil || pu.UdfService == nil { + return moerr.NewNotSupportedNoCtx("Python UDF feature is disabled") + } + validator, ok := pu.UdfService.(udf.RuntimeDefinitionValidator) + if !ok { + return moerr.NewNotSupportedNoCtx("Python UDF runtime does not expose definition validation") + } + if tenant == nil { + return moerr.NewInvalidInputNoCtx("Python UDF definition validation requires an account") + } + if err := body.Validate(); err != nil { + return moerr.NewInvalidInputNoCtxf("Python UDF definition rejected before publication: %v", err) + } + definitionFingerprint, err := function.PythonRoutineBodyFingerprint(body) + if err != nil { + return moerr.NewInvalidInputNoCtxf("Python UDF definition fingerprint cannot be computed: %v", err) + } + args := make([]types.Type, len(body.ArgTypes)) + for index, descriptor := range body.ArgTypes { + args[index] = descriptor.Type() + } + return validator.ValidateDefinition(ctx, &udf.RoutineDefinition{ + Language: udf.LanguagePython, + AccountID: uint64(tenant.GetTenantID()), + Handler: body.Handler, + Source: body.Source, + Args: args, + ReturnType: body.ReturnType.Type(), + Mode: body.Mode, + NullPolicy: body.NullPolicy, + ABIContract: body.ABIContract, + AdapterVersion: body.AdapterVersion, + SDKVersion: body.SDKVersion, + DefinitionSchemaVersion: body.DefinitionSchemaVersion, + ArtifactDigest: body.ArtifactDigest, + EnvironmentDigest: body.EnvironmentDigest, + DefinitionFingerprint: definitionFingerprint, + }) +} + +// canonicalPythonInputDescriptor is the shared overload key used by the +// catalog lookup and by the immutable revision metadata. Keeping this +// conversion at the create boundary prevents the logical SQL OID list from +// accidentally being used to match width/scale-sensitive Python signatures. +func canonicalPythonInputDescriptor( + args []function.PythonTypeDescriptor, + returnType *function.PythonTypeDescriptor, +) (string, error) { + inputDescriptor, _, _, err := function.PythonSignatureMetadata(args, returnType) + return inputDescriptor, err +} + func InitFunction(ses *Session, execCtx *ExecCtx, tenant *TenantInfo, cf *tree.CreateFunction) (err error) { + isPython := strings.EqualFold(cf.Language, string(tree.PYTHON)) var retTypeStr string var dbName string var dbExists bool var checkExistence string var argsJson []byte - var argsCondition string + var logicalArgTypes string + var exactArgTypes string var fmtctx *tree.FmtCtx var argList []*function.Arg var typeList []string var erArray []ExecResult + var pythonArgTypes []function.PythonTypeDescriptor + var pythonReturnType *function.PythonTypeDescriptor + if isPython { + if err := ensurePythonUdfRuntimeReady(execCtx.reqCtx, ses); err != nil { + return err + } + } // a database must be selected or specified as qualifier when create a function if cf.Name.HasNoNameQualifier() { @@ -11526,38 +11792,28 @@ func InitFunction(ses *Session, execCtx *ExecCtx, tenant *TenantInfo, cf *tree.C dbName = string(cf.Name.Name.SchemaName) } - // Exact function signatures need an exclusion boundary in every deployment - // mode. The catalog unique index documents the identity, but optimistic/SI - // transactions do not acquire FOR UPDATE locks. This private transaction is - // therefore explicitly pessimistic RC, locks the target database row, then - // rechecks and writes the signature before releasing that lock. - bh := ses.GetBackgroundExec(execCtx.reqCtx, &BackgroundExecOption{forcePessimisticRC: true}) - defer bh.Close() - - err = bh.Exec(execCtx.reqCtx, "begin;") - if err != nil { - return err - } - defer func() { - err = finishTxn(execCtx.reqCtx, bh, err) - }() - - // Lock and authenticate the target database before the exact-signature - // read. The lock stays held through persistence and commit. - dbExists, err = lockDatabaseForUDFCreation(execCtx.reqCtx, bh, dbName) - if err != nil { - return err - } - if !dbExists { - return moerr.NewBadDB(execCtx.reqCtx, dbName) - } - - // format return type + // Parse the complete typed definition before opening the Catalog + // transaction. Python validation performs a network round trip to the + // worker; holding the database lock while waiting would make a slow or + // unavailable worker block unrelated DDL. The later transaction still + // locks and rechecks the exact identity before publication. fmtctx = tree.NewFmtCtx(dialect.MYSQL, tree.WithQuoteString(true)) retTypeStr, err = plan2.GetFunctionTypeStrFromAst(cf.ReturnType.Type) if err != nil { return err } + if isPython { + returnType, typeErr := plan2.GetFunctionTypeFromAst(cf.ReturnType.Type) + if typeErr != nil { + return typeErr + } + descriptor, typeErr := function.NewPythonTypeDescriptor(returnType) + if typeErr != nil { + return typeErr + } + pythonReturnType = &descriptor + pythonArgTypes = make([]function.PythonTypeDescriptor, len(cf.Args)) + } // build argmap and marshal as json argList = make([]*function.Arg, len(cf.Args)) @@ -11572,6 +11828,17 @@ func InitFunction(ses *Session, execCtx *ExecCtx, tenant *TenantInfo, cf *tree.C } argList[i].Type = typ typeList[i] = typ + if isPython { + argType, typeErr := plan2.GetFunctionTypeFromAst(cf.Args[i].(*tree.FunctionArgDecl).Type) + if typeErr != nil { + return typeErr + } + descriptor, typeErr := function.NewPythonTypeDescriptor(argType) + if typeErr != nil { + return typeErr + } + pythonArgTypes[i] = descriptor + } } argsJson, err = json.Marshal(argList) if err != nil { @@ -11582,54 +11849,47 @@ func InitFunction(ses *Session, execCtx *ExecCtx, tenant *TenantInfo, cf *tree.C if err != nil { return err } - argsCondition = fmt.Sprintf("'%s'", argTypes) - - // validate duplicate function declaration - bh.ClearExecResultSet() - checkExistence = fmt.Sprintf(checkUdfExistence, string(cf.Name.Name.ObjectName), dbName, argsCondition) - err = bh.Exec(execCtx.reqCtx, checkExistence) - if err != nil { - return err - } - - erArray, err = getResultSet(execCtx.reqCtx, bh) - if err != nil { - return err + logicalArgTypes = argTypes + if isPython { + exactArgTypes, err = canonicalPythonInputDescriptor(pythonArgTypes, pythonReturnType) + if err != nil { + return err + } } - if execResultArrayHasData(erArray) && !cf.Replace { - return moerr.NewUDFAlreadyExistsNoCtx(string(cf.Name.Name.ObjectName)) - } var body string - if cf.Language == string(tree.SQL) { + if !isPython { body = cf.Body } else { if cf.Import { - // check - if cf.Language == string(tree.PYTHON) { - if !strings.HasSuffix(cf.Body, ".py") && - !strings.HasSuffix(cf.Body, ".whl") { - return moerr.NewInvalidInput(execCtx.reqCtx, "file '"+cf.Body+"', only support '*.py', '*.whl'") - } - if strings.HasSuffix(cf.Body, ".whl") { - dotIdx := strings.LastIndex(cf.Handler, ".") - if dotIdx < 1 { - return moerr.NewInvalidInput(execCtx.reqCtx, "handler '"+cf.Handler+"', when you import a *.whl, the handler should be in the format of '.'") - } - } - } - // upload - storageDir := string(cf.Name.Name.ObjectName) + "_" + strings.Join(typeList, "-") + "_" - cf.Body, err = Upload(ses, execCtx, cf.Body, storageDir) - if err != nil { - return err - } - } - - nb := function.NonSqlUdfBody{ - Handler: cf.Handler, - Import: cf.Import, - Body: cf.Body, + return moerr.NewNotSupportedNoCtx("Python artifact import requires the immutable artifact catalog") + } + mode := cf.Mode + if mode == "" { + mode = "SCALAR" + } + nullPolicy := cf.NullPolicy + if nullPolicy == "" { + nullPolicy = udf.NullCallHandler + } + environmentDigest, digestErr := udf.PythonEnvironmentDigest() + if digestErr != nil { + return moerr.NewInvalidInputNoCtxf("Python UDF environment is not available: %v", digestErr) + } + + nb := function.PythonRoutineBody{ + DefinitionSchemaVersion: udf.PythonDefinitionSchemaVersion, + Handler: cf.Handler, + Source: cf.Body, + Mode: mode, + NullPolicy: nullPolicy, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + ArtifactDigest: udf.PythonInlineArtifactDigest(cf.Handler, cf.Body), + EnvironmentDigest: environmentDigest, + SDKVersion: udf.PythonSDKVersion, + ArgTypes: pythonArgTypes, + ReturnType: pythonReturnType, } var byt []byte byt, err = json.Marshal(nb) @@ -11640,6 +11900,29 @@ func InitFunction(ses *Session, execCtx *ExecCtx, tenant *TenantInfo, cf *tree.C // Using strconv.Quote here would preserve backslashes before JSON quotes // in storage and break json.Unmarshal when invoking python UDFs. body = string(byt) + + // Publish and validate the exact immutable artifact before opening the + // Catalog transaction. A failed CREATE/REPLACE therefore cannot expose + // a revision whose source the current worker has not accepted, while a + // failed replacement leaves its previous active revision untouched. + artifactStore, storeErr := pythonudf.NewFileArtifactStore( + getPu(ses.GetService()).FileService, + pythonudf.DefaultMaxArtifactBytes, + ) + if storeErr != nil { + return storeErr + } + if _, err = artifactStore.Publish( + execCtx.reqCtx, + uint64(tenant.GetTenantID()), + cf.Handler, + cf.Body, + ); err != nil { + return err + } + if err = validatePythonUdfDefinitionAtCreate(execCtx.reqCtx, ses, tenant, nb); err != nil { + return err + } } definition := userDefinedFunctionDefinition{ name: string(cf.Name.Name.ObjectName), @@ -11651,11 +11934,67 @@ func InitFunction(ses *Session, execCtx *ExecCtx, tenant *TenantInfo, cf *tree.C sqlMode: sessionSQLModeForParser(ses), dbName: dbName, } - if execResultArrayHasData(erArray) { // replace - id, err := erArray[0].GetInt64(execCtx.reqCtx, 0, 0) - if err != nil { + + // Exact function signatures need an exclusion boundary in every deployment + // mode. The catalog unique index documents the identity, but optimistic/SI + // transactions do not acquire FOR UPDATE locks. This private transaction is + // therefore explicitly pessimistic RC, locks the target database row, then + // rechecks and writes the signature before releasing that lock. + bh := ses.GetBackgroundExec(execCtx.reqCtx, &BackgroundExecOption{forcePessimisticRC: true}) + defer bh.Close() + + err = bh.Exec(execCtx.reqCtx, "begin;") + if err != nil { + return err + } + defer func() { + err = finishTxn(execCtx.reqCtx, bh, err) + }() + if isPython { + if err = ensurePythonUdfCatalogReady(execCtx.reqCtx, bh); err != nil { return err } + } + + // Lock and authenticate the target database before the exact-signature + // read. The lock stays held through persistence and commit. + dbExists, err = lockDatabaseForUDFCreation(execCtx.reqCtx, bh, dbName) + if err != nil { + return err + } + if !dbExists { + return moerr.NewBadDB(execCtx.reqCtx, dbName) + } + + // Validate duplicate function declaration under the same lock used for + // persistence. Python source validation above is intentionally outside this + // transaction, but identity/revision publication remains linearized here. + bh.ClearExecResultSet() + if isPython { + checkExistence = fmt.Sprintf(checkPythonUdfExistence, string(cf.Name.Name.ObjectName), dbName) + } else { + checkExistence = fmt.Sprintf(checkUdfExistence, string(cf.Name.Name.ObjectName), dbName) + } + err = bh.Exec(execCtx.reqCtx, checkExistence) + if err != nil { + return err + } + erArray, err = getResultSet(execCtx.reqCtx, bh) + if err != nil { + return err + } + matchedIDs, err := matchUserDefinedFunctionCandidates(execCtx.reqCtx, erArray, string(cf.Language), logicalArgTypes, exactArgTypes) + if err != nil { + return err + } + if len(matchedIDs) > 1 { + return moerr.NewInvalidInputNoCtxf("function %s has multiple catalog identities for the same signature", string(cf.Name.Name.ObjectName)) + } + if len(matchedIDs) == 1 && !cf.Replace { + return moerr.NewUDFAlreadyExistsNoCtx(string(cf.Name.Name.ObjectName)) + } + if len(matchedIDs) == 1 { // replace + id := matchedIDs[0] return persistUserDefinedFunction( execCtx.reqCtx, bh, tenant, ses.GetTenantInfo().GetDefaultRoleID(), definition, &id, ) @@ -11697,20 +12036,26 @@ func escapeSQLStringForDoubleQuotes(s string) string { // userDefinedFunctionDefinition is the function metadata kept outside // mo_tables. Callers control the transaction that persists it. type userDefinedFunctionDefinition struct { - name string - args string - argTypes string - retType string - body string - lang string - sqlMode string - dbName string -} - -// userDefinedFunctionArgumentTypes is the canonical identity of a function -// overload. Argument names do not participate in function resolution, while -// their ordered types do. Keep the zero-argument identity empty to match the -// legacy json_extract(args, '$[*].type') IS NULL representation. + name string + args string + argTypes string + canonicalInputDescriptor string + returnDescriptor string + signatureKeySchemaVersion int + signatureFingerprint string + retType string + body string + lang string + sqlMode string + dbName string +} + +// userDefinedFunctionArgumentTypes is the historical logical signature key +// shared by ordinary SQL routines and by the compatibility columns of the +// current Python catalog. Python's exact width/scale identity is stored in +// canonical_input_descriptor; this helper deliberately remains limited to +// ordered logical type names. Keep the zero-argument value empty to match the +// historical json_extract(args, '$[*].type') IS NULL representation. func userDefinedFunctionArgumentTypes(argumentTypes []string) (string, error) { if len(argumentTypes) == 0 { return "", nil @@ -11751,6 +12096,165 @@ func userDefinedFunctionArgumentTypesFromJSON(args string) (string, error) { return userDefinedFunctionArgumentTypes(types) } +// matchUserDefinedFunctionCandidates compares the current declaration with +// every same-name routine in the namespace. SQL retains its historical +// logical arg_types key; current Python rows additionally carry the exact +// canonical descriptor. Looking at the full candidate set is necessary now +// that Python width/scale overloads may share one logical OID sequence. +func matchUserDefinedFunctionCandidates( + ctx context.Context, + results []ExecResult, + language, logicalArgTypes, exactArgTypes string, +) ([]int64, error) { + result, err := candidateCatalogResultSet(results, "function catalog candidate lookup") + if err != nil { + return nil, err + } + if result == nil { + return nil, nil + } + if result.GetRowCount() == 0 { + return nil, nil + } + columnCount := result.GetColumnCount() + if columnCount < 4 { + return nil, moerr.NewInvalidInputNoCtx("UNSUPPORTED_ROUTINE_VERSION: malformed function catalog candidate") + } + matched := make([]int64, 0, 1) + for row := uint64(0); row < result.GetRowCount(); row++ { + functionID, err := result.GetInt64(ctx, row, 0) + if err != nil { + return nil, err + } + args, err := result.GetString(ctx, row, 1) + if err != nil { + return nil, err + } + existingLanguage, err := result.GetString(ctx, row, 2) + if err != nil { + return nil, err + } + storedArgTypes, err := result.GetString(ctx, row, 3) + if err != nil { + return nil, err + } + existingLogical := storedArgTypes + if parsed, parseErr := userDefinedFunctionArgumentTypesFromJSON(args); parseErr == nil { + existingLogical = parsed + } else if existingLogical == "" { + return nil, moerr.NewInvalidInputNoCtxf( + "UNSUPPORTED_ROUTINE_VERSION: function %d has malformed argument metadata: %v", functionID, parseErr, + ) + } + + isMatch := false + if strings.EqualFold(language, string(tree.PYTHON)) { + existingCanonical := "" + if columnCount >= 5 { + existingCanonical, err = result.GetString(ctx, row, 4) + if err != nil { + return nil, err + } + } + if strings.EqualFold(existingLanguage, string(tree.PYTHON)) { + if columnCount < 5 || existingCanonical == "" { + return nil, moerr.NewInvalidInputNoCtxf( + "UNSUPPORTED_ROUTINE_VERSION: Python function %d has no exact input descriptor", + functionID, + ) + } + isMatch = existingCanonical == exactArgTypes + } else { + // SQL and Python share the historical logical namespace. The + // exact descriptor is only authoritative for a Python row. + isMatch = existingLogical == logicalArgTypes + } + } else { + // SQL and any unknown language still use the shared logical + // namespace until their own canonical descriptor contract is + // published. + isMatch = existingLogical == logicalArgTypes + } + if isMatch { + matched = append(matched, functionID) + } + } + return matched, nil +} + +func normalizePythonFunctionDefinition(definition userDefinedFunctionDefinition) (userDefinedFunctionDefinition, error) { + body, err := function.DecodePythonRoutineBody(definition.body) + if err != nil { + return userDefinedFunctionDefinition{}, moerr.NewInvalidInputNoCtxf( + "UNSUPPORTED_ROUTINE_VERSION: Python definition rejected before publication: %v", err, + ) + } + canonicalInput, returnDescriptor, signatureFingerprint, err := function.PythonSignatureMetadata(body.ArgTypes, body.ReturnType) + if err != nil { + return userDefinedFunctionDefinition{}, moerr.NewInvalidInputNoCtxf( + "UNSUPPORTED_ROUTINE_VERSION: Python signature rejected before publication: %v", err, + ) + } + if definition.canonicalInputDescriptor != "" && definition.canonicalInputDescriptor != canonicalInput { + return userDefinedFunctionDefinition{}, moerr.NewInvalidInputNoCtx("UNSUPPORTED_ROUTINE_VERSION: Python input descriptor does not match its definition") + } + if definition.returnDescriptor != "" && definition.returnDescriptor != returnDescriptor { + return userDefinedFunctionDefinition{}, moerr.NewInvalidInputNoCtx("UNSUPPORTED_ROUTINE_VERSION: Python return descriptor does not match its definition") + } + if definition.signatureKeySchemaVersion != 0 && definition.signatureKeySchemaVersion != udf.PythonSignatureKeySchemaVersion { + return userDefinedFunctionDefinition{}, moerr.NewInvalidInputNoCtxf( + "UNSUPPORTED_ROUTINE_VERSION: Python signature key schema %d is not supported", definition.signatureKeySchemaVersion, + ) + } + if definition.signatureFingerprint != "" && definition.signatureFingerprint != signatureFingerprint { + return userDefinedFunctionDefinition{}, moerr.NewInvalidInputNoCtx("UNSUPPORTED_ROUTINE_VERSION: Python signature fingerprint does not match its definition") + } + definition.canonicalInputDescriptor = canonicalInput + definition.returnDescriptor = returnDescriptor + definition.signatureKeySchemaVersion = udf.PythonSignatureKeySchemaVersion + definition.signatureFingerprint = signatureFingerprint + // The base catalog keeps the historical logical signature columns while the + // immutable revision keeps the exact Python descriptors. Both are + // execution authority: accepting a caller-supplied args/retType pair that + // disagrees with the typed body would publish an identity whose shared + // overload key and immutable revision describe different functions. That + // malformed row would only be discovered on a later read or plan bind. + logicalArgTypes, err := userDefinedFunctionArgumentTypesFromJSON(definition.args) + if err != nil { + return userDefinedFunctionDefinition{}, moerr.NewInvalidInputNoCtxf( + "UNSUPPORTED_ROUTINE_VERSION: Python logical argument metadata is invalid: %v", err, + ) + } + expectedLogicalTypes := make([]string, len(body.ArgTypes)) + for index, descriptor := range body.ArgTypes { + expectedLogicalTypes[index] = function.PythonCatalogTypeName(descriptor.Type()) + } + expectedLogicalArgTypes, err := userDefinedFunctionArgumentTypes(expectedLogicalTypes) + if err != nil { + return userDefinedFunctionDefinition{}, moerr.NewInvalidInputNoCtxf( + "UNSUPPORTED_ROUTINE_VERSION: Python typed argument metadata is invalid: %v", err, + ) + } + if logicalArgTypes != expectedLogicalArgTypes { + return userDefinedFunctionDefinition{}, moerr.NewInvalidInputNoCtxf( + "UNSUPPORTED_ROUTINE_VERSION: Python catalog arguments %q do not match the typed body %q", + logicalArgTypes, expectedLogicalArgTypes, + ) + } + if !routineRevisionReturnTypeMatches(definition.retType, body.ReturnType.Type().Oid) { + return userDefinedFunctionDefinition{}, moerr.NewInvalidInputNoCtxf( + "UNSUPPORTED_ROUTINE_VERSION: Python catalog return type %q does not match the typed body %q", + definition.retType, body.ReturnType.Type().Oid.String(), + ) + } + // Keep arg_types canonicalized from the typed body. The exact Python + // descriptor belongs in canonical_input_descriptor and in the immutable + // revision row; the shared logical key is derived from the same source so + // SQL readers and Python readers cannot drift. + definition.argTypes = expectedLogicalArgTypes + return definition, nil +} + // persistUserDefinedFunction writes function metadata into the caller-owned // transaction. A non-nil functionID replaces that existing definition. func persistUserDefinedFunction( @@ -11761,22 +12265,423 @@ func persistUserDefinedFunction( definition userDefinedFunctionDefinition, functionID *int64, ) error { - body := escapeSQLStringForDoubleQuotes(definition.body) sqlMode := plan2.EscapeFormat(definition.sqlMode) + securityType := "DEFINER" + if strings.EqualFold(definition.lang, string(tree.PYTHON)) { + // Python handlers run with the caller's execution frame in the current + // contract. They cannot declare DEFINER semantics; keeping this value + // in the shared catalog makes the security decision visible to readers + // and prevents a Python row from inheriting the SQL UDF default. + securityType = "INVOKER" + } + var revisionCatalogReady bool + if !strings.EqualFold(definition.lang, string(tree.PYTHON)) { + var err error + revisionCatalogReady, err = functionRevisionCatalogAvailable(ctx, bh) + if err != nil { + return err + } + } if functionID != nil { - return bh.Exec(ctx, fmt.Sprintf(updateMoUserDefinedFunctionFormat, + previousLanguage, err := readUserDefinedFunctionLanguage(ctx, bh, *functionID) + if err != nil { + return err + } + if previousLanguage == "" || !strings.EqualFold(previousLanguage, definition.lang) { + return moerr.NewInvalidInputNoCtxf( + "UNSUPPORTED_ROUTINE_VERSION: function identity %d cannot change language from %q to %q; use DROP and CREATE", + *functionID, previousLanguage, definition.lang, + ) + } + var previousRevision, previousNamespace uint64 + if strings.EqualFold(definition.lang, string(tree.PYTHON)) { + // Validate the current head and definition before touching the legacy + // compatibility row. A historical Python demo has no immutable + // revision and must be rejected without partially rewriting its body. + var readErr error + previousRevision, previousNamespace, readErr = readPythonRevisionHead(ctx, bh, *functionID) + if readErr != nil { + return readErr + } + if previousRevision == 0 || previousNamespace == 0 { + return moerr.NewInvalidInputNoCtx("UNSUPPORTED_ROUTINE_VERSION: legacy Python definition requires DROP and CREATE") + } + candidate, err := function.DecodePythonRoutineBody(definition.body) + if err != nil { + return moerr.NewInvalidInputNoCtxf("UNSUPPORTED_ROUTINE_VERSION: Python definition rejected before publication: %v", err) + } + previousBody, err := readPythonRevisionBody(ctx, bh, *functionID, previousRevision, previousNamespace) + if err != nil { + return err + } + previous, err := function.DecodePythonRoutineBody(previousBody) + if err != nil { + return moerr.NewInvalidInputNoCtxf("UNSUPPORTED_ROUTINE_VERSION: current Python revision %d is invalid: %v", previousRevision, err) + } + if !samePythonRoutineSignature(previous, candidate) { + return moerr.NewInvalidInputNoCtxf( + "UNSUPPORTED_ROUTINE_VERSION: Python REPLACE cannot change input or return descriptor; use DROP and CREATE", + ) + } + // Compare the immutable candidate signature with the active revision + // before validating the compatibility columns. A REPLACE that changes + // the descriptor must report the stable identity error even when its + // caller-supplied logical args/return fields are stale; otherwise the + // same invalid operation produces a different error depending on which + // catalog projection is checked first. No catalog write has happened + // at this point. + definition, err = normalizePythonFunctionDefinition(definition) + if err != nil { + return err + } + } else if revisionCatalogReady { + var readErr error + previousRevision, previousNamespace, readErr = readFunctionRevisionHead(ctx, bh, *functionID) + if readErr != nil { + return readErr + } + previousReturnType, returnErr := readUserDefinedFunctionReturnType(ctx, bh, *functionID) + if returnErr != nil { + return returnErr + } + if !strings.EqualFold(previousReturnType, definition.retType) { + return moerr.NewInvalidInputNoCtxf( + "SQL REPLACE cannot change return type from %q to %q; use DROP and CREATE", + previousReturnType, definition.retType, + ) + } + } + body := escapeSQLStringForDoubleQuotes(definition.body) + if err := bh.Exec(ctx, fmt.Sprintf(updateMoUserDefinedFunctionFormat, ownerRoleID, definition.args, definition.argTypes, definition.retType, body, definition.lang, - tenant.GetUser(), types.CurrentTimestamp().String2(time.UTC, 0), "FUNCTION", "DEFINER", "", "utf8mb4", "utf8mb4_0900_ai_ci", "utf8mb4_0900_ai_ci", sqlMode, - int32(*functionID))) - } - return bh.Exec(ctx, fmt.Sprintf(initMoUserDefinedFunctionFormat, - definition.name, - ownerRoleID, - definition.args, - definition.argTypes, definition.retType, body, definition.lang, definition.dbName, - tenant.GetUser(), types.CurrentTimestamp().String2(time.UTC, 0), types.CurrentTimestamp().String2(time.UTC, 0), "FUNCTION", "DEFINER", "", "utf8mb4", "utf8mb4_0900_ai_ci", "utf8mb4_0900_ai_ci", sqlMode)) + tenant.GetUser(), types.CurrentTimestamp().String2(time.UTC, 0), "FUNCTION", securityType, "", "utf8mb4", "utf8mb4_0900_ai_ci", "utf8mb4_0900_ai_ci", sqlMode, + int32(*functionID))); err != nil { + return err + } + if strings.EqualFold(definition.lang, string(tree.PYTHON)) { + nextRevision := previousRevision + 1 + nextNamespace := previousNamespace + 1 + if err := insertPythonRevision(ctx, bh, definition, *functionID, nextRevision, nextNamespace); err != nil { + return err + } + return activateFunctionRevision(ctx, bh, *functionID, nextRevision, nextNamespace) + } + if !revisionCatalogReady { + return nil + } + nextRevision := previousRevision + 1 + nextNamespace := previousNamespace + 1 + if previousRevision == 0 || previousNamespace == 0 { + nextRevision = 1 + nextNamespace = 1 + } + if err := insertSQLRevision(ctx, bh, definition, *functionID, nextRevision, nextNamespace); err != nil { + return err + } + return activateFunctionRevision(ctx, bh, *functionID, nextRevision, nextNamespace) + } + if strings.EqualFold(definition.lang, string(tree.PYTHON)) { + // A current Python definition must be valid before the base catalog row + // is created. The caller owns the transaction, but rejecting before the + // first write also keeps direct/background writers from leaving a + // partially published identity when validation fails. + var err error + definition, err = normalizePythonFunctionDefinition(definition) + if err != nil { + return err + } + } + body := escapeSQLStringForDoubleQuotes(definition.body) + created := types.CurrentTimestamp().String2(time.UTC, 0) + var insertSQL string + if strings.EqualFold(definition.lang, string(tree.PYTHON)) { + canonicalInputDescriptor := escapeSQLStringForDoubleQuotes(definition.canonicalInputDescriptor) + returnDescriptor := escapeSQLStringForDoubleQuotes(definition.returnDescriptor) + insertSQL = fmt.Sprintf(initMoUserDefinedFunctionFormat, + definition.name, + ownerRoleID, + definition.args, + definition.argTypes, canonicalInputDescriptor, returnDescriptor, definition.signatureKeySchemaVersion, + definition.signatureFingerprint, definition.retType, body, definition.lang, definition.dbName, + tenant.GetUser(), created, created, "FUNCTION", securityType, "", "utf8mb4", "utf8mb4_0900_ai_ci", "utf8mb4_0900_ai_ci", sqlMode) + } else { + // Keep ordinary SQL UDF creation independent of the Python catalog + // columns until the rolling upgrade has reached every writer. + insertSQL = fmt.Sprintf(initMoUserDefinedFunctionSQLFormat, + definition.name, + ownerRoleID, + definition.args, + definition.argTypes, definition.retType, body, definition.lang, definition.dbName, + tenant.GetUser(), created, created, "FUNCTION", "DEFINER", "", "utf8mb4", "utf8mb4_0900_ai_ci", "utf8mb4_0900_ai_ci", sqlMode) + } + if err := bh.Exec(ctx, insertSQL); err != nil { + return err + } + if strings.EqualFold(definition.lang, string(tree.PYTHON)) { + functionIDValue, err := findPersistedFunctionID(ctx, bh, definition) + if err != nil { + return err + } + if err := insertPythonRevision(ctx, bh, definition, functionIDValue, 1, 1); err != nil { + return err + } + return activateFunctionRevision(ctx, bh, functionIDValue, 1, 1) + } + if !revisionCatalogReady { + return nil + } + functionIDValue, err := findPersistedSQLFunctionID(ctx, bh, definition) + if err != nil { + return err + } + if err := insertSQLRevision(ctx, bh, definition, functionIDValue, 1, 1); err != nil { + return err + } + return activateFunctionRevision(ctx, bh, functionIDValue, 1, 1) +} + +func readUserDefinedFunctionLanguage(ctx context.Context, bh BackgroundExec, functionID int64) (string, error) { + bh.ClearExecResultSet() + if err := bh.Exec(ctx, fmt.Sprintf( + "select language from mo_catalog.mo_user_defined_function where function_id = %d;", + functionID, + )); err != nil { + return "", err + } + rows, err := getResultSet(ctx, bh) + if err != nil { + return "", err + } + row, err := exactlyOneCatalogRow(ctx, rows, fmt.Sprintf("function identity %d while replacing", functionID)) + if err != nil { + return "", err + } + language, err := row.GetString(ctx, 0, 0) + if err != nil { + return "", err + } + return language, nil +} + +func readUserDefinedFunctionReturnType(ctx context.Context, bh BackgroundExec, functionID int64) (string, error) { + bh.ClearExecResultSet() + if err := bh.Exec(ctx, fmt.Sprintf( + "select rettype from mo_catalog.mo_user_defined_function where function_id = %d;", + functionID, + )); err != nil { + return "", err + } + rows, err := getResultSet(ctx, bh) + if err != nil { + return "", err + } + row, err := exactlyOneCatalogRow(ctx, rows, fmt.Sprintf("function identity %d while checking its return type", functionID)) + if err != nil { + return "", err + } + return row.GetString(ctx, 0, 0) +} + +func readPythonRevisionBody(ctx context.Context, bh BackgroundExec, functionID int64, revision, namespace uint64) (string, error) { + bh.ClearExecResultSet() + if err := bh.Exec(ctx, fmt.Sprintf( + "select body from mo_catalog.mo_function_revisions where function_id = %d and revision = %d and namespace_version = %d;", + functionID, revision, namespace, + )); err != nil { + return "", errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: Python revision %d is unavailable", revision) + } + rows, err := getResultSet(ctx, bh) + if err != nil { + return "", err + } + row, err := exactlyOneCatalogRow(ctx, rows, fmt.Sprintf("UNSUPPORTED_ROUTINE_VERSION: Python revision %d", revision)) + if err != nil { + return "", err + } + body, err := row.GetString(ctx, 0, 0) + if err != nil { + return "", err + } + return body, nil +} + +func samePythonRoutineSignature(left, right function.PythonRoutineBody) bool { + if len(left.ArgTypes) != len(right.ArgTypes) { + return false + } + for index := range left.ArgTypes { + if left.ArgTypes[index] != right.ArgTypes[index] { + return false + } + } + return left.ReturnType != nil && right.ReturnType != nil && *left.ReturnType == *right.ReturnType +} + +func readPythonRevisionHead(ctx context.Context, bh BackgroundExec, functionID int64) (uint64, uint64, error) { + bh.ClearExecResultSet() + if err := bh.Exec(ctx, fmt.Sprintf( + "select active_revision, namespace_version from mo_catalog.mo_user_defined_function where function_id = %d;", + functionID, + )); err != nil { + return 0, 0, err + } + rows, err := getResultSet(ctx, bh) + if err != nil { + return 0, 0, err + } + row, err := exactlyOneCatalogRow(ctx, rows, fmt.Sprintf("function identity %d while publishing Python revision", functionID)) + if err != nil { + return 0, 0, err + } + revision, err := row.GetInt64(ctx, 0, 0) + if err != nil { + return 0, 0, err + } + namespace, err := row.GetInt64(ctx, 0, 1) + if err != nil { + return 0, 0, err + } + if revision < 0 || namespace < 0 { + return 0, 0, moerr.NewInvalidInputNoCtxf("function identity %d has invalid Python revision head", functionID) + } + return uint64(revision), uint64(namespace), nil +} + +func findPersistedFunctionID(ctx context.Context, bh BackgroundExec, definition userDefinedFunctionDefinition) (int64, error) { + bh.ClearExecResultSet() + query := fmt.Sprintf( + `select function_id from mo_catalog.mo_user_defined_function where name = "%s" and db = "%s" and canonical_input_descriptor = "%s" and language = '%s' order by function_id desc limit 1;`, + escapeSQLStringForDoubleQuotes(definition.name), + escapeSQLStringForDoubleQuotes(definition.dbName), + escapeSQLStringForDoubleQuotes(definition.canonicalInputDescriptor), + escapeSQLStringForDoubleQuotes(definition.lang), + ) + if err := bh.Exec(ctx, query); err != nil { + return 0, err + } + rows, err := getResultSet(ctx, bh) + if err != nil { + return 0, err + } + row, err := exactlyOneCatalogRow(ctx, rows, "Python function identity after creation") + if err != nil { + return 0, err + } + return row.GetInt64(ctx, 0, 0) +} + +func findPersistedSQLFunctionID(ctx context.Context, bh BackgroundExec, definition userDefinedFunctionDefinition) (int64, error) { + bh.ClearExecResultSet() + query := fmt.Sprintf( + `select function_id from mo_catalog.mo_user_defined_function where name = "%s" and db = "%s" and arg_types = %s and language = '%s' order by function_id desc limit 1;`, + escapeSQLStringForDoubleQuotes(definition.name), + escapeSQLStringForDoubleQuotes(definition.dbName), + quoteSQLStringLiteral(definition.argTypes), + escapeSQLStringForDoubleQuotes(definition.lang), + ) + if err := bh.Exec(ctx, query); err != nil { + return 0, err + } + rows, err := getResultSet(ctx, bh) + if err != nil { + return 0, err + } + row, err := exactlyOneCatalogRow(ctx, rows, "SQL function identity after creation") + if err != nil { + return 0, err + } + return row.GetInt64(ctx, 0, 0) +} + +func insertPythonRevision(ctx context.Context, bh BackgroundExec, definition userDefinedFunctionDefinition, functionID int64, revision, namespace uint64) error { + body, err := function.DecodePythonRoutineBody(definition.body) + if err != nil { + return moerr.NewInvalidInputNoCtxf("UNSUPPORTED_ROUTINE_VERSION: Python definition rejected before publication: %v", err) + } + fingerprint, err := function.PythonRoutineFingerprint(definition.body) + if err != nil { + return err + } + canonicalInput, _, _, err := function.PythonSignatureMetadata(body.ArgTypes, body.ReturnType) + if err != nil { + return moerr.NewInvalidInputNoCtxf("UNSUPPORTED_ROUTINE_VERSION: Python signature rejected before publication: %v", err) + } + if definition.canonicalInputDescriptor != "" && definition.canonicalInputDescriptor != canonicalInput { + return moerr.NewInvalidInputNoCtx("UNSUPPORTED_ROUTINE_VERSION: Python input descriptor does not match its definition") + } + quote := func(value string) string { return escapeSQLStringForDoubleQuotes(value) } + created := types.CurrentTimestamp().String2(time.UTC, 0) + sql := fmt.Sprintf(`insert into mo_catalog.mo_function_revisions( + function_id, revision, namespace_version, name, args, arg_types, rettype, body, + language, definition_schema_version, abi_contract, adapter_version, + artifact_digest, environment_digest, sdk_version, null_policy, volatility, + definition_fingerprint, created_time, security_type) values ( + %d, %d, %d, "%s", "%s", "%s", "%s", "%s", "%s", %d, "%s", "%s", "%s", "%s", "%s", "%s", "VOLATILE", "%s", "%s", "INVOKER");`, + functionID, revision, namespace, quote(definition.name), quote(definition.args), quote(canonicalInput), + quote(definition.retType), quote(definition.body), quote(definition.lang), body.DefinitionSchemaVersion, + quote(body.ABIContract), quote(body.AdapterVersion), quote(body.ArtifactDigest), quote(body.EnvironmentDigest), + quote(body.SDKVersion), quote(body.NullPolicy), quote(fingerprint), created, + ) + return bh.Exec(ctx, sql) +} + +func insertSQLRevision(ctx context.Context, bh BackgroundExec, definition userDefinedFunctionDefinition, functionID int64, revision, namespace uint64) error { + fingerprint, err := function.SQLRoutineFingerprint(definition.body, definition.argTypes, definition.retType) + if err != nil { + return moerr.NewInvalidInputNoCtxf("SQL definition rejected before publication: %v", err) + } + quote := func(value string) string { return escapeSQLStringForDoubleQuotes(value) } + created := types.CurrentTimestamp().String2(time.UTC, 0) + sql := fmt.Sprintf(`insert into mo_catalog.mo_function_revisions( + function_id, revision, namespace_version, name, args, arg_types, rettype, body, + language, definition_schema_version, abi_contract, adapter_version, + artifact_digest, environment_digest, sdk_version, null_policy, volatility, + definition_fingerprint, created_time, security_type) values ( + %d, %d, %d, "%s", "%s", "%s", "%s", "%s", "%s", %d, "", "", "", "", "", "%s", "VOLATILE", "%s", "%s", "DEFINER");`, + functionID, revision, namespace, quote(definition.name), quote(definition.args), + quote(definition.argTypes), quote(definition.retType), quote(definition.body), quote(definition.lang), + udf.SQLDefinitionSchemaVersion, quote(udf.NullCallHandler), quote(fingerprint), created, + ) + return bh.Exec(ctx, sql) +} + +func readFunctionRevisionHead(ctx context.Context, bh BackgroundExec, functionID int64) (uint64, uint64, error) { + bh.ClearExecResultSet() + if err := bh.Exec(ctx, fmt.Sprintf( + "select active_revision, namespace_version from mo_catalog.mo_user_defined_function where function_id = %d;", + functionID, + )); err != nil { + return 0, 0, err + } + rows, err := getResultSet(ctx, bh) + if err != nil { + return 0, 0, err + } + row, err := exactlyOneCatalogRow(ctx, rows, fmt.Sprintf("function identity %d while publishing a revision", functionID)) + if err != nil { + return 0, 0, err + } + revision, err := row.GetInt64(ctx, 0, 0) + if err != nil { + return 0, 0, err + } + namespace, err := row.GetInt64(ctx, 0, 1) + if err != nil { + return 0, 0, err + } + if revision < 0 || namespace < 0 { + return 0, 0, moerr.NewInvalidInputNoCtxf("function identity %d has an invalid revision head", functionID) + } + return uint64(revision), uint64(namespace), nil +} + +func activateFunctionRevision(ctx context.Context, bh BackgroundExec, functionID int64, revision, namespace uint64) error { + return bh.Exec(ctx, fmt.Sprintf( + "update mo_catalog.mo_user_defined_function set active_revision = %d, namespace_version = %d where function_id = %d;", + revision, namespace, functionID, + )) } // storedProcedureDefinition is the procedure metadata kept outside mo_tables. diff --git a/pkg/frontend/authenticate_test.go b/pkg/frontend/authenticate_test.go index 7a8ac420b18ea..43916620a8b0e 100644 --- a/pkg/frontend/authenticate_test.go +++ b/pkg/frontend/authenticate_test.go @@ -9981,6 +9981,30 @@ func Test_doDropFunctionIfExistsWithDifferentOverload(t *testing.T) { } } +func TestDeleteUserDefinedFunctionRevisionsIfPresent(t *testing.T) { + ctx := context.Background() + functionID := int64(91) + deleteSQL := fmt.Sprintf(deleteUserDefinedFunctionRevisionsFormat, functionID) + + t.Run("missing revision table is compatible with legacy SQL UDF drop", func(t *testing.T) { + bh := &backgroundExecTest{} + bh.init() + bh.sql2err[deleteSQL] = moerr.NewNoSuchTableNoCtx("mo_catalog", "mo_function_revisions") + + require.NoError(t, deleteUserDefinedFunctionRevisionsIfPresent(ctx, bh, functionID)) + require.Equal(t, []string{deleteSQL}, bh.executedSQLs) + }) + + t.Run("unexpected cleanup failure is not hidden", func(t *testing.T) { + bh := &backgroundExecTest{} + bh.init() + wantErr := errors.New("revision cleanup failed") + bh.sql2err[deleteSQL] = wantErr + + require.ErrorIs(t, deleteUserDefinedFunctionRevisionsIfPresent(ctx, bh, functionID), wantErr) + }) +} + func Test_doDropRole(t *testing.T) { convey.Convey("drop role succ", t, func() { ctrl := gomock.NewController(t) diff --git a/pkg/frontend/clone.go b/pkg/frontend/clone.go index 617ae66c23da8..0b3d11f271c5f 100644 --- a/pkg/frontend/clone.go +++ b/pkg/frontend/clone.go @@ -1147,6 +1147,22 @@ func handleCloneDatabaseWithSource( if err = validateCloneUserDefinedFunctions(source.userDefinedFuncs); err != nil { return } + for _, definition := range source.userDefinedFuncs { + if !strings.EqualFold(definition.lang, string(tree.PYTHON)) { + continue + } + // Database clone is a new Python publication in the target account. + // Apply the same runtime and catalog gates before creating the target + // database, so a disabled or partially upgraded node cannot leave a + // clone that contains an unrunnable routine. + if err = ensurePythonUdfRuntimeReady(reqCtx, ses); err != nil { + return + } + if err = ensurePythonUdfCatalogReady(reqCtx, bh); err != nil { + return + } + break + } fromAccountID := source.opAccountId if source.snapshot != nil && source.snapshot.Tenant != nil { fromAccountID = source.snapshot.Tenant.TenantID @@ -1387,6 +1403,7 @@ func handleCloneDatabaseWithSource( } if err = restoreCloneDatabaseUserDefinedFunctions( ctx1, bh, routineTenant, source.userDefinedFuncs, stmt.DstDatabase.String(), + getPu(ses.GetService()).FileService, ); err != nil { return } diff --git a/pkg/frontend/clone_database_source.go b/pkg/frontend/clone_database_source.go index c6ed89b3c4e37..9ed047eb11f93 100644 --- a/pkg/frontend/clone_database_source.go +++ b/pkg/frontend/clone_database_source.go @@ -25,12 +25,14 @@ import ( "github.com/matrixorigin/matrixone/pkg/catalog" "github.com/matrixorigin/matrixone/pkg/common/moerr" "github.com/matrixorigin/matrixone/pkg/defines" + "github.com/matrixorigin/matrixone/pkg/fileservice" "github.com/matrixorigin/matrixone/pkg/pb/plan" "github.com/matrixorigin/matrixone/pkg/sql/parsers" "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect" "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect/mysql" "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" "github.com/matrixorigin/matrixone/pkg/sql/plan/function" + pythonudf "github.com/matrixorigin/matrixone/pkg/udf/python" ) type cloneDatabaseSource struct { @@ -659,14 +661,35 @@ func validateCloneUserDefinedFunctions(functions []userDefinedFunctionDefinition continue } - var body function.NonSqlUdfBody - if json.Unmarshal([]byte(definition.body), &body) == nil && body.Import { + var raw map[string]json.RawMessage + if json.Unmarshal([]byte(definition.body), &raw) != nil { + return moerr.NewNotSupportedNoCtxf( + "CREATE DATABASE CLONE with malformed %s function %s is not supported", + definition.lang, + definition.name, + ) + } + var importedBody bool + if value, ok := raw["import"]; ok { + _ = json.Unmarshal(value, &importedBody) + } + if importedBody { return moerr.NewNotSupportedNoCtxf( "CREATE DATABASE CLONE with imported %s function %s is not supported: imported UDF packages are not snapshot-versioned", definition.lang, definition.name, ) } + if strings.EqualFold(definition.lang, string(tree.PYTHON)) { + if _, err := function.DecodePythonRoutineBody(definition.body); err != nil { + return moerr.NewNotSupportedNoCtxf( + "CREATE DATABASE CLONE with unsupported %s function %s is not supported: %v", + definition.lang, + definition.name, + err, + ) + } + } } return nil } @@ -766,11 +789,35 @@ func restoreCloneDatabaseUserDefinedFunctions( tenant *TenantInfo, functions []userDefinedFunctionDefinition, dbName string, + artifactFileServices ...fileservice.FileService, ) error { - for _, function := range functions { - function.dbName = dbName + var artifactStore *pythonudf.FileArtifactStore + if len(artifactFileServices) > 0 && artifactFileServices[0] != nil { + var err error + artifactStore, err = pythonudf.NewFileArtifactStore( + artifactFileServices[0], + pythonudf.DefaultMaxArtifactBytes, + ) + if err != nil { + return err + } + } + for _, definition := range functions { + definition.dbName = dbName + if strings.EqualFold(definition.lang, string(tree.PYTHON)) { + if artifactStore == nil { + return moerr.NewNotSupportedNoCtx("Python artifact store is required to clone a current Python routine") + } + body, err := function.DecodePythonRoutineBody(definition.body) + if err != nil { + return moerr.NewInvalidInputNoCtxf("UNSUPPORTED_ROUTINE_VERSION: Python clone source is invalid: %v", err) + } + if _, err := artifactStore.Publish(ctx, uint64(tenant.GetTenantID()), body.Handler, body.Source); err != nil { + return err + } + } if err := persistUserDefinedFunction( - ctx, bh, tenant, tenant.GetDefaultRoleID(), function, nil, + ctx, bh, tenant, tenant.GetDefaultRoleID(), definition, nil, ); err != nil { return err } diff --git a/pkg/frontend/clone_database_source_test.go b/pkg/frontend/clone_database_source_test.go index 55d78004f6bbc..c7290cb953ef4 100644 --- a/pkg/frontend/clone_database_source_test.go +++ b/pkg/frontend/clone_database_source_test.go @@ -22,7 +22,11 @@ import ( "github.com/golang/mock/gomock" "github.com/matrixorigin/matrixone/pkg/catalog" + "github.com/matrixorigin/matrixone/pkg/container/types" "github.com/matrixorigin/matrixone/pkg/defines" + "github.com/matrixorigin/matrixone/pkg/fileservice" + "github.com/matrixorigin/matrixone/pkg/sql/plan/function" + pythonudf "github.com/matrixorigin/matrixone/pkg/udf/python" "github.com/stretchr/testify/require" mock_frontend "github.com/matrixorigin/matrixone/pkg/frontend/test" @@ -48,6 +52,14 @@ type erroringBackgroundExec struct { err error } +func configureSQLFunctionIdentityLookup(bh *backgroundExecTest, functionID int64) { + bh.beforeExec = func(sql string) { + if strings.HasPrefix(sql, "select function_id from mo_catalog.mo_user_defined_function where name = ") { + bh.sql2result[sql] = newMrsForPasswordOfUser([][]interface{}{{functionID, nil, nil}}) + } + } +} + func (bt *erroringBackgroundExec) Exec(ctx context.Context, sql string) error { if err := bt.backgroundExecTest.Exec(ctx, sql); err != nil { return err @@ -172,7 +184,7 @@ func TestUdfCatalogLookupUsesSnapshot(t *testing.T) { require.NoError(t, err) require.Equal(t, uint32(7), accountID) require.Equal(t, - `select args, body, language, rettype, db, modified_time, sql_mode from mo_catalog.mo_user_defined_function {MO_TS = 42} where name = "f_snapshot" and db = "source_db";`, + `select function_id, args, body, language, rettype, db, modified_time, sql_mode from mo_catalog.mo_user_defined_function {MO_TS = 42} where name = "f_snapshot" and db = "source_db";`, sql, ) @@ -180,11 +192,25 @@ func TestUdfCatalogLookupUsesSnapshot(t *testing.T) { _, err = defines.GetAccountId(queryCtx) require.Error(t, err) require.Equal(t, - `select args, body, language, rettype, db, modified_time, sql_mode from mo_catalog.mo_user_defined_function where name = "f_live" and db = "live_db";`, + `select function_id, args, body, language, rettype, db, modified_time, sql_mode from mo_catalog.mo_user_defined_function where name = "f_live" and db = "live_db";`, sql, ) } +func TestPythonRevisionCatalogLookupUsesSameSnapshotForBothTables(t *testing.T) { + snapshot := &plan.Snapshot{TS: ×tamp.Timestamp{PhysicalTime: 99}} + query := pythonRevisionCatalogSQL(snapshot, 41) + require.Contains(t, query, "from mo_catalog.mo_user_defined_function {MO_TS = 99} f") + require.Contains(t, query, "join mo_catalog.mo_function_revisions {MO_TS = 99} r") + require.Contains(t, query, "r.namespace_version = f.namespace_version") + require.Contains(t, query, "where f.function_id = 41;") + + liveQuery := pythonRevisionCatalogSQL(nil, 41) + require.Contains(t, liveQuery, "from mo_catalog.mo_user_defined_function f") + require.Contains(t, liveQuery, "join mo_catalog.mo_function_revisions r") + require.Contains(t, liveQuery, "r.namespace_version = f.namespace_version") +} + func TestGetCloneDatabaseRoutineInfosRespectsSubscriptionBoundary(t *testing.T) { t.Run("database source collects functions and procedures", func(t *testing.T) { const dbName = "source_db" @@ -295,25 +321,120 @@ func TestRestoreCloneDatabaseUserDefinedFunctions(t *testing.T) { bh := &backgroundExecTest{} bh.init() + bh.sql2result[functionRevisionCatalogSchemaCheck] = emptyCatalogProbeResult(20) + configureSQLFunctionIdentityLookup(bh, 1) require.NoError(t, restoreCloneDatabaseUserDefinedFunctions(ctx, bh, tenant, []userDefinedFunctionDefinition{function}, "target_db")) - require.Len(t, bh.executedSQLs, 1) - require.Contains(t, bh.executedSQLs[0], "insert into mo_catalog.mo_user_defined_function") - require.Contains(t, bh.executedSQLs[0], "\"f_answer\",2") - require.Contains(t, bh.executedSQLs[0], "\"target_db\"") - require.Contains(t, bh.executedSQLs[0], "\"root1\"") + require.Len(t, bh.executedSQLs, 5) + require.Equal(t, functionRevisionCatalogSchemaCheck, bh.executedSQLs[0]) + require.Contains(t, bh.executedSQLs[1], "insert into mo_catalog.mo_user_defined_function") + require.Contains(t, bh.executedSQLs[1], "\"f_answer\",2") + require.Contains(t, bh.executedSQLs[1], "\"target_db\"") + require.Contains(t, bh.executedSQLs[1], "\"root1\"") + require.Contains(t, bh.executedSQLs[2], "select function_id from mo_catalog.mo_user_defined_function") + require.Contains(t, bh.executedSQLs[3], "insert into mo_catalog.mo_function_revisions") + require.Contains(t, bh.executedSQLs[4], "update mo_catalog.mo_user_defined_function set active_revision") // SQL literal quoting is an implementation detail of EscapeFormat; preserve // the behavior under test rather than coupling this regression to its style. - require.Contains(t, bh.executedSQLs[0], "PIPES_AS_CONCAT") + require.Contains(t, bh.executedSQLs[1], "PIPES_AS_CONCAT") require.NotContains(t, bh.executedSQLs, "begin;") failingBase := &backgroundExecTest{} failingBase.init() + failingBase.sql2result[functionRevisionCatalogSchemaCheck] = emptyCatalogProbeResult(20) wantErr := errors.New("function persistence failed") failing := &erroringBackgroundExec{backgroundExecTest: failingBase, err: wantErr} require.ErrorIs(t, restoreCloneDatabaseUserDefinedFunctions(ctx, failing, tenant, []userDefinedFunctionDefinition{function}, "target_db"), wantErr) require.Len(t, failing.executedSQLs, 1) } +func TestValidateCloneUserDefinedFunctionsRejectsInertOrMalformedPython(t *testing.T) { + validPython := pythonCatalogTestBody(t, types.T_int64) + for _, tc := range []struct { + name string + definition userDefinedFunctionDefinition + wantError string + }{ + { + name: "current Python definition is cloneable", + definition: userDefinedFunctionDefinition{name: "f", lang: "python", body: validPython}, + }, + { + name: "old Python demo is rejected", + definition: userDefinedFunctionDefinition{name: "legacy", lang: "python", body: `{"handler":"f","source":"old"}`}, + wantError: "unsupported python function legacy", + }, + { + name: "malformed body is rejected", + definition: userDefinedFunctionDefinition{name: "broken", lang: "python", body: "{"}, + wantError: "malformed python function broken", + }, + { + name: "imported non SQL function is rejected", + definition: userDefinedFunctionDefinition{name: "imported", lang: "python", body: `{"import":true}`}, + wantError: "imported python function imported", + }, + { + name: "SQL definition keeps existing clone behavior", + definition: userDefinedFunctionDefinition{name: "sql_f", lang: "sql", body: "select 1"}, + }, + } { + t.Run(tc.name, func(t *testing.T) { + err := validateCloneUserDefinedFunctions([]userDefinedFunctionDefinition{tc.definition}) + if tc.wantError == "" { + require.NoError(t, err) + } else { + require.ErrorContains(t, err, tc.wantError) + } + }) + } +} + +func TestRestoreCloneDatabasePythonRoutineRepublishesTargetArtifact(t *testing.T) { + ctx := context.Background() + const accountID = uint32(27) + tenant := &TenantInfo{User: "root1", TenantID: accountID, DefaultRoleID: accountAdminRoleID} + body := pythonCatalogTestBody(t, types.T_int64) + decoded, err := function.DecodePythonRoutineBody(body) + require.NoError(t, err) + inputDescriptor, _, _, err := function.PythonSignatureMetadata(decoded.ArgTypes, decoded.ReturnType) + require.NoError(t, err) + definition := userDefinedFunctionDefinition{ + name: "cloned_python", + args: `[{"name":"value","type":"bigint"}]`, + argTypes: `["bigint"]`, + retType: "bigint", + body: body, + lang: "python", + dbName: "source_db", + canonicalInputDescriptor: inputDescriptor, + } + findSQL := `select function_id from mo_catalog.mo_user_defined_function where name = "cloned_python" and db = "target_db" and canonical_input_descriptor = "` + escapeSQLStringForDoubleQuotes(inputDescriptor) + `" and language = 'python' order by function_id desc limit 1;` + background := &backgroundExecTest{} + background.init() + background.sql2result[findSQL] = singleInt64Result("function_id", 97) + fs, err := fileservice.NewMemoryFS(defines.SharedFileServiceName, fileservice.DisabledCacheConfig, nil) + require.NoError(t, err) + + require.NoError(t, restoreCloneDatabaseUserDefinedFunctions( + ctx, background, tenant, []userDefinedFunctionDefinition{definition}, "target_db", fs, + )) + require.Contains(t, background.executedSQLs[0], `"cloned_python"`) + require.Contains(t, background.executedSQLs[0], `"target_db"`) + store, err := pythonudf.NewFileArtifactStore(fs, pythonudf.DefaultMaxArtifactBytes) + require.NoError(t, err) + resolved, err := store.Resolve(ctx, uint64(accountID), decoded.Handler, decoded.ArtifactDigest) + require.NoError(t, err) + require.Equal(t, decoded.Source, resolved) + + withoutStore := &backgroundExecTest{} + withoutStore.init() + err = restoreCloneDatabaseUserDefinedFunctions( + ctx, withoutStore, tenant, []userDefinedFunctionDefinition{definition}, "target_db", + ) + require.ErrorContains(t, err, "artifact store is required") + require.Empty(t, withoutStore.executedSQLs, "a routine must not be persisted before its artifact store is available") +} + func TestRestoreCloneDatabaseStoredProcedures(t *testing.T) { ctx := context.Background() tenant := &TenantInfo{User: "root1", DefaultRoleID: accountAdminRoleID} diff --git a/pkg/frontend/clone_test.go b/pkg/frontend/clone_test.go index 64878230ac9fb..939816f7813f9 100644 --- a/pkg/frontend/clone_test.go +++ b/pkg/frontend/clone_test.go @@ -957,6 +957,8 @@ func TestHandleCloneDatabaseWithSourceRestoresRoutines(t *testing.T) { t.Cleanup(ses.Close) bh := &backgroundExecTest{} bh.init() + bh.sql2result[functionRevisionCatalogSchemaCheck] = emptyCatalogProbeResult(20) + configureSQLFunctionIdentityLookup(bh, 1) checkSQL := getSqlForCheckProcedureExistence("p_answer", "destination") bh.sql2result[checkSQL] = newMrsForPasswordOfUser(nil) @@ -965,11 +967,15 @@ func TestHandleCloneDatabaseWithSourceRestoresRoutines(t *testing.T) { ses, bh, newStatement(), newSource(), ) require.NoError(t, err) - require.Len(t, bh.executedSQLs, 4) + require.Len(t, bh.executedSQLs, 8) require.Equal(t, "create database `destination`", bh.executedSQLs[0]) - require.Contains(t, bh.executedSQLs[1], "insert into mo_catalog.mo_user_defined_function") - require.Equal(t, checkSQL, bh.executedSQLs[2]) - require.Contains(t, bh.executedSQLs[3], "insert into mo_catalog.mo_stored_procedure") + require.Equal(t, functionRevisionCatalogSchemaCheck, bh.executedSQLs[1]) + require.Contains(t, bh.executedSQLs[2], "insert into mo_catalog.mo_user_defined_function") + require.Contains(t, bh.executedSQLs[3], "select function_id from mo_catalog.mo_user_defined_function") + require.Contains(t, bh.executedSQLs[4], "insert into mo_catalog.mo_function_revisions") + require.Contains(t, bh.executedSQLs[5], "update mo_catalog.mo_user_defined_function set active_revision") + require.Equal(t, checkSQL, bh.executedSQLs[6]) + require.Contains(t, bh.executedSQLs[7], "insert into mo_catalog.mo_stored_procedure") }) t.Run("propagates procedure restoration failures", func(t *testing.T) { @@ -978,6 +984,8 @@ func TestHandleCloneDatabaseWithSourceRestoresRoutines(t *testing.T) { t.Cleanup(ses.Close) bh := &backgroundExecTest{} bh.init() + bh.sql2result[functionRevisionCatalogSchemaCheck] = emptyCatalogProbeResult(20) + configureSQLFunctionIdentityLookup(bh, 1) checkSQL := getSqlForCheckProcedureExistence("p_answer", "destination") wantErr := errors.New("procedure lookup failed") bh.sql2err[checkSQL] = wantErr @@ -987,10 +995,14 @@ func TestHandleCloneDatabaseWithSourceRestoresRoutines(t *testing.T) { ses, bh, newStatement(), newSource(), ) require.ErrorIs(t, err, wantErr) - require.Len(t, bh.executedSQLs, 3) + require.Len(t, bh.executedSQLs, 7) require.Equal(t, "create database `destination`", bh.executedSQLs[0]) - require.Contains(t, bh.executedSQLs[1], "insert into mo_catalog.mo_user_defined_function") - require.Equal(t, checkSQL, bh.executedSQLs[2]) + require.Equal(t, functionRevisionCatalogSchemaCheck, bh.executedSQLs[1]) + require.Contains(t, bh.executedSQLs[2], "insert into mo_catalog.mo_user_defined_function") + require.Contains(t, bh.executedSQLs[3], "select function_id from mo_catalog.mo_user_defined_function") + require.Contains(t, bh.executedSQLs[4], "insert into mo_catalog.mo_function_revisions") + require.Contains(t, bh.executedSQLs[5], "update mo_catalog.mo_user_defined_function set active_revision") + require.Equal(t, checkSQL, bh.executedSQLs[6]) }) t.Run("rejects imported functions before target database creation", func(t *testing.T) { diff --git a/pkg/frontend/compiler_context.go b/pkg/frontend/compiler_context.go index a398929b1ef37..df29d59ca9b65 100644 --- a/pkg/frontend/compiler_context.go +++ b/pkg/frontend/compiler_context.go @@ -26,6 +26,9 @@ import ( "sync" "time" + "github.com/matrixorigin/matrixone/pkg/udf/udferr" + "github.com/matrixorigin/matrixone/pkg/util/errutil" + "go.uber.org/zap" "github.com/matrixorigin/matrixone/pkg/catalog" @@ -43,6 +46,7 @@ import ( plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan" "github.com/matrixorigin/matrixone/pkg/sql/plan/function" "github.com/matrixorigin/matrixone/pkg/sql/util" + "github.com/matrixorigin/matrixone/pkg/udf" v2 "github.com/matrixorigin/matrixone/pkg/util/metric/v2" "github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace/statistic" "github.com/matrixorigin/matrixone/pkg/vm/engine" @@ -830,6 +834,7 @@ func (tcc *TxnCompilerContext) ResolveUdf(name string, args []*plan.Expr) (udf * } } + defer pinRoutineCatalogReads(bh)() queryCtx, sql := udfCatalogLookup(ctx, tcc.GetSnapshot(), name, tcc.DefaultDatabase()) bh.ClearExecResultSet() err = bh.Exec(queryCtx, sql) @@ -841,15 +846,25 @@ func (tcc *TxnCompilerContext) ResolveUdf(name string, args []*plan.Expr) (udf * if err != nil { return nil, err } + if len(erArray) > 1 || (len(erArray) == 1 && erArray[0] == nil) { + return nil, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: UDF %s lookup returned %d result sets, expected one or an empty candidate result", name, len(erArray)) + } if execResultArrayHasData(erArray) { fromList := make([]types.Type, len(args)) for i, arg := range args { - fromList[i] = types.Type{ - Oid: types.T(arg.Typ.Id), - Width: arg.Typ.Width, - Scale: arg.Typ.Scale, - } + // Reconstruct the complete SQL type instead of filling only the + // plan-visible fields. Type.Eq includes the physical size, which is + // not serialized in plan.Type but is required for exact Python ABI + // matching. In particular, a vector type built with Size == 0 is + // rejected against the declared VECF32/VECF64 descriptor because its + // fixed child width is no longer comparable. + fromList[i] = types.NewWithCharset( + types.T(arg.Typ.Id), + arg.Typ.Width, + arg.Typ.Scale, + uint8(arg.Typ.Charset), + ) argTypeStr += strings.ToLower(fromList[i].String()) if i+1 != len(args) { @@ -866,38 +881,75 @@ func (tcc *TxnCompilerContext) ResolveUdf(name string, args []*plan.Expr) (udf * matchedList := make([]*MatchUdf, 0) for i := uint64(0); i < erArray[0].GetRowCount(); i++ { - argstr, err = erArray[0].GetString(ctx, i, 0) + functionID, getErr := erArray[0].GetInt64(ctx, i, 0) + if getErr != nil { + return nil, getErr + } + argstr, err = erArray[0].GetString(ctx, i, 1) if err != nil { return nil, err } udf = &function.Udf{} - udf.Body, err = erArray[0].GetString(ctx, i, 1) + udf.Body, err = erArray[0].GetString(ctx, i, 2) if err != nil { return nil, err } - udf.Language, err = erArray[0].GetString(ctx, i, 2) + udf.Language, err = erArray[0].GetString(ctx, i, 3) if err != nil { return nil, err } - udf.RetType, err = erArray[0].GetString(ctx, i, 3) + udf.RetType, err = erArray[0].GetString(ctx, i, 4) if err != nil { return nil, err } - udf.Db, err = erArray[0].GetString(ctx, i, 4) + udf.Db, err = erArray[0].GetString(ctx, i, 5) if err != nil { return nil, err } - udf.ModifiedTime, err = erArray[0].GetString(ctx, i, 5) + udf.ModifiedTime, err = erArray[0].GetString(ctx, i, 6) if err != nil { return nil, err } udf.ModifiedTime = strings.ReplaceAll(udf.ModifiedTime, " ", "_") udf.ModifiedTime = strings.ReplaceAll(udf.ModifiedTime, ":", "-") - mode, getErr := erArray[0].GetString(ctx, i, 6) + mode, getErr := erArray[0].GetString(ctx, i, 7) if getErr != nil { return nil, getErr } udf.SQLMode = &mode + udf.FunctionID = functionID + if udf.Language == string(tree.PYTHON) { + revision, revisionErr := readPythonRevision(queryCtx, bh, functionID, tcc.GetSnapshot()) + if revisionErr != nil { + return nil, revisionErr + } + argstr = revision.Args + udf.Body = revision.Body + udf.Language = revision.Language + udf.RetType = revision.RetType + udf.Revision = revision.Revision + udf.NamespaceVersion = revision.NamespaceVersion + } else if udf.Language == string(tree.SQL) { + revision, found, revisionErr := readSQLRevision(queryCtx, bh, functionID, tcc.GetSnapshot()) + if revisionErr != nil { + return nil, revisionErr + } + if found { + argstr = revision.Args + udf.Body = revision.Body + udf.Language = revision.Language + udf.RetType = revision.RetType + udf.Revision = revision.Revision + udf.NamespaceVersion = revision.NamespaceVersion + udf.DefinitionFingerprint = revision.DefinitionFingerprint + udf.SemanticDefinitionSchemaVersion = int(revision.DefinitionSchema) + udf.Volatility = revision.Volatility + udf.NullPolicy = revision.NullPolicy + } + } + if err = udf.LoadPythonTypeContract(); err != nil { + return nil, err + } // arg type check argList := make([]*function.Arg, 0) err = json.Unmarshal([]byte(argstr), &argList) @@ -907,10 +959,23 @@ func (tcc *TxnCompilerContext) ResolveUdf(name string, args []*plan.Expr) (udf * if len(argList) != len(args) { // mismatch continue } + udf.Args = argList + if err = udf.ValidatePythonTypeContract(); err != nil { + return nil, err + } + if err = udf.ValidatePythonCatalogSignature(); err != nil { + return nil, err + } toList := make([]types.T, len(args)) + pythonTargetTypes := make([]types.Type, 0) + if udf.Language == string(tree.PYTHON) { + pythonTargetTypes = udf.GetArgsType() + } for j := range argList { - if fromList[j].IsDecimal() && argList[j].Type == "decimal" { + if len(pythonTargetTypes) != 0 { + toList[j] = pythonTargetTypes[j].Oid + } else if fromList[j].IsDecimal() && argList[j].Type == "decimal" { toList[j] = fromList[j].Oid } else { toList[j] = types.Types[argList[j].Type] @@ -918,11 +983,13 @@ func (tcc *TxnCompilerContext) ResolveUdf(name string, args []*plan.Expr) (udf * } canCast, cost := function.UdfArgTypeMatch(fromList, toList) + if len(pythonTargetTypes) != 0 { + canCast, cost = function.PythonUdfArgTypeMatch(fromList, pythonTargetTypes) + } if !canCast { // mismatch continue } - udf.Args = argList matchedList = append(matchedList, &MatchUdf{ Udf: udf, Cost: cost, @@ -946,7 +1013,36 @@ func (tcc *TxnCompilerContext) ResolveUdf(name string, args []*plan.Expr) (udf * } if matchNum == 1 { - matchedList[0].Udf.ArgsType = function.UdfArgTypeCast(fromList, matchedList[0].TypeList) + if strings.EqualFold(matchedList[0].Udf.Language, string(tree.PYTHON)) { + matchedList[0].Udf.ArgsType = function.PythonUdfArgTypeCast(fromList, matchedList[0].Udf.GetArgsType()) + if len(matchedList[0].Udf.ArgsType) != len(fromList) { + return nil, udferr.Newf("python udf: argument descriptor count changed during resolution") + } + } else { + matchedList[0].Udf.ArgsType = function.UdfArgTypeCast(fromList, matchedList[0].TypeList) + } + if matchedList[0].Udf.Revision != 0 { + accountID, accountErr := tcc.GetAccountId() + if accountErr != nil { + return nil, accountErr + } + accountID = routineCatalogAccountID(accountID, tcc.GetSnapshot()) + databaseID, databaseErr := routineCatalogDatabaseID(queryCtx, bh, matchedList[0].Udf.Db, accountID, tcc.GetSnapshot()) + if databaseErr != nil { + return nil, errutil.Wrapf(databaseErr, "python routine database identity") + } + matchedList[0].Udf.AccountID = uint64(accountID) + matchedList[0].Udf.DatabaseID = databaseID + namespaces, namespaceErr := readRoutineNamespaces(queryCtx, bh, []uint64{uint64(matchedList[0].Udf.FunctionID)}, tcc.GetSnapshot()) + if namespaceErr != nil && !errors.Is(namespaceErr, errRoutineNamespaceBudget) { + return nil, namespaceErr + } + matchedList[0].Udf.NamespaceFingerprint = namespaces[uint64(matchedList[0].Udf.FunctionID)] + if namespaceErr == nil && matchedList[0].Udf.NamespaceFingerprint == "" { + return nil, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: missing routine namespace") + } + + } return matchedList[0].Udf, err } @@ -976,13 +1072,407 @@ func udfCatalogLookup( } } return ctx, fmt.Sprintf( - `select args, body, language, rettype, db, modified_time, sql_mode from %s where name = "%s" and db = "%s";`, + `select function_id, args, body, language, rettype, db, modified_time, sql_mode from %s where name = "%s" and db = "%s";`, catalogTable, name, database, ) } +// exactlyOneCatalogResultSet is for catalog reads that must be interpreted +// atomically. A BackgroundExec result array is a transport shape, not a +// guarantee that a single SELECT produced one result set. Treating the first +// result set as authoritative would let a split or malformed reader hide +// catalog corruption from the planner/cache validator. +func exactlyOneCatalogResultSet(ctx context.Context, rows []ExecResult, label string) (ExecResult, error) { + if len(rows) != 1 || rows[0] == nil { + return nil, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: %s returned %d result sets, expected exactly one", label, len(rows)) + } + return rows[0], nil +} + +// candidateCatalogResultSet is used only for a name/signature lookup. The +// execution engine represents a SELECT with no matching rows as an empty +// result-set slice, and that is the normal state before the first CREATE. +// Multiple result sets or a nil result remain malformed and fail closed. +func candidateCatalogResultSet(rows []ExecResult, label string) (ExecResult, error) { + if len(rows) == 0 { + return nil, nil + } + return exactlyOneCatalogResultSet(context.Background(), rows, label) +} + +// exactlyOneCatalogRow is for identity and revision point reads. A catalog +// query with a function_id/revision predicate is expected to return one +// logical row in one result set. Treating the first row as authoritative +// would turn duplicate or split result sets caused by corruption, restore, or +// a malformed reader into an arbitrary executable contract. +func exactlyOneCatalogRow(ctx context.Context, rows []ExecResult, label string) (ExecResult, error) { + result, err := exactlyOneCatalogResultSet(ctx, rows, label) + if err != nil { + return nil, err + } + rowCount := result.GetRowCount() + if rowCount != 1 { + return nil, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: %s returned %d rows, expected exactly one", label, rowCount) + } + return result, nil +} + +type pythonRevisionCatalogRow struct { + Args string + ArgTypes string + Body string + Language string + RetType string + Revision uint64 + NamespaceVersion uint64 + CanonicalInputDescriptor string + ReturnDescriptor string + SignatureKeySchemaVersion int64 + SignatureFingerprint string + DefinitionSchema int64 + ABIContract string + AdapterVersion string + SDKVersion string + NullPolicy string + Volatility string + DefinitionFingerprint string + ArtifactDigest string + EnvironmentDigest string + SecurityType string +} + +type sqlRevisionCatalogRow struct { + Args string + ArgTypes string + Body string + Language string + RetType string + Revision uint64 + NamespaceVersion uint64 + DefinitionSchema int64 + DefinitionFingerprint string + Volatility string + NullPolicy string + SecurityType string +} + +// readSQLRevision resolves the current shared revision head without making a +// legacy SQL row look current. A missing v4_0_7 table/column is reported as +// found=false so ordinary SQL remains available during a rolling upgrade; +// once a head is published, every missing or malformed revision is a hard +// catalog error. +func readSQLRevision( + ctx context.Context, + bh BackgroundExec, + functionID int64, + snapshot *plan2.Snapshot, +) (sqlRevisionCatalogRow, bool, error) { + baseTable := "mo_catalog.mo_user_defined_function" + revisionTable := "mo_catalog.mo_function_revisions" + if snapshot != nil && snapshot.TS != nil { + suffix := fmt.Sprintf(" {MO_TS = %d}", snapshot.TS.PhysicalTime) + baseTable += suffix + revisionTable += suffix + } + + bh.ClearExecResultSet() + if err := bh.Exec(ctx, fmt.Sprintf( + "select active_revision, namespace_version, security_type from %s where function_id = %d;", + baseTable, functionID, + )); err != nil { + if isMissingCatalogObjectError(err) { + return sqlRevisionCatalogRow{}, false, nil + } + return sqlRevisionCatalogRow{}, false, errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: SQL function %d revision head is unavailable", functionID) + } + rows, err := getResultSet(ctx, bh) + if err != nil { + return sqlRevisionCatalogRow{}, false, err + } + row, err := exactlyOneCatalogRow(ctx, rows, fmt.Sprintf("SQL function %d revision head", functionID)) + if err != nil { + return sqlRevisionCatalogRow{}, false, err + } + activeRevision, err := row.GetInt64(ctx, 0, 0) + if err != nil { + return sqlRevisionCatalogRow{}, false, err + } + namespaceVersion, err := row.GetInt64(ctx, 0, 1) + if err != nil { + return sqlRevisionCatalogRow{}, false, err + } + baseSecurityType, err := row.GetString(ctx, 0, 2) + if err != nil { + return sqlRevisionCatalogRow{}, false, err + } + if activeRevision == 0 && namespaceVersion == 0 { + return sqlRevisionCatalogRow{}, false, nil + } + if activeRevision <= 0 || namespaceVersion <= 0 { + return sqlRevisionCatalogRow{}, false, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: SQL function %d has an invalid revision head", functionID) + } + + bh.ClearExecResultSet() + if err := bh.Exec(ctx, fmt.Sprintf( + "select revision, args, arg_types, body, rettype, language, "+ + "definition_schema_version, definition_fingerprint, volatility, null_policy, security_type "+ + "from %s where function_id = %d and revision = %d and namespace_version = %d;", + revisionTable, functionID, activeRevision, namespaceVersion, + )); err != nil { + if isMissingCatalogObjectError(err) { + return sqlRevisionCatalogRow{}, false, errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: SQL function %d revision table is unavailable", functionID) + } + return sqlRevisionCatalogRow{}, false, errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: SQL function %d revision is unavailable", functionID) + } + rows, err = getResultSet(ctx, bh) + if err != nil { + return sqlRevisionCatalogRow{}, false, err + } + row, err = exactlyOneCatalogRow(ctx, rows, fmt.Sprintf("SQL function %d active revision", functionID)) + if err != nil { + return sqlRevisionCatalogRow{}, false, err + } + getString := func(column uint64) (string, error) { return row.GetString(ctx, 0, column) } + revisionValue, err := row.GetInt64(ctx, 0, 0) + if err != nil { + return sqlRevisionCatalogRow{}, false, err + } + args, err := getString(1) + if err != nil { + return sqlRevisionCatalogRow{}, false, err + } + argTypes, err := getString(2) + if err != nil { + return sqlRevisionCatalogRow{}, false, err + } + body, err := getString(3) + if err != nil { + return sqlRevisionCatalogRow{}, false, err + } + retType, err := getString(4) + if err != nil { + return sqlRevisionCatalogRow{}, false, err + } + language, err := getString(5) + if err != nil { + return sqlRevisionCatalogRow{}, false, err + } + definitionSchema, err := row.GetInt64(ctx, 0, 6) + if err != nil { + return sqlRevisionCatalogRow{}, false, err + } + fingerprint, err := getString(7) + if err != nil { + return sqlRevisionCatalogRow{}, false, err + } + volatility, err := getString(8) + if err != nil { + return sqlRevisionCatalogRow{}, false, err + } + nullPolicy, err := getString(9) + if err != nil { + return sqlRevisionCatalogRow{}, false, err + } + securityType, err := getString(10) + if err != nil { + return sqlRevisionCatalogRow{}, false, err + } + if revisionValue <= 0 || uint64(revisionValue) != uint64(activeRevision) || + language != string(tree.SQL) || + definitionSchema != udf.SQLDefinitionSchemaVersion || + volatility != "VOLATILE" || nullPolicy != udf.NullCallHandler || + !strings.EqualFold(securityType, "DEFINER") || + !strings.EqualFold(baseSecurityType, securityType) { + return sqlRevisionCatalogRow{}, false, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: SQL function %d revision contract is not supported", functionID) + } + logicalArgTypes, err := userDefinedFunctionArgumentTypesFromJSON(args) + if err != nil || logicalArgTypes != argTypes { + return sqlRevisionCatalogRow{}, false, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: SQL function %d revision argument metadata is invalid", functionID) + } + expectedFingerprint, err := function.SQLRoutineFingerprint(body, argTypes, retType) + if err != nil || fingerprint == "" || fingerprint != expectedFingerprint { + return sqlRevisionCatalogRow{}, false, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: SQL function %d revision fingerprint mismatch", functionID) + } + return sqlRevisionCatalogRow{ + Args: args, ArgTypes: argTypes, Body: body, Language: language, RetType: retType, + Revision: uint64(revisionValue), NamespaceVersion: uint64(namespaceVersion), + DefinitionSchema: definitionSchema, DefinitionFingerprint: fingerprint, + Volatility: volatility, NullPolicy: nullPolicy, SecurityType: securityType, + }, true, nil +} + +func readPythonRevision(ctx context.Context, bh BackgroundExec, functionID int64, snapshot *plan2.Snapshot) (pythonRevisionCatalogRow, error) { + bh.ClearExecResultSet() + query := pythonRevisionCatalogSQL(snapshot, functionID) + if err := bh.Exec(ctx, query); err != nil { + return pythonRevisionCatalogRow{}, errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: Python catalog revision is unavailable") + } + rows, err := getResultSet(ctx, bh) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + row, err := exactlyOneCatalogRow(ctx, rows, fmt.Sprintf("Python function %d active revision", functionID)) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + activeRevision, err := row.GetInt64(ctx, 0, 0) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + namespaceVersion, err := row.GetInt64(ctx, 0, 1) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + revision, err := row.GetInt64(ctx, 0, 2) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + if activeRevision <= 0 || namespaceVersion <= 0 || revision != activeRevision { + return pythonRevisionCatalogRow{}, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python function %d has an invalid revision head", functionID) + } + getString := func(column uint64) (string, error) { return row.GetString(ctx, 0, column) } + canonicalInput, err := getString(3) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + returnDescriptor, err := getString(4) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + signatureKeySchemaVersion, err := row.GetInt64(ctx, 0, 5) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + signatureFingerprint, err := getString(6) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + args, err := getString(7) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + argTypes, err := getString(8) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + body, err := getString(9) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + language, err := getString(10) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + retType, err := getString(11) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + definitionSchema, err := row.GetInt64(ctx, 0, 12) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + abi, err := getString(13) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + adapter, err := getString(14) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + sdk, err := getString(15) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + nullPolicy, err := getString(16) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + volatility, err := getString(17) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + fingerprint, err := getString(18) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + artifact, err := getString(19) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + environment, err := getString(20) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + securityType, err := getString(21) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + baseSecurityType, err := getString(22) + if err != nil { + return pythonRevisionCatalogRow{}, err + } + if language != string(tree.PYTHON) || definitionSchema != udf.PythonDefinitionSchemaVersion || abi != udf.PythonABIContract || adapter != udf.PythonAdapterVersion || sdk != udf.PythonSDKVersion || volatility != "VOLATILE" || !strings.EqualFold(securityType, "INVOKER") || !strings.EqualFold(baseSecurityType, securityType) { + return pythonRevisionCatalogRow{}, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python function %d revision contract is not supported", functionID) + } + bodyDefinition, err := function.DecodePythonRoutineBody(body) + if err != nil { + return pythonRevisionCatalogRow{}, errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: Python function %d revision body is invalid", functionID) + } + if bodyDefinition.ABIContract != abi || bodyDefinition.AdapterVersion != adapter || bodyDefinition.SDKVersion != sdk || bodyDefinition.NullPolicy != nullPolicy || bodyDefinition.ArtifactDigest != artifact || bodyDefinition.EnvironmentDigest != environment { + return pythonRevisionCatalogRow{}, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python function %d revision metadata does not match its definition", functionID) + } + actualFingerprint, err := function.PythonRoutineFingerprint(body) + if err != nil { + return pythonRevisionCatalogRow{}, errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: Python function %d revision fingerprint cannot be computed", functionID) + } + if fingerprint == "" || fingerprint != actualFingerprint { + return pythonRevisionCatalogRow{}, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python function %d revision fingerprint mismatch", functionID) + } + expectedInput, expectedReturn, expectedSignature, err := function.PythonSignatureMetadata(bodyDefinition.ArgTypes, bodyDefinition.ReturnType) + if err != nil { + return pythonRevisionCatalogRow{}, errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: Python function %d signature cannot be computed", functionID) + } + if signatureKeySchemaVersion != udf.PythonSignatureKeySchemaVersion || + canonicalInput != expectedInput || returnDescriptor != expectedReturn || signatureFingerprint != expectedSignature { + return pythonRevisionCatalogRow{}, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python function %d identity descriptor metadata mismatch", functionID) + } + if argTypes != expectedInput { + return pythonRevisionCatalogRow{}, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python function %d revision argument descriptor mismatch", functionID) + } + return pythonRevisionCatalogRow{ + Args: args, ArgTypes: argTypes, Body: body, Language: language, RetType: retType, + Revision: uint64(revision), NamespaceVersion: uint64(namespaceVersion), + CanonicalInputDescriptor: canonicalInput, ReturnDescriptor: returnDescriptor, + SignatureKeySchemaVersion: signatureKeySchemaVersion, SignatureFingerprint: signatureFingerprint, + DefinitionSchema: definitionSchema, ABIContract: abi, AdapterVersion: adapter, + SDKVersion: sdk, NullPolicy: nullPolicy, Volatility: volatility, DefinitionFingerprint: fingerprint, + ArtifactDigest: artifact, EnvironmentDigest: environment, SecurityType: securityType, + }, nil +} + +func pythonRevisionCatalogSQL(snapshot *plan2.Snapshot, functionID int64) string { + userFunctionTable := "mo_catalog.mo_user_defined_function" + revisionTable := "mo_catalog.mo_function_revisions" + if snapshot != nil && snapshot.TS != nil { + userFunctionTable += fmt.Sprintf(" {MO_TS = %d}", snapshot.TS.PhysicalTime) + revisionTable += fmt.Sprintf(" {MO_TS = %d}", snapshot.TS.PhysicalTime) + } + return fmt.Sprintf(`select f.active_revision, f.namespace_version, r.revision, + f.canonical_input_descriptor, f.return_descriptor, + f.signature_key_schema_version, f.signature_fingerprint, + r.args, r.arg_types, r.body, r.language, r.rettype, r.definition_schema_version, + r.abi_contract, r.adapter_version, r.sdk_version, r.null_policy, r.volatility, + r.definition_fingerprint, r.artifact_digest, r.environment_digest, + r.security_type, f.security_type + from %s f + join %s r + on r.function_id = f.function_id and r.revision = f.active_revision + and r.namespace_version = f.namespace_version + where f.function_id = %d;`, userFunctionTable, revisionTable, functionID) +} + func (tcc *TxnCompilerContext) ResolveVariable(varName string, isSystemVar, isGlobalVar bool) (varValue interface{}, err error) { stats := statistic.StatsInfoFromContext(tcc.execCtx.reqCtx) start := time.Now() diff --git a/pkg/frontend/compiler_context_test.go b/pkg/frontend/compiler_context_test.go index 9000e43836972..7ad143dbf191a 100644 --- a/pkg/frontend/compiler_context_test.go +++ b/pkg/frontend/compiler_context_test.go @@ -34,6 +34,7 @@ import ( "github.com/matrixorigin/matrixone/pkg/sql/plan/function" "github.com/matrixorigin/matrixone/pkg/testutil" "github.com/matrixorigin/matrixone/pkg/txn/client" + "github.com/matrixorigin/matrixone/pkg/udf" "github.com/matrixorigin/matrixone/pkg/vm/engine" "github.com/stretchr/testify/require" ) @@ -87,6 +88,112 @@ func TestSubscriptionMetasFromSubInfos(t *testing.T) { }, metas) } +func TestResolveUdfBindsExactPythonRevisionAndNamespace(t *testing.T) { + ctx := defines.AttachAccountId(context.Background(), 0) + ses := &Session{feSessionImpl: feSessionImpl{}} + ses.SetAccountId(0) + background := &backgroundExecTestWithHistory{} + background.init() + previousNewBackgroundExec := NewBackgroundExec + NewBackgroundExec = func(context.Context, FeSession, ...*BackgroundExecOption) BackgroundExec { + return background + } + t.Cleanup(func() { NewBackgroundExec = previousNewBackgroundExec }) + + body := pythonCatalogTestBody(t, types.T_int64) + decoded, err := function.DecodePythonRoutineBody(body) + require.NoError(t, err) + logicalArgs := `[{"name":"value","type":"bigint"}]` + compiler := &TxnCompilerContext{execCtx: &ExecCtx{reqCtx: ctx, ses: ses}} + compiler.SetDatabase("app") + _, candidateSQL := udfCatalogLookup(ctx, nil, "f", "app") + background.sql2result[candidateSQL] = resolveUdfCatalogResult( + []string{"function_id", "args", "body", "language", "rettype", "db", "modified_time", "sql_mode"}, + []interface{}{int64(44), logicalArgs, body, "python", "bigint", "app", "2026-09-20 00:00:00", ""}, + ) + + inputDescriptor, returnDescriptor, signatureFingerprint, err := function.PythonSignatureMetadata(decoded.ArgTypes, decoded.ReturnType) + require.NoError(t, err) + definitionFingerprint, err := function.PythonRoutineFingerprint(body) + require.NoError(t, err) + background.sql2result[pythonRevisionCatalogSQL(nil, 44)] = resolveUdfCatalogResult( + []string{ + "active_revision", "namespace_version", "revision", "canonical_input_descriptor", "return_descriptor", + "signature_key_schema_version", "signature_fingerprint", "args", "arg_types", "body", "language", + "rettype", "definition_schema_version", "abi_contract", "adapter_version", "sdk_version", "null_policy", + "volatility", "definition_fingerprint", "artifact_digest", "environment_digest", "revision_security_type", "head_security_type", + }, + []interface{}{ + int64(1), int64(1), int64(1), inputDescriptor, returnDescriptor, int64(udf.PythonSignatureKeySchemaVersion), + signatureFingerprint, logicalArgs, inputDescriptor, body, "python", "bigint", int64(udf.PythonDefinitionSchemaVersion), + udf.PythonABIContract, udf.PythonAdapterVersion, udf.PythonSDKVersion, udf.NullCallHandler, "VOLATILE", + definitionFingerprint, decoded.ArtifactDigest, decoded.EnvironmentDigest, "INVOKER", "INVOKER", + }, + ) + background.sql2result["select dat_id from mo_catalog.mo_database where datname = 'app' and account_id = 0;"] = singleInt64Result("dat_id", 88) + namespaceSQL := routineNamespacesSQL([]uint64{44}, nil) + background.sql2result[namespaceSQL] = namespaceRows(namespaceMember(44, "candidate-state")) + + argumentType := types.T_int64.ToType() + resolved, err := compiler.ResolveUdf("f", []*pbplan.Expr{{Typ: plan2.MakePlan2Type(&argumentType)}}) + require.NoError(t, err) + require.Equal(t, int64(44), resolved.FunctionID) + require.Equal(t, uint64(1), resolved.Revision) + require.Equal(t, uint64(1), resolved.NamespaceVersion) + require.Equal(t, uint64(88), resolved.DatabaseID) + require.NotEmpty(t, resolved.NamespaceFingerprint) + require.Equal(t, []types.Type{types.T_int64.ToType()}, resolved.ArgsType) + require.Contains(t, background.executedSqls, candidateSQL) + require.Contains(t, background.executedSqls, pythonRevisionCatalogSQL(nil, 44)) + require.Contains(t, background.executedSqls, namespaceSQL) +} + +func TestResolveUdfKeepsLegacySQLRoutineReadableWithoutRevisionCatalog(t *testing.T) { + ctx := defines.AttachAccountId(context.Background(), 0) + ses := &Session{feSessionImpl: feSessionImpl{}} + ses.SetAccountId(0) + background := &backgroundExecTestWithHistory{} + background.init() + previousNewBackgroundExec := NewBackgroundExec + NewBackgroundExec = func(context.Context, FeSession, ...*BackgroundExecOption) BackgroundExec { + return background + } + t.Cleanup(func() { NewBackgroundExec = previousNewBackgroundExec }) + + compiler := &TxnCompilerContext{execCtx: &ExecCtx{reqCtx: ctx, ses: ses}} + compiler.SetDatabase("app") + _, candidateSQL := udfCatalogLookup(ctx, nil, "legacy_f", "app") + background.sql2result[candidateSQL] = resolveUdfCatalogResult( + []string{"function_id", "args", "body", "language", "rettype", "db", "modified_time", "sql_mode"}, + []interface{}{int64(52), `[{"name":"value","type":"bigint"}]`, "select value + 1", "sql", "bigint", "app", "2026-09-20 00:00:00", ""}, + ) + background.sql2err["select active_revision, namespace_version, security_type from mo_catalog.mo_user_defined_function where function_id = 52;"] = errors.New("no such table: mo_function_revisions") + argumentType := types.T_int64.ToType() + resolved, err := compiler.ResolveUdf("legacy_f", []*pbplan.Expr{{Typ: plan2.MakePlan2Type(&argumentType)}}) + require.NoError(t, err) + require.Equal(t, int64(52), resolved.FunctionID) + require.Equal(t, "sql", resolved.Language) + require.Zero(t, resolved.Revision, "a legacy SQL definition stays on its existing body while the shared revision table is absent") + require.Equal(t, []types.Type{types.T_int64.ToType()}, resolved.ArgsType) + require.Contains(t, background.executedSqls, "select active_revision, namespace_version, security_type from mo_catalog.mo_user_defined_function where function_id = 52;") +} + +func resolveUdfCatalogResult(columns []string, row []interface{}) *MysqlResultSet { + result := &MysqlResultSet{} + for index, name := range columns { + column := &MysqlColumn{} + column.SetName(name) + if _, ok := row[index].(int64); ok { + column.SetColumnType(defines.MYSQL_TYPE_LONGLONG) + } else { + column.SetColumnType(defines.MYSQL_TYPE_VAR_STRING) + } + result.AddColumn(column) + } + result.AddRow(row) + return result +} + func TestSubscriptionMetadataEnumerationObservesCancellation(t *testing.T) { wantErr := errors.New("stop subscription metadata enumeration") ctx, cancel := context.WithCancelCause(context.Background()) diff --git a/pkg/frontend/computation_wrapper.go b/pkg/frontend/computation_wrapper.go index cc41c18f98e5e..07402b4f69064 100644 --- a/pkg/frontend/computation_wrapper.go +++ b/pkg/frontend/computation_wrapper.go @@ -1430,6 +1430,11 @@ func initExecuteStmtParamWithResolverInSession( currentDDLVersion := owner.getDDLVersion() change := prepareStmt.tempTableVersion != currentTempTableVersion || prepareStmt.ddlVersion != currentDDLVersion + routineChanged, routineErr := validateRoutinePlanDependencies(reqCtx, executionSes, executionPlan) + if routineErr != nil { + return nil, nil, nil, "", false, routineErr + } + change = change || routineChanged var preparedMetadataTS timestamp.Timestamp if catalogCache != nil { preparedMetadataTS = catalogCache.GetPreparedMetadataTS() diff --git a/pkg/frontend/mysql_cmd_executor.go b/pkg/frontend/mysql_cmd_executor.go index 7dc741979fd10..80ca1b65b6495 100644 --- a/pkg/frontend/mysql_cmd_executor.go +++ b/pkg/frontend/mysql_cmd_executor.go @@ -4146,6 +4146,13 @@ func cachedPlanForInput(ses *Session, input *UserInput) *cachedPlan { return nil } cached := ses.getCachedPlan(input.getHash()) + if cached != nil && !cachedRoutinePlanDependenciesCurrent(ses, cached) { + // A cached plan carries exact routine revisions. Do not let an entry + // survive a replace/drop or an integrity mismatch merely because the + // ordinary table/schema generation is unchanged. + ses.removeCachedPlan(input.getHash()) + return nil + } // SELECT ... INTO @var changes the type of a session variable as part of // execution. A cached SELECT-INTO plan can therefore never be reused: it // may have been bound against the variable's pre-assignment type, and the @@ -5399,7 +5406,11 @@ func dispatchStmt(ses FeSession, if err != nil { return err } - if flag { + routineChanged, err := validateRoutinePlanDependencies(execCtx.reqCtx, ses, execCtx.cw.Plan()) + if err != nil { + return err + } + if flag || routineChanged { if err = rebuildStaleCachedStatements(ses, execCtx); err != nil { return err } diff --git a/pkg/frontend/pitr.go b/pkg/frontend/pitr.go index 414273f674b29..ccb89eb6210f5 100644 --- a/pkg/frontend/pitr.go +++ b/pkg/frontend/pitr.go @@ -1597,6 +1597,21 @@ func reCreateTableWithPitr( fmt.Sprintf(" {MO_TS = %d}", ts), accountID, accountID, + tblInfo.createSql, + ) + } + if isCurrentFunctionRevisionCatalog(tblInfo) { + accountID, accountErr := defines.GetAccountId(ctx) + if accountErr != nil { + return accountErr + } + return restoreFunctionRevisionCatalogWithCurrentSchema( + ctx, + bh, + fmt.Sprintf(" {MO_TS = %d}", ts), + accountID, + accountID, + tblInfo.createSql, ) } if isSequence(tblInfo) { diff --git a/pkg/frontend/predefined.go b/pkg/frontend/predefined.go index c9ccfc4fc13d9..c988702a3503b 100644 --- a/pkg/frontend/predefined.go +++ b/pkg/frontend/predefined.go @@ -99,10 +99,16 @@ var ( MoCatalogMoUserDefinedFunctionDDL = fmt.Sprintf(`create table mo_catalog.mo_user_defined_function ( function_id int auto_increment, + active_revision bigint unsigned not null default 0, + namespace_version bigint unsigned not null default 0, name varchar(100), owner int unsigned, args json, arg_types varchar(%d) not null default '', + canonical_input_descriptor varchar(%d) not null default '', + return_descriptor varchar(%d) not null default '', + signature_key_schema_version int not null default 0, + signature_fingerprint varchar(128) not null default '', retType varchar(20), body text, language varchar(20), @@ -111,14 +117,38 @@ var ( modified_time timestamp, created_time timestamp, type varchar(10), - security_type varchar(10), + security_type varchar(10) not null default 'DEFINER', comment varchar(5000), character_set_client varchar(64), collation_connection varchar(64), database_collation varchar(64), sql_mode varchar(1024) not null default 'PIPES_AS_CONCAT', primary key(function_id), - unique key name_db_arg_types(name, db, arg_types) + unique key name_db_arg_types_descriptor(name, db, arg_types, canonical_input_descriptor) + )`, types.MaxStringSize, types.MaxStringSize, types.MaxStringSize) + + MoCatalogMoFunctionRevisionDDL = fmt.Sprintf(`create table mo_catalog.mo_function_revisions ( + function_id bigint unsigned not null, + revision bigint unsigned not null, + namespace_version bigint unsigned not null, + name varchar(100) not null, + args json not null, + arg_types varchar(%d) not null default '', + rettype varchar(20) not null, + body text not null, + language varchar(20) not null, + definition_schema_version int not null default 0, + abi_contract varchar(64) not null default '', + adapter_version varchar(64) not null default '', + artifact_digest varchar(128) not null default '', + environment_digest varchar(128) not null default '', + sdk_version varchar(64) not null default '', + null_policy varchar(64) not null default '', + volatility varchar(20) not null default 'VOLATILE', + definition_fingerprint varchar(128) not null default '', + created_time timestamp, + security_type varchar(10) not null default 'DEFINER', + primary key(function_id, revision) )`, types.MaxStringSize) MoCatalogMoMysqlCompatibilityModeDDL = `create table mo_catalog.mo_mysql_compatibility_mode ( diff --git a/pkg/frontend/python_udf_catalog_test.go b/pkg/frontend/python_udf_catalog_test.go new file mode 100644 index 0000000000000..849e7bdc85ec0 --- /dev/null +++ b/pkg/frontend/python_udf_catalog_test.go @@ -0,0 +1,1465 @@ +// Copyright 2026 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 frontend + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "strconv" + "strings" + "testing" + + "github.com/golang/mock/gomock" + "github.com/matrixorigin/matrixone/pkg/common/moerr" + "github.com/matrixorigin/matrixone/pkg/common/mpool" + "github.com/matrixorigin/matrixone/pkg/config" + "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/sql/parsers" + "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect" + "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" + "github.com/matrixorigin/matrixone/pkg/sql/plan/function" + "github.com/matrixorigin/matrixone/pkg/udf" + pythonudf "github.com/matrixorigin/matrixone/pkg/udf/python" + "github.com/prashantv/gostub" + "github.com/stretchr/testify/require" +) + +type definitionValidationRuntime struct { + definition *udf.RoutineDefinition + err error +} + +func (r *definitionValidationRuntime) Language() string { return udf.LanguagePython } + +func (r *definitionValidationRuntime) Execute( + context.Context, + *udf.Invocation, + vector.FunctionResultWrapper, + *mpool.MPool, +) error { + return nil +} + +func (r *definitionValidationRuntime) CheckLanguageReady(context.Context, string) error { + return nil +} + +func (r *definitionValidationRuntime) ValidateDefinition( + _ context.Context, + definition *udf.RoutineDefinition, +) error { + r.definition = definition + return r.err +} + +func TestValidatePythonUdfDefinitionAtCreateUsesTypedWorkerGate(t *testing.T) { + const service = "python-definition-validation-test" + InitServerLevelVars(service) + previous := getPuIfPresent(service) + t.Cleanup(func() { setPu(service, previous) }) + + runtime := &definitionValidationRuntime{err: fmt.Errorf("USER_CODE: Python syntax error at line 1, column 22")} + pu := config.NewParameterUnit(&config.FrontendParameters{}, nil, nil, nil) + pu.UdfService = runtime + setPu(service, pu) + + source := "def f(ctx, value): return value" + body, err := function.DecodePythonRoutineBody(pythonCatalogTestBody(t, types.T_int64)) + require.NoError(t, err) + body.Source = source + body.ArtifactDigest = udf.PythonInlineArtifactDigest(body.Handler, source) + body.EnvironmentDigest, err = udf.PythonEnvironmentDigest() + require.NoError(t, err) + + ses := &Session{feSessionImpl: feSessionImpl{service: service}} + tenant := &TenantInfo{TenantID: 27} + err = validatePythonUdfDefinitionAtCreate(context.Background(), ses, tenant, body) + require.ErrorContains(t, err, "Python syntax error") + require.NotNil(t, runtime.definition) + require.Equal(t, uint64(27), runtime.definition.AccountID) + require.Equal(t, body.Handler, runtime.definition.Handler) + require.Equal(t, body.Source, runtime.definition.Source) + require.Equal(t, body.ArtifactDigest, runtime.definition.ArtifactDigest) + require.Equal(t, body.EnvironmentDigest, runtime.definition.EnvironmentDigest) + require.Equal(t, types.T_int64.ToType(), runtime.definition.ReturnType) +} + +func TestInitPythonFunctionValidatesArtifactBeforeCatalogReadiness(t *testing.T) { + const service = "python-create-catalog-gate-test" + InitServerLevelVars(service) + previousPU := getPuIfPresent(service) + t.Cleanup(func() { setPu(service, previousPU) }) + + fs, err := fileservice.NewMemoryFS(defines.SharedFileServiceName, fileservice.DisabledCacheConfig, nil) + require.NoError(t, err) + runtime := &definitionValidationRuntime{} + pu := config.NewParameterUnit(&config.FrontendParameters{}, nil, nil, nil) + pu.FileService = fs + pu.UdfService = runtime + setPu(service, pu) + + ctx := defines.AttachAccountId(context.Background(), 27) + statement, err := parsers.ParseOne(ctx, dialect.MYSQL, + "create function app.py_echo(value bigint) returns bigint language python as 'def py_echo(ctx, value): return value' handler 'py_echo' mode scalar called on null input", 1) + require.NoError(t, err) + defer statement.Free() + createFunction, ok := statement.(*tree.CreateFunction) + require.True(t, ok) + + background := &backgroundExecTestWithHistory{} + background.init() + background.sql2result[pythonUdfCatalogIdentitySchemaCheck] = emptyCatalogProbeResult(6) + missingRevisionCatalog := errors.New("revision catalog has not been upgraded") + background.sql2err[functionRevisionCatalogSchemaCheck] = missingRevisionCatalog + previousNewBackgroundExec := NewBackgroundExec + NewBackgroundExec = func(context.Context, FeSession, ...*BackgroundExecOption) BackgroundExec { + return background + } + t.Cleanup(func() { NewBackgroundExec = previousNewBackgroundExec }) + + tenant := &TenantInfo{User: "root", TenantID: 27, DefaultRoleID: accountAdminRoleID} + session := &Session{feSessionImpl: feSessionImpl{service: service, tenant: tenant}} + err = InitFunction(session, &ExecCtx{reqCtx: ctx}, tenant, createFunction) + require.ErrorContains(t, err, "Python UDF catalog contract is not ready") + require.ErrorContains(t, err, missingRevisionCatalog.Error()) + require.NotNil(t, runtime.definition, "CREATE must validate the source with the current worker before opening the catalog transaction") + require.Equal(t, uint64(27), runtime.definition.AccountID) + require.Equal(t, "py_echo", runtime.definition.Handler) + require.Equal(t, "def py_echo(ctx, value): return value", runtime.definition.Source) + require.Equal(t, "SCALAR", runtime.definition.Mode) + require.Equal(t, udf.NullCallHandler, runtime.definition.NullPolicy) + + store, err := pythonudf.NewFileArtifactStore(fs, pythonudf.DefaultMaxArtifactBytes) + require.NoError(t, err) + resolved, err := store.Resolve(ctx, 27, runtime.definition.Handler, runtime.definition.ArtifactDigest) + require.NoError(t, err) + require.Equal(t, runtime.definition.Source, resolved) + for _, query := range background.executedSqls { + require.NotContains(t, query, "insert into mo_catalog.mo_user_defined_function") + require.NotContains(t, query, "insert into mo_catalog.mo_function_revisions") + } +} + +func TestInitPythonFunctionChecksExactOverloadBeforePublishing(t *testing.T) { + const service = "python-create-overload-check-test" + InitServerLevelVars(service) + previousPU := getPuIfPresent(service) + t.Cleanup(func() { setPu(service, previousPU) }) + + fs, err := fileservice.NewMemoryFS(defines.SharedFileServiceName, fileservice.DisabledCacheConfig, nil) + require.NoError(t, err) + runtime := &definitionValidationRuntime{} + pu := config.NewParameterUnit(&config.FrontendParameters{}, nil, nil, nil) + pu.FileService = fs + pu.UdfService = runtime + setPu(service, pu) + + ctx := defines.AttachAccountId(context.Background(), 27) + statement, err := parsers.ParseOne(ctx, dialect.MYSQL, + "create function app.py_echo(value bigint) returns bigint language python as 'def py_echo(ctx, value): return value' handler 'py_echo'", 1) + require.NoError(t, err) + defer statement.Free() + createFunction := statement.(*tree.CreateFunction) + + background := &backgroundExecTestWithHistory{} + background.init() + background.sql2result[pythonUdfCatalogIdentitySchemaCheck] = emptyCatalogProbeResult(6) + background.sql2result[functionRevisionCatalogSchemaCheck] = emptyCatalogProbeResult(20) + databaseSQL, err := getSqlForCheckDatabaseByAccount(ctx, "app") + require.NoError(t, err) + databaseSQL = strings.TrimSuffix(databaseSQL, ";") + " for update;" + background.sql2result[databaseSQL] = singleInt64Result("dat_id", 8) + decoded, err := function.DecodePythonRoutineBody(pythonCatalogTestBody(t, types.T_int64)) + require.NoError(t, err) + canonicalInput, _, _, err := function.PythonSignatureMetadata(decoded.ArgTypes, decoded.ReturnType) + require.NoError(t, err) + checkCandidatesSQL := fmt.Sprintf(checkPythonUdfExistence, "py_echo", "app") + background.sql2result[checkCandidatesSQL] = resolveUdfCatalogResult( + []string{"function_id", "args", "language", "arg_types", "canonical_input_descriptor"}, + []interface{}{int64(55), `[{"name":"value","type":"bigint"}]`, "python", `["bigint"]`, + canonicalInput}, + ) + previousNewBackgroundExec := NewBackgroundExec + NewBackgroundExec = func(context.Context, FeSession, ...*BackgroundExecOption) BackgroundExec { + return background + } + t.Cleanup(func() { NewBackgroundExec = previousNewBackgroundExec }) + + tenant := &TenantInfo{User: "root", TenantID: 27, DefaultRoleID: accountAdminRoleID} + session := &Session{feSessionImpl: feSessionImpl{service: service, tenant: tenant}} + err = InitFunction(session, &ExecCtx{reqCtx: ctx}, tenant, createFunction) + require.ErrorContains(t, err, "already exists") + require.NotNil(t, runtime.definition, "the submitted source must be validated before the locked exact-signature check") + require.Equal(t, uint64(27), runtime.definition.AccountID) + require.Equal(t, "py_echo", runtime.definition.Handler) + require.Contains(t, background.executedSqls, databaseSQL) + require.Contains(t, background.executedSqls, checkCandidatesSQL) + require.Contains(t, background.executedSqls, "rollback;") + for _, query := range background.executedSqls { + require.NotContains(t, query, "insert into mo_catalog.mo_user_defined_function") + require.NotContains(t, query, "insert into mo_catalog.mo_function_revisions") + } +} + +func TestPersistPythonReplaceRejectsLegacyHeadBeforeWriting(t *testing.T) { + ctx := context.Background() + functionID := int64(41) + languageSQL := fmt.Sprintf( + "select language from mo_catalog.mo_user_defined_function where function_id = %d;", + functionID, + ) + headSQL := fmt.Sprintf( + "select active_revision, namespace_version from mo_catalog.mo_user_defined_function where function_id = %d;", + functionID, + ) + bh := &backgroundExecTestWithHistory{} + bh.init() + language := &MysqlResultSet{} + languageColumn := &MysqlColumn{} + languageColumn.SetName("language") + languageColumn.SetColumnType(defines.MYSQL_TYPE_VAR_STRING) + language.AddColumn(languageColumn) + language.AddRow([]interface{}{"python"}) + bh.sql2result[languageSQL] = language + head := &MysqlResultSet{} + for _, name := range []string{"active_revision", "namespace_version"} { + column := &MysqlColumn{} + column.SetName(name) + column.SetColumnType(defines.MYSQL_TYPE_LONGLONG) + head.AddColumn(column) + } + head.AddRow([]interface{}{int64(0), int64(0)}) + bh.sql2result[headSQL] = head + + err := persistUserDefinedFunction(ctx, bh, nil, 7, userDefinedFunctionDefinition{ + name: "legacy_python", + args: "[]", + argTypes: "[]", + retType: "int", + body: "legacy demo body", + lang: "python", + dbName: "db1", + }, &functionID) + + require.ErrorContains(t, err, "UNSUPPORTED_ROUTINE_VERSION") + require.ErrorContains(t, err, "DROP and CREATE") + require.Equal(t, []string{languageSQL, headSQL}, bh.executedSqls) +} + +func TestPersistFunctionReplaceRejectsLanguageChangeBeforeWriting(t *testing.T) { + ctx := context.Background() + functionID := int64(42) + languageSQL := fmt.Sprintf( + "select language from mo_catalog.mo_user_defined_function where function_id = %d;", + functionID, + ) + b := &backgroundExecTestWithHistory{} + b.init() + language := &MysqlResultSet{} + column := &MysqlColumn{} + column.SetName("language") + column.SetColumnType(defines.MYSQL_TYPE_VAR_STRING) + language.AddColumn(column) + language.AddRow([]interface{}{"SQL"}) + b.sql2result[languageSQL] = language + + err := persistUserDefinedFunction(ctx, b, nil, 7, userDefinedFunctionDefinition{ + name: "cross_language", + lang: "python", + body: "not published", + }, &functionID) + + require.ErrorContains(t, err, "cannot change language") + require.ErrorContains(t, err, "DROP and CREATE") + require.Equal(t, []string{languageSQL}, b.executedSqls) +} + +func TestPersistPythonReplaceRejectsSignatureChangeBeforeWriting(t *testing.T) { + ctx := context.Background() + functionID := int64(43) + languageSQL := fmt.Sprintf( + "select language from mo_catalog.mo_user_defined_function where function_id = %d;", + functionID, + ) + headSQL := fmt.Sprintf( + "select active_revision, namespace_version from mo_catalog.mo_user_defined_function where function_id = %d;", + functionID, + ) + bodySQL := fmt.Sprintf( + "select body from mo_catalog.mo_function_revisions where function_id = %d and revision = %d and namespace_version = %d;", + functionID, 1, 1, + ) + b := &backgroundExecTestWithHistory{} + b.init() + b.sql2result[languageSQL] = singleStringResult("language", "python") + head := &MysqlResultSet{} + for _, name := range []string{"active_revision", "namespace_version"} { + column := &MysqlColumn{} + column.SetName(name) + column.SetColumnType(defines.MYSQL_TYPE_LONGLONG) + head.AddColumn(column) + } + head.AddRow([]interface{}{int64(1), int64(1)}) + b.sql2result[headSQL] = head + previous := pythonCatalogTestBody(t, types.T_int64) + b.sql2result[bodySQL] = singleStringResult("body", previous) + candidate := pythonCatalogTestBody(t, types.T_int32) + + err := persistUserDefinedFunction(ctx, b, nil, 7, userDefinedFunctionDefinition{ + name: "current_python", + args: "[]", + argTypes: "[]", + retType: "int", + body: candidate, + lang: "python", + dbName: "db1", + }, &functionID) + + require.ErrorContains(t, err, "cannot change input or return descriptor") + require.Equal(t, []string{languageSQL, headSQL, bodySQL}, b.executedSqls) +} + +func singleStringResult(name, value string) *MysqlResultSet { + result := &MysqlResultSet{} + column := &MysqlColumn{} + column.SetName(name) + column.SetColumnType(defines.MYSQL_TYPE_VAR_STRING) + result.AddColumn(column) + result.AddRow([]interface{}{value}) + return result +} + +func singleInt64Result(name string, value int64) *MysqlResultSet { + result := &MysqlResultSet{} + column := &MysqlColumn{} + column.SetName(name) + column.SetColumnType(defines.MYSQL_TYPE_LONGLONG) + result.AddColumn(column) + result.AddRow([]interface{}{value}) + return result +} + +func pythonCatalogTestBody(t *testing.T, oid types.T) string { + t.Helper() + descriptor, err := function.NewPythonTypeDescriptor(oid.ToType()) + require.NoError(t, err) + source := "def f(ctx, value): return value" + environment, err := udf.PythonEnvironmentDigest() + require.NoError(t, err) + body, err := json.Marshal(function.PythonRoutineBody{ + DefinitionSchemaVersion: udf.PythonDefinitionSchemaVersion, + Handler: "f", + Source: source, + Mode: "SCALAR", + NullPolicy: udf.NullCallHandler, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + ArtifactDigest: udf.PythonInlineArtifactDigest("f", source), + EnvironmentDigest: environment, + SDKVersion: udf.PythonSDKVersion, + ArgTypes: []function.PythonTypeDescriptor{descriptor}, + ReturnType: &descriptor, + }) + require.NoError(t, err) + return string(body) +} + +func TestPersistPythonCreateRejectsMalformedDefinitionBeforeWriting(t *testing.T) { + bh := &backgroundExecTestWithHistory{} + bh.init() + err := persistUserDefinedFunction(context.Background(), bh, &TenantInfo{User: "owner"}, 7, userDefinedFunctionDefinition{ + name: "broken_python", + args: "[]", + argTypes: "[]", + retType: "int", + body: "not current python routine json", + lang: "python", + dbName: "db1", + }, nil) + + require.ErrorContains(t, err, "UNSUPPORTED_ROUTINE_VERSION") + require.Empty(t, bh.executedSqls) +} + +func TestNormalizePythonDefinitionRejectsCatalogSignatureDrift(t *testing.T) { + body := pythonCatalogTestBody(t, types.T_int64) + cases := []struct { + name string + args string + retType string + message string + }{ + { + name: "arguments", + args: `[{"name":"value","type":"varchar"}]`, + retType: "bigint", + message: "catalog arguments", + }, + { + name: "return", + args: `[{"name":"value","type":"bigint"}]`, + retType: "varchar", + message: "catalog return type", + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + _, err := normalizePythonFunctionDefinition(userDefinedFunctionDefinition{ + args: tc.args, + retType: tc.retType, + body: body, + }) + require.ErrorContains(t, err, "UNSUPPORTED_ROUTINE_VERSION") + require.ErrorContains(t, err, tc.message) + }) + } +} + +func TestNormalizePythonDefinitionDerivesLogicalSignatureFromTypedBody(t *testing.T) { + normalized, err := normalizePythonFunctionDefinition(userDefinedFunctionDefinition{ + args: `[{"name":"value","type":"int"}]`, + retType: "int", + body: pythonCatalogTestBody(t, types.T_int32), + }) + require.NoError(t, err) + require.Equal(t, `["int"]`, normalized.argTypes) +} + +func TestNormalizePythonDefinitionAcceptsDecimalLogicalAlias(t *testing.T) { + descriptor, err := function.NewPythonTypeDescriptor(types.New(types.T_decimal128, 38, 10)) + require.NoError(t, err) + source := "def f(ctx, value): return value" + environment, err := udf.PythonEnvironmentDigest() + require.NoError(t, err) + body, err := json.Marshal(function.PythonRoutineBody{ + DefinitionSchemaVersion: udf.PythonDefinitionSchemaVersion, + Handler: "f", + Source: source, + Mode: "SCALAR", + NullPolicy: udf.NullCallHandler, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + ArtifactDigest: udf.PythonInlineArtifactDigest("f", source), + EnvironmentDigest: environment, + SDKVersion: udf.PythonSDKVersion, + ArgTypes: []function.PythonTypeDescriptor{descriptor}, + ReturnType: &descriptor, + }) + require.NoError(t, err) + + normalized, err := normalizePythonFunctionDefinition(userDefinedFunctionDefinition{ + args: `[{"name":"value","type":"decimal"}]`, + retType: "decimal", + body: string(body), + }) + require.NoError(t, err) + require.Equal(t, `["decimal"]`, normalized.argTypes) +} + +func TestPersistPythonCreateIdentityLookupIncludesLanguage(t *testing.T) { + definition := userDefinedFunctionDefinition{ + name: "python_identity", + dbName: "db1", + canonicalInputDescriptor: "{\"types\":[]}", + lang: "python", + } + query := fmt.Sprintf( + `select function_id from mo_catalog.mo_user_defined_function where name = "%s" and db = "%s" and canonical_input_descriptor = "%s" and language = '%s' order by function_id desc limit 1;`, + escapeSQLStringForDoubleQuotes(definition.name), + escapeSQLStringForDoubleQuotes(definition.dbName), + escapeSQLStringForDoubleQuotes(definition.canonicalInputDescriptor), + escapeSQLStringForDoubleQuotes(definition.lang), + ) + b := &backgroundExecTest{} + b.init() + b.sql2result[query] = singleInt64Result("function_id", 101) + + id, err := findPersistedFunctionID(context.Background(), b, definition) + require.NoError(t, err) + require.Equal(t, int64(101), id) + require.Equal(t, []string{query}, b.executedSQLs) + require.Contains(t, b.executedSQLs[0], "language = 'python'") +} + +func TestPersistSQLCreateKeepsRollingCatalogCompatibility(t *testing.T) { + bh := &backgroundExecTestWithHistory{} + bh.init() + bh.sql2err[functionRevisionCatalogSchemaCheck] = moerr.NewNoSuchTableNoCtx( + "mo_catalog", "mo_function_revisions") + + err := persistUserDefinedFunction(context.Background(), bh, &TenantInfo{User: "owner"}, 7, userDefinedFunctionDefinition{ + name: "sql_function", + args: `[{"name":"value","type":"bigint"}]`, + argTypes: `["bigint"]`, + retType: "bigint", + body: "select value + 1", + lang: string(tree.SQL), + dbName: "db1", + }, nil) + require.NoError(t, err) + require.Len(t, bh.executedSqls, 2) + require.Equal(t, functionRevisionCatalogSchemaCheck, bh.executedSqls[0]) + require.NotContains(t, bh.executedSqls[1], "canonical_input_descriptor") + require.NotContains(t, bh.executedSqls[1], "mo_function_revisions") +} + +func TestFunctionRevisionCatalogAvailablePropagatesMalformedProbeResult(t *testing.T) { + bh := &backgroundExecTest{} + bh.init() + + available, err := functionRevisionCatalogAvailable(context.Background(), bh) + + require.ErrorContains(t, err, "it is not the type of result set") + require.False(t, available) +} + +func TestFunctionRevisionCatalogAvailableRejectsSplitOrEmptyProbe(t *testing.T) { + for _, tc := range []struct { + name string + results []interface{} + }{ + {name: "empty", results: []interface{}{}}, + {name: "split", results: []interface{}{emptyCatalogProbeResult(20), emptyCatalogProbeResult(20)}}, + } { + t.Run(tc.name, func(t *testing.T) { + bh := &backgroundExecTestWithResults{results: tc.results} + bh.init() + available, err := functionRevisionCatalogAvailable(context.Background(), bh) + require.ErrorContains(t, err, "expected exactly one") + require.False(t, available) + }) + } +} + +type backgroundExecTestWithResults struct { + backgroundExecTest + results []interface{} +} + +func (bt *backgroundExecTestWithResults) GetExecResultSet() []interface{} { + return bt.results +} + +func TestExactlyOneCatalogRowRejectsDuplicateOrSplitPointReads(t *testing.T) { + one := singleStringResult("value", "current") + row, err := exactlyOneCatalogRow(context.Background(), []ExecResult{one}, "routine point read") + require.NoError(t, err) + require.Same(t, one, row) + + one.AddRow([]interface{}{"duplicate"}) + _, err = exactlyOneCatalogRow(context.Background(), []ExecResult{one}, "routine point read") + require.ErrorContains(t, err, "expected exactly one") + + _, err = exactlyOneCatalogRow(context.Background(), []ExecResult{singleStringResult("value", "one"), singleStringResult("value", "two")}, "routine point read") + require.ErrorContains(t, err, "result sets") +} + +func TestPersistSQLCreatePublishesSharedRevisionWhenCatalogIsReady(t *testing.T) { + bh := &backgroundExecTestWithHistory{} + bh.init() + bh.sql2result[functionRevisionCatalogSchemaCheck] = emptyCatalogProbeResult(20) + definition := userDefinedFunctionDefinition{ + name: "sql_revision", + args: `[{"name":"value","type":"bigint"}]`, + argTypes: `["bigint"]`, + retType: "bigint", + body: "select value + 1", + lang: string(tree.SQL), + dbName: "db1", + } + findSQL := `select function_id from mo_catalog.mo_user_defined_function where name = "sql_revision" and db = "db1" and arg_types = '["bigint"]' and language = 'sql' order by function_id desc limit 1;` + bh.sql2result[findSQL] = singleInt64Result("function_id", 91) + + err := persistUserDefinedFunction(context.Background(), bh, &TenantInfo{User: "owner"}, 7, definition, nil) + require.NoError(t, err) + require.Len(t, bh.executedSqls, 5) + require.Equal(t, functionRevisionCatalogSchemaCheck, bh.executedSqls[0]) + require.Contains(t, bh.executedSqls[1], "insert into mo_catalog.mo_user_defined_function") + require.Equal(t, findSQL, bh.executedSqls[2]) + require.Contains(t, bh.executedSqls[3], "insert into mo_catalog.mo_function_revisions") + require.Contains(t, bh.executedSqls[3], `"sql_revision"`) + require.Contains(t, bh.executedSqls[3], `"select value + 1"`) + require.Contains(t, bh.executedSqls[4], "active_revision = 1, namespace_version = 1") +} + +func TestPersistPythonCreatePublishesInvokerSecurityType(t *testing.T) { + bh := &backgroundExecTestWithHistory{} + bh.init() + body := pythonCatalogTestBody(t, types.T_int64) + decoded, err := function.DecodePythonRoutineBody(body) + require.NoError(t, err) + canonicalInput, _, _, err := function.PythonSignatureMetadata(decoded.ArgTypes, decoded.ReturnType) + require.NoError(t, err) + definition := userDefinedFunctionDefinition{ + name: "python_invoker", + args: `[{"name":"value","type":"bigint"}]`, + argTypes: `["bigint"]`, + retType: "bigint", + body: body, + lang: string(tree.PYTHON), + dbName: "db1", + canonicalInputDescriptor: canonicalInput, + } + findSQL := fmt.Sprintf( + `select function_id from mo_catalog.mo_user_defined_function where name = "%s" and db = "%s" and canonical_input_descriptor = "%s" and language = '%s' order by function_id desc limit 1;`, + escapeSQLStringForDoubleQuotes(definition.name), + escapeSQLStringForDoubleQuotes(definition.dbName), + escapeSQLStringForDoubleQuotes(canonicalInput), + escapeSQLStringForDoubleQuotes(definition.lang), + ) + bh.sql2result[findSQL] = singleInt64Result("function_id", 94) + + err = persistUserDefinedFunction(context.Background(), bh, &TenantInfo{User: "owner"}, 7, definition, nil) + require.NoError(t, err) + require.GreaterOrEqual(t, len(bh.executedSqls), 1) + require.Contains(t, bh.executedSqls[0], `"FUNCTION","INVOKER"`) + for _, sql := range bh.executedSqls { + if strings.Contains(sql, "mo_function_revisions") { + require.Contains(t, sql, `"python_invoker"`) + } + } +} + +func TestPublishRestoredPythonArtifactsRepublishesExactAccountArtifact(t *testing.T) { + const ( + sid = "python-artifact-restore-test" + targetAccount = uint32(27) + ) + InitServerLevelVars(sid) + oldPU := getPuIfPresent(sid) + t.Cleanup(func() { setPu(sid, oldPU) }) + + fs, err := fileservice.NewMemoryFS(defines.SharedFileServiceName, fileservice.DisabledCacheConfig, nil) + require.NoError(t, err) + setPu(sid, &config.ParameterUnit{FileService: fs}) + + body := pythonCatalogTestBody(t, types.T_int64) + decoded, err := function.DecodePythonRoutineBody(body) + require.NoError(t, err) + const query = "select language, artifact_digest, body from mo_catalog.mo_function_revisions order by function_id, revision;" + bh := &backgroundExecTest{} + bh.init() + bh.sql2result[query] = newMrsForRestoreStringRows( + []string{"language", "artifact_digest", "body"}, + [][]interface{}{{"python", decoded.ArtifactDigest, body}}, + ) + + err = publishRestoredPythonArtifacts( + t.Context(), sid, + bh, + defines.AttachAccountId(t.Context(), targetAccount), targetAccount, + ) + require.NoError(t, err) + + store, err := pythonudf.NewFileArtifactStore(fs, pythonudf.DefaultMaxArtifactBytes) + require.NoError(t, err) + resolved, err := store.Resolve(t.Context(), uint64(targetAccount), decoded.Handler, decoded.ArtifactDigest) + require.NoError(t, err) + require.Equal(t, decoded.Source, resolved) + _, err = store.Resolve(t.Context(), uint64(targetAccount-1), decoded.Handler, decoded.ArtifactDigest) + require.ErrorContains(t, err, "unavailable") +} + +func TestPublishRestoredPythonArtifactsRejectsMissingArtifactStore(t *testing.T) { + const sid = "python-artifact-restore-missing-store-test" + InitServerLevelVars(sid) + oldPU := getPuIfPresent(sid) + t.Cleanup(func() { setPu(sid, oldPU) }) + setPu(sid, &config.ParameterUnit{}) + + body := pythonCatalogTestBody(t, types.T_int64) + decoded, err := function.DecodePythonRoutineBody(body) + require.NoError(t, err) + const query = "select language, artifact_digest, body from mo_catalog.mo_function_revisions order by function_id, revision;" + bh := &backgroundExecTest{} + bh.init() + bh.sql2result[query] = newMrsForRestoreStringRows( + []string{"language", "artifact_digest", "body"}, + [][]interface{}{{"python", decoded.ArtifactDigest, body}}, + ) + + err = publishRestoredPythonArtifacts( + t.Context(), sid, bh, + defines.AttachAccountId(t.Context(), 27), 27, + ) + require.ErrorContains(t, err, "artifact store is required") +} + +func TestPersistSQLReplacePublishesNextImmutableRevision(t *testing.T) { + bh := &backgroundExecTestWithHistory{} + bh.init() + bh.sql2result[functionRevisionCatalogSchemaCheck] = emptyCatalogProbeResult(20) + functionID := int64(92) + bh.sql2result[fmt.Sprintf( + "select language from mo_catalog.mo_user_defined_function where function_id = %d;", functionID, + )] = singleStringResult("language", string(tree.SQL)) + bh.sql2result[fmt.Sprintf( + "select active_revision, namespace_version from mo_catalog.mo_user_defined_function where function_id = %d;", functionID, + )] = func() *MysqlResultSet { + result := &MysqlResultSet{} + for _, name := range []string{"active_revision", "namespace_version"} { + column := &MysqlColumn{} + column.SetName(name) + column.SetColumnType(defines.MYSQL_TYPE_LONGLONG) + result.AddColumn(column) + } + result.AddRow([]interface{}{int64(2), int64(5)}) + return result + }() + bh.sql2result[fmt.Sprintf( + "select rettype from mo_catalog.mo_user_defined_function where function_id = %d;", functionID, + )] = singleStringResult("rettype", "bigint") + + err := persistUserDefinedFunction(context.Background(), bh, &TenantInfo{User: "owner"}, 7, userDefinedFunctionDefinition{ + name: "sql_revision", + args: `[{"name":"value","type":"bigint"}]`, + argTypes: `["bigint"]`, + retType: "bigint", + body: "select value + 2", + lang: string(tree.SQL), + dbName: "db1", + }, &functionID) + require.NoError(t, err) + require.Len(t, bh.executedSqls, 7) + require.Equal(t, functionRevisionCatalogSchemaCheck, bh.executedSqls[0]) + require.Contains(t, bh.executedSqls[4], "body = \"select value + 2\"") + require.Contains(t, bh.executedSqls[5], "function_id, revision, namespace_version") + require.Contains(t, bh.executedSqls[5], ", 3, 6,") + require.Contains(t, bh.executedSqls[6], "active_revision = 3, namespace_version = 6") +} + +func TestReadSQLRevisionBindsActiveHeadAndRejectsTampering(t *testing.T) { + const functionID = int64(93) + const args = `[{"name":"value","type":"bigint"}]` + const argTypes = `["bigint"]` + const body = "select value + 1" + const retType = "bigint" + fingerprint, err := function.SQLRoutineFingerprint(body, argTypes, retType) + require.NoError(t, err) + baseSQL := fmt.Sprintf("select active_revision, namespace_version, security_type from mo_catalog.mo_user_defined_function where function_id = %d;", functionID) + revisionSQL := fmt.Sprintf("select revision, args, arg_types, body, rettype, language, definition_schema_version, definition_fingerprint, volatility, null_policy, security_type from mo_catalog.mo_function_revisions where function_id = %d and revision = 1 and namespace_version = 1;", functionID) + newBase := func() *MysqlResultSet { + result := &MysqlResultSet{} + for _, name := range []string{"active_revision", "namespace_version", "security_type"} { + column := &MysqlColumn{} + column.SetName(name) + if name == "security_type" { + column.SetColumnType(defines.MYSQL_TYPE_VAR_STRING) + } else { + column.SetColumnType(defines.MYSQL_TYPE_LONGLONG) + } + result.AddColumn(column) + } + result.AddRow([]interface{}{int64(1), int64(1), "DEFINER"}) + return result + } + newRevision := func(candidateBody, candidateFingerprint string) *MysqlResultSet { + result := &MysqlResultSet{} + for _, name := range []string{"revision", "args", "arg_types", "body", "rettype", "language", "definition_schema_version", "definition_fingerprint", "volatility", "null_policy", "security_type"} { + column := &MysqlColumn{} + column.SetName(name) + if name == "revision" || name == "definition_schema_version" { + column.SetColumnType(defines.MYSQL_TYPE_LONGLONG) + } else { + column.SetColumnType(defines.MYSQL_TYPE_VAR_STRING) + } + result.AddColumn(column) + } + result.AddRow([]interface{}{int64(1), args, argTypes, candidateBody, retType, string(tree.SQL), int64(udf.SQLDefinitionSchemaVersion), candidateFingerprint, "VOLATILE", udf.NullCallHandler, "DEFINER"}) + return result + } + + bh := &backgroundExecTest{} + bh.init() + bh.sql2result[baseSQL] = newBase() + bh.sql2result[revisionSQL] = newRevision(body, fingerprint) + got, found, err := readSQLRevision(context.Background(), bh, functionID, nil) + require.NoError(t, err) + require.True(t, found) + require.Equal(t, uint64(1), got.Revision) + require.Equal(t, body, got.Body) + require.Equal(t, fingerprint, got.DefinitionFingerprint) + + bh.init() + bh.sql2result[baseSQL] = newBase() + bh.sql2result[revisionSQL] = newRevision(body, strings.Repeat("a", 64)) + _, found, err = readSQLRevision(context.Background(), bh, functionID, nil) + require.ErrorContains(t, err, "fingerprint mismatch") + require.False(t, found) + + for _, tc := range []struct { + name string + mutateBase func(*MysqlResultSet) + mutateVersion func(*MysqlResultSet) + wantError string + wantFound bool + }{ + { + name: "legacy head before shared revision upgrade", + mutateBase: func(result *MysqlResultSet) { + result.Data[0][0], result.Data[0][1] = int64(0), int64(0) + }, + }, + { + name: "partial revision head", + mutateBase: func(result *MysqlResultSet) { + result.Data[0][0] = int64(0) + }, + wantError: "invalid revision head", + }, + { + name: "missing active revision row", + mutateVersion: func(result *MysqlResultSet) { + result.Data = nil + }, + wantError: "expected exactly one", + }, + { + name: "revision id differs from head", + mutateVersion: func(result *MysqlResultSet) { + result.Data[0][0] = int64(2) + }, + wantError: "revision contract is not supported", + }, + { + name: "wrong implementation language", + mutateVersion: func(result *MysqlResultSet) { + result.Data[0][5] = "python" + }, + wantError: "revision contract is not supported", + }, + { + name: "wrong definition schema", + mutateVersion: func(result *MysqlResultSet) { + result.Data[0][6] = int64(udf.SQLDefinitionSchemaVersion + 100) + }, + wantError: "revision contract is not supported", + }, + { + name: "non volatile revision", + mutateVersion: func(result *MysqlResultSet) { + result.Data[0][8] = "IMMUTABLE" + }, + wantError: "revision contract is not supported", + }, + { + name: "wrong null policy", + mutateVersion: func(result *MysqlResultSet) { + result.Data[0][9] = "STRICT" + }, + wantError: "revision contract is not supported", + }, + { + name: "security contract differs from head", + mutateVersion: func(result *MysqlResultSet) { + result.Data[0][10] = "INVOKER" + }, + wantError: "revision contract is not supported", + }, + { + name: "malformed logical argument metadata", + mutateVersion: func(result *MysqlResultSet) { + result.Data[0][1] = "{" + }, + wantError: "argument metadata is invalid", + }, + { + name: "logical argument metadata disagrees", + mutateVersion: func(result *MysqlResultSet) { + result.Data[0][2] = `["int"]` + }, + wantError: "argument metadata is invalid", + }, + } { + t.Run(tc.name, func(t *testing.T) { + background := &backgroundExecTest{} + background.init() + base := newBase() + if tc.mutateBase != nil { + tc.mutateBase(base) + } + background.sql2result[baseSQL] = base + version := newRevision(body, fingerprint) + if tc.mutateVersion != nil { + tc.mutateVersion(version) + } + background.sql2result[revisionSQL] = version + _, found, err := readSQLRevision(context.Background(), background, functionID, nil) + if tc.wantError != "" { + require.ErrorContains(t, err, tc.wantError) + require.False(t, found) + return + } + require.NoError(t, err) + require.Equal(t, tc.wantFound, found) + }) + } +} + +func TestEnsurePythonUdfCatalogReadyRequiresCurrentSchema(t *testing.T) { + bh := &backgroundExecTestWithHistory{} + bh.init() + bh.sql2result[pythonUdfCatalogIdentitySchemaCheck] = emptyCatalogProbeResult(6) + bh.sql2result[functionRevisionCatalogSchemaCheck] = emptyCatalogProbeResult(20) + require.NoError(t, ensurePythonUdfCatalogReady(context.Background(), bh)) + require.Equal(t, []string{ + pythonUdfCatalogIdentitySchemaCheck, + functionRevisionCatalogSchemaCheck, + }, bh.executedSqls) + + bh.init() + bh.sql2result[pythonUdfCatalogIdentitySchemaCheck] = emptyCatalogProbeResult(6) + wantErr := fmt.Errorf("missing current revision catalog") + bh.sql2err[functionRevisionCatalogSchemaCheck] = wantErr + err := ensurePythonUdfCatalogReady(context.Background(), bh) + require.ErrorContains(t, err, "Python UDF catalog contract is not ready") + require.ErrorContains(t, err, wantErr.Error()) + require.Equal(t, []string{ + pythonUdfCatalogIdentitySchemaCheck, + functionRevisionCatalogSchemaCheck, + }, bh.executedSqls) + + bh.init() + bh.sql2result[pythonUdfCatalogIdentitySchemaCheck] = emptyCatalogProbeResult(1) + bh.sql2result[functionRevisionCatalogSchemaCheck] = emptyCatalogProbeResult(20) + err = ensurePythonUdfCatalogReady(context.Background(), bh) + require.ErrorContains(t, err, "catalog probe returned 1 columns, expected 6") +} + +func emptyCatalogProbeResult(columnCount int) *MysqlResultSet { + result := &MysqlResultSet{} + for index := 0; index < columnCount; index++ { + column := &MysqlColumn{} + column.SetName(fmt.Sprintf("column_%d", index)) + column.SetColumnType(defines.MYSQL_TYPE_VAR_STRING) + result.AddColumn(column) + } + values := make([]interface{}, columnCount) + for index := range values { + values[index] = int64(0) + } + result.AddRow(values) + return result +} + +func TestValidateRestoredPythonRevisionCatalogChecksCurrentContract(t *testing.T) { + body := pythonCatalogTestBody(t, types.T_int64) + fingerprint, err := function.PythonRoutineFingerprint(body) + require.NoError(t, err) + decodedBody, err := function.DecodePythonRoutineBody(body) + require.NoError(t, err) + inputDescriptor, _, _, err := function.PythonSignatureMetadata(decodedBody.ArgTypes, decodedBody.ReturnType) + require.NoError(t, err) + query := fmt.Sprintf( + "select %s from %s order by function_id, revision;", + functionRevisionCatalogColumns, + qualifiedTableName(moCatalog, "mo_function_revisions"), + ) + result := &MysqlResultSet{} + for index := 0; index < 20; index++ { + column := &MysqlColumn{} + column.SetName(fmt.Sprintf("column_%d", index)) + column.SetColumnType(defines.MYSQL_TYPE_VAR_STRING) + result.AddColumn(column) + } + result.AddRow([]interface{}{ + "44", "1", "1", "f", `[ {"name":"value","type":"bigint"} ]`, inputDescriptor, "bigint", body, + "python", "1", udf.PythonABIContract, udf.PythonAdapterVersion, + udf.PythonInlineArtifactDigest("f", "def f(ctx, value): return value"), + func() string { + value, digestErr := udf.PythonEnvironmentDigest() + require.NoError(t, digestErr) + return value + }(), + udf.PythonSDKVersion, udf.NullCallHandler, "VOLATILE", fingerprint, "2026-09-11 00:00:00", "INVOKER", + }) + + bh := &backgroundExecTest{} + bh.init() + bh.sql2result[query] = result + require.NoError(t, validateRestoredFunctionRevisionCatalog(context.Background(), bh, context.Background())) + + result.Data[0][17] = "stale-fingerprint" + bh.init() + bh.sql2result[query] = result + require.ErrorContains(t, + validateRestoredFunctionRevisionCatalog(context.Background(), bh, context.Background()), + "fingerprint mismatch", + ) +} + +func TestValidateRestoredPythonRevisionCatalogRejectsMalformedContracts(t *testing.T) { + body := pythonCatalogTestBody(t, types.T_int64) + decoded, err := function.DecodePythonRoutineBody(body) + require.NoError(t, err) + inputDescriptor, _, _, err := function.PythonSignatureMetadata(decoded.ArgTypes, decoded.ReturnType) + require.NoError(t, err) + fingerprint, err := function.PythonRoutineFingerprint(body) + require.NoError(t, err) + baseRow := []string{ + "44", "1", "1", "f", `[{"name":"value","type":"bigint"}]`, inputDescriptor, "bigint", body, + udf.LanguagePython, strconv.Itoa(udf.PythonDefinitionSchemaVersion), udf.PythonABIContract, + udf.PythonAdapterVersion, decoded.ArtifactDigest, decoded.EnvironmentDigest, udf.PythonSDKVersion, + decoded.NullPolicy, "VOLATILE", fingerprint, "2026-09-11 00:00:00", "INVOKER", + } + query := fmt.Sprintf( + "select %s from %s order by function_id, revision;", + functionRevisionCatalogColumns, + qualifiedTableName(moCatalog, "mo_function_revisions"), + ) + newResult := func(row []string) *MysqlResultSet { + result := &MysqlResultSet{} + for index := range row { + column := &MysqlColumn{} + column.SetName(fmt.Sprintf("column_%d", index)) + column.SetColumnType(defines.MYSQL_TYPE_VAR_STRING) + result.AddColumn(column) + } + values := make([]interface{}, len(row)) + for index := range row { + values[index] = row[index] + } + result.AddRow(values) + return result + } + for _, tc := range []struct { + name string + index int + value string + want string + }{ + {name: "function identity", index: 0, value: "not-an-id", want: "invalid function identity"}, + {name: "zero revision", index: 1, value: "0", want: "invalid revision"}, + {name: "zero namespace", index: 2, value: "0", want: "invalid namespace version"}, + {name: "definition schema", index: 9, value: "future", want: "invalid definition schema"}, + {name: "unsupported ABI", index: 10, value: "future-abi", want: "unsupported execution contract"}, + {name: "body encoding", index: 7, value: "{", want: "body is invalid"}, + {name: "artifact digest binding", index: 12, value: strings.Repeat("a", 64), want: "metadata does not match"}, + {name: "argument JSON", index: 4, value: "{", want: "arguments are invalid"}, + {name: "argument descriptor", index: 5, value: "stale-descriptor", want: "argument descriptor mismatch"}, + {name: "volatility", index: 16, value: "IMMUTABLE", want: "unsupported execution contract"}, + {name: "security mode", index: 19, value: "DEFINER", want: "unsupported execution contract"}, + } { + t.Run(tc.name, func(t *testing.T) { + row := append([]string(nil), baseRow...) + row[tc.index] = tc.value + background := &backgroundExecTest{} + background.init() + background.sql2result[query] = newResult(row) + err := validateRestoredFunctionRevisionCatalog(context.Background(), background, context.Background()) + require.ErrorContains(t, err, tc.want) + }) + } +} + +func TestValidateRestoredSharedRevisionCatalogAcceptsSQLAndRejectsTampering(t *testing.T) { + args := `[ {"name":"value","type":"bigint"} ]` + argTypes, err := userDefinedFunctionArgumentTypesFromJSON(args) + require.NoError(t, err) + body := "select value + 1" + retType := "bigint" + fingerprint, err := function.SQLRoutineFingerprint(body, argTypes, retType) + require.NoError(t, err) + query := fmt.Sprintf( + "select %s from %s order by function_id, revision;", + functionRevisionCatalogColumns, + qualifiedTableName(moCatalog, "mo_function_revisions"), + ) + newResult := func(body, digest string) *MysqlResultSet { + result := &MysqlResultSet{} + for index := 0; index < 20; index++ { + column := &MysqlColumn{} + column.SetName(fmt.Sprintf("column_%d", index)) + column.SetColumnType(defines.MYSQL_TYPE_VAR_STRING) + result.AddColumn(column) + } + result.AddRow([]interface{}{ + "45", "1", "1", "f", args, argTypes, retType, body, + string(tree.SQL), strconv.Itoa(udf.SQLDefinitionSchemaVersion), "", "", "", "", "", + udf.NullCallHandler, "VOLATILE", digest, "2026-09-11 00:00:00", "DEFINER", + }) + return result + } + + bh := &backgroundExecTest{} + bh.init() + bh.sql2result[query] = newResult(body, fingerprint) + require.NoError(t, validateRestoredFunctionRevisionCatalog(context.Background(), bh, context.Background())) + + bh.init() + bh.sql2result[query] = newResult("select value + 2", fingerprint) + require.ErrorContains(t, + validateRestoredFunctionRevisionCatalog(context.Background(), bh, context.Background()), + "fingerprint mismatch", + ) +} + +func TestValidateRestoredPythonCatalogHeadsBindsIdentityToActiveRevision(t *testing.T) { + body := pythonCatalogTestBody(t, types.T_int64) + decoded, err := function.DecodePythonRoutineBody(body) + require.NoError(t, err) + input, output, signature, err := function.PythonSignatureMetadata(decoded.ArgTypes, decoded.ReturnType) + require.NoError(t, err) + fingerprint, err := function.PythonRoutineFingerprint(body) + require.NoError(t, err) + query := `select cast(f.function_id as char), cast(f.active_revision as char), cast(f.namespace_version as char), + cast(coalesce(r.revision, 0) as char), cast(coalesce(r.namespace_version, 0) as char), + f.canonical_input_descriptor, f.return_descriptor, + cast(f.signature_key_schema_version as char), f.signature_fingerprint, + coalesce(r.arg_types, ''), coalesce(r.rettype, ''), coalesce(r.body, ''), + lower(f.language), coalesce(r.definition_fingerprint, ''), + coalesce(r.security_type, ''), coalesce(f.security_type, '') + from mo_catalog.mo_user_defined_function f + left join mo_catalog.mo_function_revisions r + on r.function_id = f.function_id and r.revision = f.active_revision + and r.namespace_version = f.namespace_version + where lower(f.language) in ("python", "sql") + order by f.function_id;` + newResult := func() *MysqlResultSet { + result := &MysqlResultSet{} + for index := 0; index < 16; index++ { + column := &MysqlColumn{} + column.SetName(fmt.Sprintf("column_%d", index)) + column.SetColumnType(defines.MYSQL_TYPE_VAR_STRING) + result.AddColumn(column) + } + result.AddRow([]interface{}{ + "44", "2", "3", "2", "3", input, output, + fmt.Sprintf("%d", udf.PythonSignatureKeySchemaVersion), signature, + input, "bigint", body, string(tree.PYTHON), fingerprint, + "INVOKER", "INVOKER", + }) + return result + } + + b := &backgroundExecTest{} + b.init() + b.sql2result[query] = newResult() + require.NoError(t, validateRestoredFunctionCatalogHeads(context.Background(), b, context.Background())) + + mutated := newResult() + mutated.Data[0][1] = "1" + b.init() + b.sql2result[query] = mutated + require.ErrorContains(t, + validateRestoredFunctionCatalogHeads(context.Background(), b, context.Background()), + "active revision does not exist", + ) + + mutated = newResult() + mutated.Data[0][8] = "stale-signature" + b.init() + b.sql2result[query] = mutated + require.ErrorContains(t, + validateRestoredFunctionCatalogHeads(context.Background(), b, context.Background()), + "head identity does not match", + ) +} + +func TestValidateRestoredLegacyPythonHeadIsPreservedButInert(t *testing.T) { + query := `select cast(f.function_id as char), cast(f.active_revision as char), cast(f.namespace_version as char), + cast(coalesce(r.revision, 0) as char), cast(coalesce(r.namespace_version, 0) as char), + f.canonical_input_descriptor, f.return_descriptor, + cast(f.signature_key_schema_version as char), f.signature_fingerprint, + coalesce(r.arg_types, ''), coalesce(r.rettype, ''), coalesce(r.body, ''), + lower(f.language), coalesce(r.definition_fingerprint, ''), + coalesce(r.security_type, ''), coalesce(f.security_type, '') + from mo_catalog.mo_user_defined_function f + left join mo_catalog.mo_function_revisions r + on r.function_id = f.function_id and r.revision = f.active_revision + and r.namespace_version = f.namespace_version + where lower(f.language) in ("python", "sql") + order by f.function_id;` + legacy := func(active, namespace string) *MysqlResultSet { + result := &MysqlResultSet{} + for index := 0; index < 16; index++ { + column := &MysqlColumn{} + column.SetName(fmt.Sprintf("column_%d", index)) + column.SetColumnType(defines.MYSQL_TYPE_VAR_STRING) + result.AddColumn(column) + } + result.AddRow([]interface{}{ + "46", active, namespace, "0", "0", "", "", "0", "", "", "", "", + string(tree.PYTHON), "", "INVOKER", "INVOKER", + }) + return result + } + + b := &backgroundExecTest{} + b.init() + b.sql2result[query] = legacy("0", "0") + require.NoError(t, validateRestoredFunctionCatalogHeads(context.Background(), b, context.Background())) + + b.init() + b.sql2result[query] = legacy("1", "0") + require.ErrorContains(t, + validateRestoredFunctionCatalogHeads(context.Background(), b, context.Background()), + "invalid namespace version", + ) +} + +func TestValidateRestoredSharedCatalogHeadsChecksSQLRevision(t *testing.T) { + args := `[ {"name":"value","type":"bigint"} ]` + argTypes, err := userDefinedFunctionArgumentTypesFromJSON(args) + require.NoError(t, err) + body := "select value + 1" + retType := "bigint" + fingerprint, err := function.SQLRoutineFingerprint(body, argTypes, retType) + require.NoError(t, err) + query := `select cast(f.function_id as char), cast(f.active_revision as char), cast(f.namespace_version as char), + cast(coalesce(r.revision, 0) as char), cast(coalesce(r.namespace_version, 0) as char), + f.canonical_input_descriptor, f.return_descriptor, + cast(f.signature_key_schema_version as char), f.signature_fingerprint, + coalesce(r.arg_types, ''), coalesce(r.rettype, ''), coalesce(r.body, ''), + lower(f.language), coalesce(r.definition_fingerprint, ''), + coalesce(r.security_type, ''), coalesce(f.security_type, '') + from mo_catalog.mo_user_defined_function f + left join mo_catalog.mo_function_revisions r + on r.function_id = f.function_id and r.revision = f.active_revision + and r.namespace_version = f.namespace_version + where lower(f.language) in ("python", "sql") + order by f.function_id;` + newResult := func(body, digest string) *MysqlResultSet { + result := &MysqlResultSet{} + for index := 0; index < 16; index++ { + column := &MysqlColumn{} + column.SetName(fmt.Sprintf("column_%d", index)) + column.SetColumnType(defines.MYSQL_TYPE_VAR_STRING) + result.AddColumn(column) + } + result.AddRow([]interface{}{ + "45", "1", "1", "1", "1", "", "", "0", "", + argTypes, retType, body, string(tree.SQL), digest, + "DEFINER", "DEFINER", + }) + return result + } + + b := &backgroundExecTest{} + b.init() + b.sql2result[query] = newResult(body, fingerprint) + require.NoError(t, validateRestoredFunctionCatalogHeads(context.Background(), b, context.Background())) + + b.init() + b.sql2result[query] = newResult("select value + 2", fingerprint) + require.ErrorContains(t, + validateRestoredFunctionCatalogHeads(context.Background(), b, context.Background()), + "head fingerprint does not match", + ) +} + +func TestReadPythonRevisionRequiresPersistedIdentitySignature(t *testing.T) { + body := pythonCatalogTestBody(t, types.T_int64) + inputDescriptor, returnDescriptor, signatureFingerprint, err := func() (string, string, string, error) { + decoded, decodeErr := function.DecodePythonRoutineBody(body) + if decodeErr != nil { + return "", "", "", decodeErr + } + return function.PythonSignatureMetadata(decoded.ArgTypes, decoded.ReturnType) + }() + require.NoError(t, err) + fingerprint, err := function.PythonRoutineFingerprint(body) + require.NoError(t, err) + environment, err := udf.PythonEnvironmentDigest() + require.NoError(t, err) + query := pythonRevisionCatalogSQL(nil, 44) + result := &MysqlResultSet{} + for index := 0; index < 23; index++ { + column := &MysqlColumn{} + column.SetName(fmt.Sprintf("column_%d", index)) + if index == 0 || index == 1 || index == 2 || index == 5 || index == 12 { + column.SetColumnType(defines.MYSQL_TYPE_LONGLONG) + } else { + column.SetColumnType(defines.MYSQL_TYPE_VAR_STRING) + } + result.AddColumn(column) + } + result.AddRow([]interface{}{ + int64(1), int64(1), int64(1), inputDescriptor, returnDescriptor, int64(udf.PythonSignatureKeySchemaVersion), signatureFingerprint, + `[{"name":"value","type":"bigint"}]`, inputDescriptor, body, "python", "bigint", int64(udf.PythonDefinitionSchemaVersion), + udf.PythonABIContract, udf.PythonAdapterVersion, udf.PythonSDKVersion, udf.NullCallHandler, "VOLATILE", fingerprint, + udf.PythonInlineArtifactDigest("f", "def f(ctx, value): return value"), environment, + "INVOKER", "INVOKER", + }) + bh := &backgroundExecTest{} + bh.init() + bh.sql2result[query] = result + revision, err := readPythonRevision(context.Background(), bh, 44, nil) + require.NoError(t, err) + require.Equal(t, uint64(1), revision.Revision) + require.Equal(t, inputDescriptor, revision.CanonicalInputDescriptor) + + result.Data[0][3] = "[]" + bh.init() + bh.sql2result[query] = result + _, err = readPythonRevision(context.Background(), bh, 44, nil) + require.ErrorContains(t, err, "identity descriptor metadata mismatch") + + result.Data[0][3] = inputDescriptor + result.Data[0][8] = "[]" + bh.init() + bh.sql2result[query] = result + _, err = readPythonRevision(context.Background(), bh, 44, nil) + require.ErrorContains(t, err, "revision argument descriptor mismatch") + + result.Data[0][8] = inputDescriptor + result.Data[0][21] = "DEFINER" + bh.init() + bh.sql2result[query] = result + _, err = readPythonRevision(context.Background(), bh, 44, nil) + require.ErrorContains(t, err, "revision contract is not supported") +} + +func TestMatchUserDefinedFunctionCandidatesUsesExactPythonDescriptor(t *testing.T) { + decimal2, err := function.NewPythonTypeDescriptor(types.New(types.T_decimal64, 18, 2)) + require.NoError(t, err) + decimal6, err := function.NewPythonTypeDescriptor(types.New(types.T_decimal64, 18, 6)) + require.NoError(t, err) + returnType, err := function.NewPythonTypeDescriptor(types.T_decimal64.ToType()) + require.NoError(t, err) + exact2, err := canonicalPythonInputDescriptor([]function.PythonTypeDescriptor{decimal2}, &returnType) + require.NoError(t, err) + exact6, err := canonicalPythonInputDescriptor([]function.PythonTypeDescriptor{decimal6}, &returnType) + require.NoError(t, err) + + result := &MysqlResultSet{} + for _, name := range []string{"function_id", "args", "language", "arg_types", "canonical_input_descriptor"} { + column := &MysqlColumn{} + column.SetName(name) + if name == "function_id" { + column.SetColumnType(defines.MYSQL_TYPE_LONGLONG) + } else { + column.SetColumnType(defines.MYSQL_TYPE_VAR_STRING) + } + result.AddColumn(column) + } + result.AddRow([]interface{}{int64(51), `[{"name":"value","type":"decimal"}]`, "python", exact2, exact2}) + result.AddRow([]interface{}{int64(52), `[{"name":"value","type":"decimal"}]`, "python", exact6, exact6}) + result.AddRow([]interface{}{int64(53), `[{"name":"value","type":"decimal"}]`, "sql", `["decimal"]`, ""}) + + ids, err := matchUserDefinedFunctionCandidates(context.Background(), []ExecResult{result}, "python", `["decimal"]`, exact2) + require.NoError(t, err) + // A SQL routine with the same logical signature still occupies the shared + // namespace. The exact descriptor distinguishes the two Python overloads; + // it does not permit an ambiguous SQL/Python pair. + require.Equal(t, []int64{51, 53}, ids) + + ids, err = matchUserDefinedFunctionCandidates(context.Background(), []ExecResult{result}, "sql", `["decimal"]`, `["decimal"]`) + require.NoError(t, err) + require.Equal(t, []int64{51, 52, 53}, ids) +} + +func TestMatchUserDefinedFunctionCandidatesRejectsPythonRowWithoutExactDescriptor(t *testing.T) { + result := &MysqlResultSet{} + for _, name := range []string{"function_id", "args", "language", "arg_types", "canonical_input_descriptor"} { + column := &MysqlColumn{} + column.SetName(name) + if name == "function_id" { + column.SetColumnType(defines.MYSQL_TYPE_LONGLONG) + } else { + column.SetColumnType(defines.MYSQL_TYPE_VAR_STRING) + } + result.AddColumn(column) + } + result.AddRow([]interface{}{int64(54), `[{"name":"value","type":"int"}]`, "python", `["int"]`, ""}) + + _, err := matchUserDefinedFunctionCandidates(context.Background(), []ExecResult{result}, "python", `["int"]`, `{"types":[]}`) + require.ErrorContains(t, err, "has no exact input descriptor") +} + +func TestMatchUserDefinedFunctionCandidatesRejectsSplitResultSets(t *testing.T) { + result := emptyCatalogProbeResult(5) + _, err := matchUserDefinedFunctionCandidates( + context.Background(), + []ExecResult{result, result}, + string(tree.PYTHON), `[]`, `[]`, + ) + require.ErrorContains(t, err, "function catalog candidate lookup returned 2 result sets") +} + +func TestMatchUserDefinedFunctionCandidatesAcceptsEmptyLookup(t *testing.T) { + ids, err := matchUserDefinedFunctionCandidates( + context.Background(), nil, + string(tree.PYTHON), `[]`, `[]`, + ) + require.NoError(t, err) + require.Empty(t, ids) +} + +func TestPythonDropSignatureUsesExactDescriptor(t *testing.T) { + statement, err := parsers.ParseOne(context.Background(), dialect.MYSQL, "drop function db.f(decimal(18,2))", 1) + require.NoError(t, err) + defer statement.Free() + drop, ok := statement.(*tree.DropFunction) + require.True(t, ok) + + decimal2, err := function.NewPythonTypeDescriptor(types.New(types.T_decimal128, 18, 2)) + require.NoError(t, err) + decimal6, err := function.NewPythonTypeDescriptor(types.New(types.T_decimal128, 18, 6)) + require.NoError(t, err) + returnType, err := function.NewPythonTypeDescriptor(types.T_decimal64.ToType()) + require.NoError(t, err) + makeBody := func(argument function.PythonTypeDescriptor) string { + source := "def f(ctx, value): return value" + environment, environmentErr := udf.PythonEnvironmentDigest() + require.NoError(t, environmentErr) + body, bodyErr := json.Marshal(function.PythonRoutineBody{ + DefinitionSchemaVersion: udf.PythonDefinitionSchemaVersion, + Handler: "f", + Source: source, + Mode: "SCALAR", + NullPolicy: udf.NullCallHandler, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + ArtifactDigest: udf.PythonInlineArtifactDigest("f", source), + EnvironmentDigest: environment, + SDKVersion: udf.PythonSDKVersion, + ArgTypes: []function.PythonTypeDescriptor{argument}, + ReturnType: &returnType, + }) + require.NoError(t, bodyErr) + return string(body) + } + + require.True(t, pythonDropSignatureMatches(drop.Args, makeBody(decimal2))) + require.False(t, pythonDropSignatureMatches(drop.Args, makeBody(decimal6))) + + // Exercise the catalog projection wiring, not only the descriptor helper. + ctrl := gomock.NewController(t) + ses := newSes(nil, ctrl) + ctx := ses.GetTxnHandler().GetTxnCtx() + bh := &backgroundExecTest{} + bh.init() + stub := gostub.StubFunc(&NewBackgroundExec, bh) + defer stub.Reset() + checkDB, err := getSqlForCheckDatabaseByAccount(ctx, "db") + require.NoError(t, err) + bh.sql2result[checkDB] = newMrsForCheckDatabase([][]interface{}{{int64(1)}}) + bh.sql2result[fmt.Sprintf(checkUdfArgs, "f", "db")] = newMrsForCheckUdfArgs([][]interface{}{ + {`[{"name":"value","type":"decimal"}]`, int64(101), makeBody(decimal2)}, + {`[{"name":"value","type":"decimal"}]`, int64(102), makeBody(decimal6)}, + }) + require.NoError(t, doDropFunction(ctx, ses, drop, nil)) + require.Contains(t, bh.executedSQLs, fmt.Sprintf(deleteUserDefinedFunctionFormat, 101)) + require.Contains(t, bh.executedSQLs, fmt.Sprintf(deleteUserDefinedFunctionRevisionsFormat, 101)) + require.NotContains(t, bh.executedSQLs, fmt.Sprintf(deleteUserDefinedFunctionFormat, 102)) + require.NotContains(t, bh.executedSQLs, fmt.Sprintf(deleteUserDefinedFunctionRevisionsFormat, 102)) +} diff --git a/pkg/frontend/routine_error_contract_test.go b/pkg/frontend/routine_error_contract_test.go new file mode 100644 index 0000000000000..50d7f732c5246 --- /dev/null +++ b/pkg/frontend/routine_error_contract_test.go @@ -0,0 +1,41 @@ +// Copyright 2026 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 frontend + +import ( + "testing" + + "github.com/matrixorigin/matrixone/pkg/common/moerr" + "github.com/matrixorigin/matrixone/pkg/udf/udferr" + "github.com/matrixorigin/matrixone/pkg/util/errutil" + "github.com/stretchr/testify/require" +) + +func TestRoutineDiagnosticSQLContract(t *testing.T) { + cause := udferr.New("TYPE_CONTRACT: result length mismatch") + for _, err := range []error{cause, errutil.Wrapf(cause, "python udf: worker error")} { + code, state, message := RewriteError(err, "") + require.Equal(t, uint16(moerr.ER_INTERNAL_ERROR), code) + require.Equal(t, "HY000", state) + require.Equal(t, err.Error(), message) + } + + // Existing MO-classified errors retain their own SQL mapping. + classified := moerr.NewInternalErrorNoCtx("classified") + code, state, message := RewriteError(classified, "") + require.Equal(t, classified.ErrorCode(), code) + require.Equal(t, classified.SqlState(), state) + require.Equal(t, "internal error: classified", message) +} diff --git a/pkg/frontend/routine_namespace.go b/pkg/frontend/routine_namespace.go new file mode 100644 index 0000000000000..6d89b74bc617c --- /dev/null +++ b/pkg/frontend/routine_namespace.go @@ -0,0 +1,181 @@ +// Copyright 2026 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 frontend + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "sort" + "strconv" + "strings" + + "github.com/matrixorigin/matrixone/pkg/udf/udferr" + "github.com/matrixorigin/matrixone/pkg/util/errutil" + + planpb "github.com/matrixorigin/matrixone/pkg/pb/plan" +) + +var errRoutineNamespaceBudget = udferr.New("routine namespace cache budget exceeded") + +const maxRoutineNamespaceRows = 65536 +const maxRoutineNamespaceBytes = 64 << 20 + +// readRoutineNamespaces reads the complete candidate set, not just matching +// signatures. The selected identity locates its database/name under the tenant +// context; all languages participate. Revision-local namespace_version remains +// immutable. The separate digest is state-based and naturally follows rollback, +// snapshot/PITR and clone publication without a second mutable catalog index. +func readRoutineNamespaces(ctx context.Context, bh BackgroundExec, ids []uint64, snapshot *planpb.Snapshot) (map[uint64]string, error) { + bh.ClearExecResultSet() + if err := bh.Exec(ctx, routineNamespacesSQL(ids, snapshot)); err != nil { + return nil, err + } + rows, err := getResultSet(ctx, bh) + if err != nil { + return nil, err + } + row, err := candidateCatalogResultSet(rows, "routine namespaces") + if err != nil { + return nil, err + } + if row == nil { + return map[uint64]string{}, nil + } + return decodeRoutineNamespaces(ctx, row) +} + +func routineNamespacesSQL(ids []uint64, snapshot *planpb.Snapshot) string { + values := make([]string, len(ids)) + for i, id := range ids { + values[i] = strconv.FormatUint(id, 10) + } + suffix := "" + if snapshot != nil && snapshot.TS != nil { + suffix = fmt.Sprintf(" {MO_TS = %d}", snapshot.TS.PhysicalTime) + } + // Read both base and revision metadata: legacy SQL resolves the base, typed + // SQL/Python resolves the immutable revision. Never drop an unmatching sibling. + + return fmt.Sprintf(`select selected.function_id, f.function_id, f.active_revision, f.namespace_version, + sha2(cast(f.args as varchar),256), sha2(f.body,256), sha2(f.language,256), sha2(f.rettype,256), sha2(f.db,256), sha2(f.sql_mode,256), sha2(f.security_type,256), + sha2(cast(coalesce(r.args,'[]') as varchar),256), sha2(coalesce(r.body,''),256), sha2(coalesce(r.language,''),256), sha2(coalesce(r.rettype,''),256), sha2(coalesce(r.security_type,''),256) + from (select db,name,min(function_id) as function_id from mo_catalog.mo_user_defined_function%s where function_id in (%s) group by db,name) selected + join mo_catalog.mo_user_defined_function%s f on f.db=selected.db and f.name=selected.name + left join mo_catalog.mo_function_revisions%s r on r.function_id=f.function_id and r.revision=f.active_revision and r.namespace_version=f.namespace_version + limit %d;`, suffix, strings.Join(values, ","), suffix, suffix, maxRoutineNamespaceRows+1) +} + +func decodeRoutineNamespaces(ctx context.Context, rows ExecResult) (map[uint64]string, error) { + if rows.GetRowCount() > maxRoutineNamespaceRows { + return nil, errutil.WrapfCauseFirst(errRoutineNamespaceBudget, "namespace rows exceed %d", maxRoutineNamespaceRows) + } + groups := make(map[uint64]map[uint64]string) + remaining := maxRoutineNamespaceBytes + for row := uint64(0); row < rows.GetRowCount(); row++ { + var numbers [4]uint64 + for col := range numbers { + value, err := rows.GetUint64(ctx, row, uint64(col)) + if err != nil { + return nil, err + } + numbers[col] = value + } + var fields [12]string + for col := range fields { + value, err := rows.GetString(ctx, row, uint64(col+4)) + if err != nil { + return nil, err + } + if len(value) > remaining { + return nil, errutil.WrapfCauseFirst(errRoutineNamespaceBudget, "namespace bytes exceed %d", maxRoutineNamespaceBytes) + } + remaining -= len(value) + fields[col] = value + } + // JSON arrays give unambiguous length/escaping, with fixed version/domain. + // Exclude selected id so different overloads in one namespace share a token. + encoded, err := json.Marshal(struct { + Version int + Identity [3]uint64 + Fields [12]string + }{1, [3]uint64{numbers[1], numbers[2], numbers[3]}, fields}) + if err != nil { + return nil, err + } + digest := sha256.Sum256(encoded) + if groups[numbers[0]] == nil { + groups[numbers[0]] = make(map[uint64]string) + } + if _, duplicate := groups[numbers[0]][numbers[1]]; duplicate { + return nil, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: duplicate routine namespace member") + } + groups[numbers[0]][numbers[1]] = hex.EncodeToString(digest[:]) + } + result := make(map[uint64]string, len(groups)) + for _, members := range groups { + fingerprints := make([]string, 0, len(members)) + for _, fp := range members { + fingerprints = append(fingerprints, fp) + } + sort.Strings(fingerprints) + digest := sha256.Sum256([]byte("mo-routine-namespace-state/1\x00" + strings.Join(fingerprints, ""))) + for id := range members { + result[id] = hex.EncodeToString(digest[:]) + } + } + return result, nil +} + +// begin creates the catalog read transaction. Mark its internal SELECTs derived +// until finishTxn so READ COMMITTED cannot advance between enumeration, revision +// reads and the namespace fence. Restore before COMMIT/ROLLBACK and Close. +func pinRoutineCatalogReads(bh BackgroundExec) func() { + if back, ok := bh.(*backExec); ok { + previous := back.backSes.ReplaceDerivedStmt(true) + return func() { back.backSes.ReplaceDerivedStmt(previous) } + } + // Non-engine executors are deterministic unit-test readers. + return func() {} +} + +func routineCatalogDatabaseID(ctx context.Context, bh BackgroundExec, database string, accountID uint32, snapshot *planpb.Snapshot) (uint64, error) { + table := "mo_catalog.mo_database" + if snapshot != nil && snapshot.TS != nil { + table += fmt.Sprintf(" {MO_TS = %d}", snapshot.TS.PhysicalTime) + } + bh.ClearExecResultSet() + if err := bh.Exec(ctx, fmt.Sprintf("select dat_id from %s where datname = '%s' and account_id = %d;", table, strings.ReplaceAll(database, "'", "''"), accountID)); err != nil { + return 0, err + } + rows, err := getResultSet(ctx, bh) + if err != nil { + return 0, err + } + row, err := exactlyOneCatalogRow(ctx, rows, "routine database identity") + if err != nil { + return 0, err + } + return row.GetUint64(ctx, 0, 0) +} + +func routineCatalogAccountID(sessionAccount uint32, snapshot *planpb.Snapshot) uint32 { + if snapshot != nil && snapshot.Tenant != nil { + return snapshot.Tenant.TenantID + } + return sessionAccount +} diff --git a/pkg/frontend/routine_namespace_test.go b/pkg/frontend/routine_namespace_test.go new file mode 100644 index 0000000000000..6b6478a36a89a --- /dev/null +++ b/pkg/frontend/routine_namespace_test.go @@ -0,0 +1,178 @@ +// Copyright 2026 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 frontend + +import ( + "context" + "fmt" + "strings" + "testing" + + "github.com/gogo/protobuf/proto" + "github.com/golang/mock/gomock" + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/defines" + mock_frontend "github.com/matrixorigin/matrixone/pkg/frontend/test" + planpb "github.com/matrixorigin/matrixone/pkg/pb/plan" + "github.com/matrixorigin/matrixone/pkg/pb/txn" + "github.com/matrixorigin/matrixone/pkg/sql/plan/function" + "github.com/matrixorigin/matrixone/pkg/txn/client" + "github.com/stretchr/testify/require" +) + +func namespaceRows(data ...[]interface{}) *MysqlResultSet { + r := &MysqlResultSet{} + for i := 0; i < 16; i++ { + c := &MysqlColumn{} + c.SetName(fmt.Sprint(i)) + c.SetColumnType(defines.MYSQL_TYPE_VARCHAR) + if i < 4 { + c.SetColumnType(defines.MYSQL_TYPE_LONGLONG) + } + r.AddColumn(c) + } + for _, row := range data { + r.AddRow(row) + } + return r +} +func namespaceMember(id uint64, arg string) []interface{} { + return []interface{}{uint64(41), id, uint64(1), uint64(1), arg, "body", "python", "bigint", "db", "", "INVOKER", arg, "body", "python", "bigint", "INVOKER"} +} +func TestRoutineNamespaceInvalidatesBetterOverload(t *testing.T) { + input := []types.Type{types.T_int16.ToType()} + oldMatch, oldCost := function.PythonUdfArgTypeMatch(input, []types.Type{types.T_int64.ToType()}) + newMatch, newCost := function.PythonUdfArgTypeMatch(input, input) + require.True(t, oldMatch && newMatch) + require.Less(t, newCost, oldCost) + old := namespaceMember(41, "bigint") + sibling := namespaceMember(42, "smallint") + before, err := decodeRoutineNamespaces(context.Background(), namespaceRows(old)) + require.NoError(t, err) + after, err := decodeRoutineNamespaces(context.Background(), namespaceRows(old, sibling)) + require.NoError(t, err) + dependency := testRoutinePlanDependency() + dependency.NamespaceFingerprint = before[41] + state := testRoutinePlanState() + state.namespaceFingerprint = before[41] + require.False(t, routinePlanDependenciesChanged([]*planpb.RoutinePlanDependency{dependency}, map[uint64]routinePlanCatalogState{41: state})) + state.namespaceFingerprint = after[41] + require.True(t, routinePlanDependenciesChanged([]*planpb.RoutinePlanDependency{dependency}, map[uint64]routinePlanCatalogState{41: state}), "selected identity unchanged, but new better overload must invalidate") + // Rollback/restoring the identical candidate state preserves the dependency. + restored, err := decodeRoutineNamespaces(context.Background(), namespaceRows(old)) + require.NoError(t, err) + require.Equal(t, before, restored) + reordered, err := decodeRoutineNamespaces(context.Background(), namespaceRows(sibling, old)) + require.NoError(t, err) + require.Equal(t, after, reordered) + require.Equal(t, after[41], after[42], "all selected siblings reuse one namespace hash") + // Drop and replace of an unselected member change the name dependency. + sibling[2] = uint64(2) + replaced, err := decodeRoutineNamespaces(context.Background(), namespaceRows(old, sibling)) + require.NoError(t, err) + require.NotEqual(t, after, replaced) + // Effective revision metadata, rather than only initial head projection. + sibling[11] = "int" + effective, err := decodeRoutineNamespaces(context.Background(), namespaceRows(old, sibling)) + require.NoError(t, err) + require.NotEqual(t, replaced, effective) + _, err = decodeRoutineNamespaces(context.Background(), namespaceRows(old, old)) + require.ErrorContains(t, err, "duplicate") + data, err := proto.Marshal(dependency) + require.NoError(t, err) + var decoded planpb.RoutinePlanDependency + require.NoError(t, proto.Unmarshal(data, &decoded)) + require.Equal(t, dependency.NamespaceFingerprint, decoded.NamespaceFingerprint) + decoded.NamespaceFingerprint = "" + require.ErrorContains(t, validateRoutinePlanDependencyShape(&decoded, 9), "incomplete") +} +func TestRoutineNamespaceQueryReadsAllLanguagesAndSignatures(t *testing.T) { + query := routineNamespacesSQL([]uint64{41, 42}, nil) + require.Contains(t, query, "f.db=selected.db and f.name=selected.name") + require.Contains(t, query, "where function_id in (41,42) group by db,name") + require.NotContains(t, query, "f.language =") + require.NotContains(t, query, "f.arg_types =") + require.Contains(t, query, "limit 65537") +} +func TestRoutineNamespaceReadIsBounded(t *testing.T) { + oversized := namespaceMember(41, "bigint") + oversized[5] = strings.Repeat("x", maxRoutineNamespaceBytes+1) + _, err := decodeRoutineNamespaces(context.Background(), namespaceRows(oversized)) + require.ErrorContains(t, err, "namespace bytes") +} + +type routineSnapshotWorkspace struct { + client.Workspace + advances int +} + +func (w *routineSnapshotWorkspace) IncrStatementID(context.Context, bool) error { + w.advances++ + return fmt.Errorf("snapshot advanced") +} + +func TestRoutineCatalogReadsKeepRCSnapshotUntilFinish(t *testing.T) { + ctrl := gomock.NewController(t) + op := mock_frontend.NewMockTxnOperator(ctrl) + workspace := &routineSnapshotWorkspace{} + op.EXPECT().GetWorkspace().Return(workspace).AnyTimes() + op.EXPECT().Status().Return(txn.TxnStatus_Active).AnyTimes() + back := &backExec{backSes: &backSession{}} + restore := pinRoutineCatalogReads(back) + // This is the real statement boundary that would advance an RC snapshot. + // A concurrent DDL commit between these internal SELECTs cannot invoke it. + for i := 0; i < 3; i++ { + require.NoError(t, executeStmtWithIncrStmt(back.backSes, nil, nil, op)) + } + require.Zero(t, workspace.advances) + restore() + require.False(t, back.backSes.IsDerivedStmt()) + err := executeStmtWithIncrStmt(back.backSes, nil, &ExecCtx{reqCtx: context.Background()}, op) + require.ErrorContains(t, err, "snapshot advanced") + require.Equal(t, 1, workspace.advances) + // Nested shared readers restore the existing derived state rather than + // committing/advancing their caller's statement on return. + back.backSes.ReplaceDerivedStmt(true) + restore = pinRoutineCatalogReads(back) + restore() + require.True(t, back.backSes.IsDerivedStmt()) +} + +type namespaceValidationSession struct{ FeSession } + +func (*namespaceValidationSession) GetTxnCompileCtx() *TxnCompilerContext { return nil } +func (*namespaceValidationSession) GetAccountId() uint32 { return 9 } +func TestRoutinePlanWithoutNamespaceRebinds(t *testing.T) { + dependency := testRoutinePlanDependency() + dependency.NamespaceFingerprint = "" + p := &planpb.Plan{Plan: &planpb.Plan_Query{Query: &planpb.Query{RoutineDependencies: []*planpb.RoutinePlanDependency{dependency}}}} + changed, err := validateRoutinePlanDependencies(context.Background(), &namespaceValidationSession{}, p) + require.NoError(t, err) + require.True(t, changed) +} + +func TestRoutineCatalogDatabaseUsesSnapshotTenant(t *testing.T) { + snapshot := &planpb.Snapshot{Tenant: &planpb.SnapshotTenant{TenantID: 7}} + require.Equal(t, uint32(7), routineCatalogAccountID(0, snapshot)) + require.Equal(t, uint32(9), routineCatalogAccountID(9, nil)) + bh := &backgroundExecTestWithHistory{} + bh.init() + bh.sql2result["select dat_id from mo_catalog.mo_database where datname = 'source_db' and account_id = 7;"] = singleInt64Result("dat_id", 88) + ctx := defines.AttachAccountId(context.Background(), 7) + id, err := routineCatalogDatabaseID(ctx, bh, "source_db", routineCatalogAccountID(0, snapshot), snapshot) + require.NoError(t, err) + require.Equal(t, uint64(88), id) + require.Contains(t, bh.executedSqls[0], "account_id = 7") +} diff --git a/pkg/frontend/routine_plan_validation.go b/pkg/frontend/routine_plan_validation.go new file mode 100644 index 0000000000000..7329e417a6a29 --- /dev/null +++ b/pkg/frontend/routine_plan_validation.go @@ -0,0 +1,569 @@ +// Copyright 2026 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 frontend + +import ( + "context" + "errors" + "fmt" + "sort" + "strconv" + "strings" + + "github.com/matrixorigin/matrixone/pkg/udf/udferr" + "github.com/matrixorigin/matrixone/pkg/util/errutil" + + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/defines" + planpb "github.com/matrixorigin/matrixone/pkg/pb/plan" + "github.com/matrixorigin/matrixone/pkg/sql/plan/function" + "github.com/matrixorigin/matrixone/pkg/udf" +) + +const ( + // Keep dependency validation bounded before allocating or opening a catalog + // transaction. The entry limit protects the result/accounting side; the + // depth limit protects the plan traversal side when a malformed plan nests + // background queries without contributing many routine entries. + maxRoutinePlanDependencies = 1024 + maxRoutinePlanDependencyBytes = 1 << 20 + maxRoutinePlanQueryDepth = 64 +) + +type routinePlanCatalogState struct { + namespaceFingerprint string + activeRevision uint64 + namespaceVersion uint64 + databaseID uint64 + revision uint64 + language string + volatility string + nullPolicy string + fingerprint string + artifactDigest string + environmentDigest string + securityType string + identityChecked bool + identityValid bool +} + +func cachedRoutinePlanDependenciesCurrent(ses *Session, cached *cachedPlan) bool { + if cached == nil { + return true + } + if ses == nil { + // A cached plan that carries a routine dependency must never be reused + // without the tenant-aware catalog reader that can validate its exact + // revision. Plans without such metadata remain ordinary cache entries. + for _, p := range cached.plans { + dependencies, err := routinePlanDependencies(p) + if err != nil || len(dependencies) != 0 { + return false + } + } + return true + } + ctx := context.Background() + if tcc := ses.GetTxnCompileCtx(); tcc != nil && tcc.execCtx != nil { + ctx = tcc.GetContext() + } + for _, p := range cached.plans { + changed, err := validateRoutinePlanDependencies(ctx, ses, p) + if err != nil || changed { + return false + } + } + return true +} + +func routinePlanDependencies(p *planpb.Plan) ([]*planpb.RoutinePlanDependency, error) { + if p == nil { + return nil, nil + } + query := p.GetQuery() + if query == nil { + return nil, nil + } + + type queryFrame struct { + query *planpb.Query + depth int + next int + } + initialCapacity := len(query.GetRoutineDependencies()) + if initialCapacity > maxRoutinePlanDependencies { + initialCapacity = maxRoutinePlanDependencies + } + dependencies := make([]*planpb.RoutinePlanDependency, 0, initialCapacity) + dependencyBytes := 0 + stack := []queryFrame{{query: query}} + active := map[*planpb.Query]struct{}{query: {}} + completed := make(map[*planpb.Query]struct{}) + for len(stack) != 0 { + frameIndex := len(stack) - 1 + frame := &stack[frameIndex] + if frame.next == 0 { + frameDependencies := frame.query.GetRoutineDependencies() + if len(dependencies)+len(frameDependencies) > maxRoutinePlanDependencies { + return nil, udferr.Newf("PROGRAM_LIMIT_EXCEEDED: routine dependency count exceeds %d", maxRoutinePlanDependencies) + } + for _, dependency := range frameDependencies { + dependencySize := 1 + if dependency != nil { + dependencySize = dependency.ProtoSize() + } + if dependencySize > maxRoutinePlanDependencyBytes-dependencyBytes { + return nil, udferr.Newf("PROGRAM_LIMIT_EXCEEDED: routine dependency bytes exceed %d", maxRoutinePlanDependencyBytes) + } + dependencyBytes += dependencySize + } + dependencies = append(dependencies, frameDependencies...) + } + backgroundQueries := frame.query.GetBackgroundQueries() + if frame.next >= len(backgroundQueries) { + delete(active, frame.query) + completed[frame.query] = struct{}{} + stack = stack[:frameIndex] + continue + } + background := backgroundQueries[frame.next] + frame.next++ + if background == nil { + continue + } + if frame.depth+1 > maxRoutinePlanQueryDepth { + return nil, udferr.Newf("PROGRAM_LIMIT_EXCEEDED: routine dependency query nesting exceeds %d", maxRoutinePlanQueryDepth) + } + if _, exists := active[background]; exists { + return nil, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: routine dependency query graph contains a cycle") + } + // Shared background queries contribute their immutable dependencies + // once. Re-expanding a DAG as a tree can turn a small plan into + // exponential work (even when it contains no routine dependencies). + if _, exists := completed[background]; exists { + continue + } + active[background] = struct{}{} + stack = append(stack, queryFrame{query: background, depth: frame.depth + 1}) + } + return dependencies, nil +} + +// validateRoutinePlanDependencies checks a plan against the current catalog +// publication. It is deliberately identity based: execution never resolves a +// routine by name or latest revision, while cache/prepared reuse is rejected +// when the active namespace has moved since the plan was bound. +func validateRoutinePlanDependencies(ctx context.Context, ses FeSession, p *planpb.Plan) (changed bool, err error) { + dependencies, err := routinePlanDependencies(p) + if err != nil { + return false, err + } + if len(dependencies) == 0 { + return false, nil + } + if len(dependencies) > maxRoutinePlanDependencies { + return false, udferr.Newf("PROGRAM_LIMIT_EXCEEDED: routine dependency count exceeds %d", maxRoutinePlanDependencies) + } + if ses == nil { + return false, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: routine dependency validation has no session") + } + var snapshot *planpb.Snapshot + if tcc := ses.GetTxnCompileCtx(); tcc != nil { + snapshot = tcc.GetSnapshot() + } + accountID := routineCatalogAccountID(ses.GetAccountId(), snapshot) + ids := make([]uint64, 0, len(dependencies)) + seen := make(map[uint64]struct{}, len(dependencies)) + for _, dependency := range dependencies { + if dependency != nil && dependency.NamespaceFingerprint == "" { + return true, nil + } + if err := validateRoutinePlanDependencyShape(dependency, accountID); err != nil { + return false, err + } + id := dependency.FunctionRef.FunctionId + if _, ok := seen[id]; !ok { + seen[id] = struct{}{} + ids = append(ids, id) + } + } + sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] }) + + if ctx == nil { + ctx = context.Background() + } + ctx = defines.AttachAccountId(ctx, accountID) + // Background execution is still part of the real SQL call path (for + // procedures, derived statements, restore and other frontend-owned work). + // Validate through the execution session so the catalog read carries the + // same tenant and transaction context as the plan. GetBackgroundExec is + // implemented for both client and background sessions; rejecting the latter + // here would make a valid typed routine fail only when a statement is + // executed through a nested frontend pipeline. + + useCallerTxn := resolvesUdfInCallerTxn(ctx) + var bh BackgroundExec + if useCallerTxn { + bh = ses.GetShareTxnBackgroundExec(ctx, false) + } else { + bh = ses.GetBackgroundExec(ctx) + } + defer bh.Close() + if !useCallerTxn { + if err = bh.Exec(ctx, "begin;"); err != nil { + return false, errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: routine dependency validation could not start") + } + defer func() { err = finishTxn(ctx, bh, err) }() + } + + defer pinRoutineCatalogReads(bh)() + bh.ClearExecResultSet() + query := routinePlanCatalogSQL(ids, accountID) + if snapshot != nil && snapshot.TS != nil { + for _, table := range []string{"mo_user_defined_function", "mo_database", "mo_function_revisions"} { + name := "mo_catalog." + table + query = strings.ReplaceAll(query, name+" ", fmt.Sprintf("%s {MO_TS = %d} ", name, snapshot.TS.PhysicalTime)) + } + } + if err = bh.Exec(ctx, query); err != nil { + return false, errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: routine dependency validation failed") + } + rows, err := getResultSet(ctx, bh) + if err != nil { + return false, err + } + catalogResult, err := candidateCatalogResultSet(rows, "routine dependency catalog") + if err != nil { + return false, err + } + if catalogResult == nil { + return true, nil + } + states := make(map[uint64]routinePlanCatalogState, len(rows)) + if catalogResult.GetRowCount() != 0 { + for row := uint64(0); row < catalogResult.GetRowCount(); row++ { + id, getErr := catalogResult.GetUint64(ctx, row, 0) + if getErr != nil { + return false, getErr + } + activeRevision, getErr := catalogResult.GetUint64(ctx, row, 1) + if getErr != nil { + return false, getErr + } + namespaceVersion, getErr := catalogResult.GetUint64(ctx, row, 2) + if getErr != nil { + return false, getErr + } + databaseID, getErr := catalogResult.GetUint64(ctx, row, 3) + if getErr != nil { + return false, getErr + } + revision, getErr := catalogResult.GetUint64(ctx, row, 4) + if getErr != nil { + return false, getErr + } + language, getErr := catalogResult.GetString(ctx, row, 5) + if getErr != nil { + return false, getErr + } + volatility, getErr := catalogResult.GetString(ctx, row, 6) + if getErr != nil { + return false, getErr + } + fingerprint, getErr := catalogResult.GetString(ctx, row, 7) + if getErr != nil { + return false, getErr + } + artifactDigest, getErr := catalogResult.GetString(ctx, row, 8) + if getErr != nil { + return false, getErr + } + environmentDigest, getErr := catalogResult.GetString(ctx, row, 9) + if getErr != nil { + return false, getErr + } + canonicalInput, getErr := catalogResult.GetString(ctx, row, 10) + if getErr != nil { + return false, getErr + } + returnDescriptor, getErr := catalogResult.GetString(ctx, row, 11) + if getErr != nil { + return false, getErr + } + signatureKeySchemaVersion, getErr := catalogResult.GetInt64(ctx, row, 12) + if getErr != nil { + return false, getErr + } + signatureFingerprint, getErr := catalogResult.GetString(ctx, row, 13) + if getErr != nil { + return false, getErr + } + body, getErr := catalogResult.GetString(ctx, row, 14) + if getErr != nil { + return false, getErr + } + revisionArgTypes, getErr := catalogResult.GetString(ctx, row, 15) + if getErr != nil { + return false, getErr + } + revisionRetType, getErr := catalogResult.GetString(ctx, row, 16) + if getErr != nil { + return false, getErr + } + definitionSchema, getErr := catalogResult.GetInt64(ctx, row, 17) + if getErr != nil { + return false, getErr + } + revisionABI, getErr := catalogResult.GetString(ctx, row, 18) + if getErr != nil { + return false, getErr + } + revisionAdapter, getErr := catalogResult.GetString(ctx, row, 19) + if getErr != nil { + return false, getErr + } + revisionSDK, getErr := catalogResult.GetString(ctx, row, 20) + if getErr != nil { + return false, getErr + } + revisionNullPolicy, getErr := catalogResult.GetString(ctx, row, 21) + if getErr != nil { + return false, getErr + } + revisionSecurityType, getErr := catalogResult.GetString(ctx, row, 22) + if getErr != nil { + return false, getErr + } + baseSecurityType, getErr := catalogResult.GetString(ctx, row, 23) + if getErr != nil { + return false, getErr + } + if !strings.EqualFold(revisionSecurityType, baseSecurityType) { + return false, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: routine %d has inconsistent revision and identity security contracts", id) + } + if language == udf.LanguagePython && !strings.EqualFold(revisionSecurityType, "INVOKER") { + return false, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python routine catalog security type is not INVOKER") + } + if language == udf.LanguageSQL && !strings.EqualFold(revisionSecurityType, "DEFINER") { + return false, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: SQL routine catalog security type is not DEFINER") + } + identityValid := routinePlanCatalogIdentityValidForLanguage( + language, + body, fingerprint, signatureKeySchemaVersion, canonicalInput, + returnDescriptor, signatureFingerprint, revisionArgTypes, + revisionRetType, definitionSchema, revisionABI, revisionAdapter, + revisionSDK, revisionNullPolicy, + ) + if _, duplicate := states[id]; duplicate { + return false, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: routine catalog returned duplicate state for function %d", id) + } + states[id] = routinePlanCatalogState{ + activeRevision: activeRevision, namespaceVersion: namespaceVersion, + databaseID: databaseID, + revision: revision, language: language, volatility: volatility, nullPolicy: revisionNullPolicy, fingerprint: fingerprint, + artifactDigest: artifactDigest, environmentDigest: environmentDigest, + securityType: revisionSecurityType, + identityChecked: true, identityValid: identityValid, + } + } + } + namespaces, namespaceErr := readRoutineNamespaces(ctx, bh, ids, snapshot) + if errors.Is(namespaceErr, errRoutineNamespaceBudget) { + return true, nil + } + if namespaceErr != nil { + return false, namespaceErr + } + for id, state := range states { + state.namespaceFingerprint = namespaces[id] + states[id] = state + } + return routinePlanDependenciesChanged(dependencies, states), nil +} + +// routinePlanCatalogIdentityValid verifies the complete immutable revision +// contract before a cached plan can be reused. Keeping this check separate +// from the SQL row decoder makes the important tamper cases directly +// testable: changing source, a descriptor, an ABI field, or a legacy logical +// return type while retaining the old fingerprint must invalidate the plan. +func routinePlanCatalogIdentityValid( + rawBody, fingerprint string, + signatureKeySchemaVersion int64, + canonicalInput, returnDescriptor, signatureFingerprint, revisionArgTypes, + revisionRetType string, + definitionSchema int64, + revisionABI, revisionAdapter, revisionSDK, revisionNullPolicy string, +) bool { + return routinePlanCatalogIdentityValidForLanguage( + udf.LanguagePython, + rawBody, fingerprint, signatureKeySchemaVersion, canonicalInput, + returnDescriptor, signatureFingerprint, revisionArgTypes, revisionRetType, + definitionSchema, revisionABI, revisionAdapter, revisionSDK, revisionNullPolicy, + ) +} + +func routinePlanCatalogIdentityValidForLanguage( + language string, + rawBody, fingerprint string, + signatureKeySchemaVersion int64, + canonicalInput, returnDescriptor, signatureFingerprint, revisionArgTypes, + revisionRetType string, + definitionSchema int64, + revisionABI, revisionAdapter, revisionSDK, revisionNullPolicy string, +) bool { + if language == udf.LanguageSQL { + expectedFingerprint, err := function.SQLRoutineFingerprint(rawBody, revisionArgTypes, revisionRetType) + return err == nil && + fingerprint == expectedFingerprint && + definitionSchema == int64(udf.SQLDefinitionSchemaVersion) && + revisionABI == "" && revisionAdapter == "" && revisionSDK == "" && + revisionNullPolicy == udf.NullCallHandler + } + if language != udf.LanguagePython { + return false + } + decoded, err := function.DecodePythonRoutineBody(rawBody) + if err != nil { + return false + } + expectedInput, expectedReturn, expectedFingerprint, err := function.PythonSignatureMetadata(decoded.ArgTypes, decoded.ReturnType) + if err != nil { + return false + } + bodyFingerprint, err := function.PythonRoutineBodyFingerprint(decoded) + if err != nil { + return false + } + return bodyFingerprint == fingerprint && + signatureKeySchemaVersion == udf.PythonSignatureKeySchemaVersion && + canonicalInput == expectedInput && returnDescriptor == expectedReturn && signatureFingerprint == expectedFingerprint && + revisionArgTypes == expectedInput && + routineRevisionMetadataMatches(decoded, definitionSchema, revisionABI, revisionAdapter, revisionSDK, revisionNullPolicy) && + routineRevisionReturnTypeMatches(revisionRetType, decoded.ReturnType.Type().Oid) +} + +func routinePlanCatalogSQL(ids []uint64, accountID uint32) string { + values := make([]string, len(ids)) + for i, id := range ids { + values[i] = strconv.FormatUint(id, 10) + } + return fmt.Sprintf(`select f.function_id, f.active_revision, f.namespace_version, d.dat_id, + r.revision, r.language, r.volatility, r.definition_fingerprint, r.artifact_digest, + r.environment_digest, f.canonical_input_descriptor, f.return_descriptor, + f.signature_key_schema_version, f.signature_fingerprint, r.body, r.arg_types, + r.rettype, r.definition_schema_version, r.abi_contract, r.adapter_version, + r.sdk_version, r.null_policy, r.security_type, f.security_type + from mo_catalog.mo_user_defined_function f + join mo_catalog.mo_database d on d.datname = f.db and d.account_id = %d + join mo_catalog.mo_function_revisions r + on r.function_id = f.function_id and r.revision = f.active_revision + and r.namespace_version = f.namespace_version + where f.function_id in (%s);`, accountID, strings.Join(values, ",")) +} + +func routineRevisionMetadataMatches( + body function.PythonRoutineBody, + definitionSchema int64, + abi, adapter, sdk, nullPolicy string, +) bool { + return definitionSchema == int64(udf.PythonDefinitionSchemaVersion) && + abi == udf.PythonABIContract && adapter == udf.PythonAdapterVersion && + sdk == udf.PythonSDKVersion && nullPolicy == body.NullPolicy && + body.ABIContract == abi && body.AdapterVersion == adapter && body.SDKVersion == sdk +} + +func routineRevisionReturnTypeMatches(rettype string, oid types.T) bool { + if strings.EqualFold(rettype, oid.String()) { + return true + } + return strings.EqualFold(rettype, "decimal") && (oid == types.T_decimal64 || oid == types.T_decimal128) +} + +func validateRoutinePlanDependencyShape(dependency *planpb.RoutinePlanDependency, accountID uint32) error { + if dependency == nil || dependency.FunctionRef == nil { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: routine plan dependency has no FunctionRef") + } + ref := dependency.FunctionRef + if ref.FunctionId == 0 || ref.Revision == 0 || ref.NamespaceVersion == 0 || + ref.AccountId != uint64(accountID) || ref.DatabaseId == 0 { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: routine plan dependency has an invalid catalog identity") + } + if dependency.ContractVersion != udf.RoutinePlanContractVersion || + !udf.IsSHA256Digest(dependency.DefinitionFingerprint) || !udf.IsSHA256Digest(dependency.NamespaceFingerprint) { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: routine plan dependency contract is incomplete") + } + if dependency.Volatility == "" || dependency.NullPolicy == "" || !dependency.MayError || dependency.Leakproof { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: routine plan dependency semantic contract is incomplete") + } + switch dependency.Language { + case udf.LanguagePython: + if dependency.SecurityMode != "INVOKER" { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python routine plan dependency must use INVOKER security") + } + if !udf.IsSHA256Digest(dependency.ArtifactDigest) || !udf.IsSHA256Digest(dependency.EnvironmentDigest) { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python routine plan dependency integrity is incomplete") + } + case udf.LanguageSQL: + if dependency.SecurityMode == "" { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: SQL routine plan dependency has no security mode") + } + if dependency.ArtifactDigest != "" || dependency.EnvironmentDigest != "" { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: SQL routine plan dependency has external integrity fields") + } + default: + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: routine plan dependency language %q is unsupported", dependency.Language) + } + return nil +} + +func routinePlanDependenciesChanged( + dependencies []*planpb.RoutinePlanDependency, + states map[uint64]routinePlanCatalogState, +) bool { + for _, dependency := range dependencies { + if dependency == nil || dependency.FunctionRef == nil { + return true + } + ref := dependency.FunctionRef + state, ok := states[ref.FunctionId] + if !ok || state.activeRevision == 0 || state.revision == 0 { + return true + } + if state.identityChecked && !state.identityValid { + return true + } + expectedSecurityMode := dependency.SecurityMode + if expectedSecurityMode == "" { + return true + } + if state.namespaceFingerprint != dependency.NamespaceFingerprint || !udf.IsSHA256Digest(dependency.NamespaceFingerprint) || + state.activeRevision != ref.Revision || state.revision != ref.Revision || + state.databaseID != ref.DatabaseId || + state.namespaceVersion != ref.NamespaceVersion || + state.volatility != dependency.Volatility || + state.nullPolicy != dependency.NullPolicy || + !strings.EqualFold(state.securityType, dependency.SecurityMode) || + (dependency.Language == udf.LanguagePython && expectedSecurityMode != "INVOKER") || + (dependency.Language == udf.LanguageSQL && expectedSecurityMode == "") || + !dependency.MayError || dependency.Leakproof || + state.language != dependency.Language || + state.fingerprint != dependency.DefinitionFingerprint || + state.artifactDigest != dependency.ArtifactDigest || + state.environmentDigest != dependency.EnvironmentDigest { + return true + } + } + return false +} diff --git a/pkg/frontend/routine_plan_validation_test.go b/pkg/frontend/routine_plan_validation_test.go new file mode 100644 index 0000000000000..41d26bbfa2234 --- /dev/null +++ b/pkg/frontend/routine_plan_validation_test.go @@ -0,0 +1,483 @@ +// Copyright 2026 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 frontend + +import ( + "context" + "encoding/json" + "errors" + "strings" + "testing" + + "github.com/matrixorigin/matrixone/pkg/container/types" + planpb "github.com/matrixorigin/matrixone/pkg/pb/plan" + sqlplan "github.com/matrixorigin/matrixone/pkg/sql/plan" + "github.com/matrixorigin/matrixone/pkg/sql/plan/function" + "github.com/matrixorigin/matrixone/pkg/udf" + "github.com/stretchr/testify/require" +) + +type routinePlanValidationExec struct { + BackgroundExec + resultSets []interface{} + catalogResultSets []interface{} + namespaceResultSets []interface{} + failOn string + statements []string +} + +func (e *routinePlanValidationExec) Close() {} + +func (e *routinePlanValidationExec) Exec(_ context.Context, statement string) error { + e.statements = append(e.statements, statement) + if e.failOn != "" && strings.Contains(statement, e.failOn) { + return errors.New("injected routine catalog read failure") + } + if strings.Contains(statement, "select f.function_id") { + e.resultSets = e.catalogResultSets + } else if strings.Contains(statement, "select selected.function_id") { + e.resultSets = e.namespaceResultSets + } + return nil +} + +func (e *routinePlanValidationExec) GetExecResultSet() []interface{} { + return e.resultSets +} + +func (e *routinePlanValidationExec) ClearExecResultSet() { + e.resultSets = nil +} + +type routinePlanValidationSession struct { + FeSession + exec BackgroundExec +} + +func (s *routinePlanValidationSession) GetAccountId() uint32 { return 9 } + +func (s *routinePlanValidationSession) GetTxnCompileCtx() *TxnCompilerContext { return nil } + +func (s *routinePlanValidationSession) GetBackgroundExec(context.Context, ...*BackgroundExecOption) BackgroundExec { + return s.exec +} + +func routinePlanCatalogResultSet(values []interface{}) *MysqlResultSet { + result := &MysqlResultSet{} + for range values { + result.AddColumn(&MysqlColumn{}) + } + result.AddRow(values) + return result +} + +func emptyRoutineNamespaceResultSet() *MysqlResultSet { + result := &MysqlResultSet{} + for range 16 { + result.AddColumn(&MysqlColumn{}) + } + return result +} + +func testRoutinePlanDependency() *planpb.RoutinePlanDependency { + return &planpb.RoutinePlanDependency{ + FunctionRef: &planpb.FunctionRef{ + FunctionId: 41, + Revision: 7, + NamespaceVersion: 12, + AccountId: 9, + DatabaseId: 8, + }, + Language: udf.LanguagePython, + ContractVersion: udf.PythonPlanContractVersion, + NamespaceFingerprint: strings.Repeat("d", 64), + DefinitionFingerprint: strings.Repeat("a", 64), + ArtifactDigest: strings.Repeat("b", 64), + EnvironmentDigest: strings.Repeat("c", 64), + Volatility: "VOLATILE", + NullPolicy: udf.NullCallHandler, + MayError: true, + SecurityMode: "INVOKER", + Leakproof: false, + } +} + +func testRoutinePlanState() routinePlanCatalogState { + return routinePlanCatalogState{ + namespaceFingerprint: strings.Repeat("d", 64), + activeRevision: 7, + namespaceVersion: 12, + databaseID: 8, + revision: 7, + language: udf.LanguagePython, + volatility: "VOLATILE", + nullPolicy: udf.NullCallHandler, + fingerprint: strings.Repeat("a", 64), + artifactDigest: strings.Repeat("b", 64), + environmentDigest: strings.Repeat("c", 64), + securityType: "INVOKER", + } +} + +func TestRoutinePlanDependenciesChangedRequiresExactPublication(t *testing.T) { + dependency := testRoutinePlanDependency() + state := testRoutinePlanState() + + require.False(t, routinePlanDependenciesChanged( + []*planpb.RoutinePlanDependency{dependency}, + map[uint64]routinePlanCatalogState{41: state}, + )) + + cases := []struct { + name string + mutate func(*routinePlanCatalogState) + }{ + {name: "active revision", mutate: func(s *routinePlanCatalogState) { + s.activeRevision++ + }}, + {name: "namespace", mutate: func(s *routinePlanCatalogState) { + s.namespaceVersion++ + }}, + {name: "database", mutate: func(s *routinePlanCatalogState) { + s.databaseID++ + }}, + {name: "revision", mutate: func(s *routinePlanCatalogState) { + s.revision++ + }}, + {name: "fingerprint", mutate: func(s *routinePlanCatalogState) { + s.fingerprint = strings.Repeat("d", 64) + }}, + {name: "artifact", mutate: func(s *routinePlanCatalogState) { + s.artifactDigest = strings.Repeat("d", 64) + }}, + {name: "environment", mutate: func(s *routinePlanCatalogState) { + s.environmentDigest = strings.Repeat("d", 64) + }}, + {name: "security", mutate: func(s *routinePlanCatalogState) { + s.securityType = "DEFINER" + }}, + {name: "language", mutate: func(s *routinePlanCatalogState) { + s.language = "sql" + }}, + {name: "volatility", mutate: func(s *routinePlanCatalogState) { + s.volatility = "IMMUTABLE" + }}, + {name: "missing", mutate: func(s *routinePlanCatalogState) { + s.activeRevision = 0 + }}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + changedState := state + tc.mutate(&changedState) + states := map[uint64]routinePlanCatalogState{41: changedState} + if tc.name == "missing" { + states = map[uint64]routinePlanCatalogState{} + } + require.True(t, routinePlanDependenciesChanged( + []*planpb.RoutinePlanDependency{dependency}, states)) + }) + } +} + +func TestValidateRoutinePlanDependencyShapeRejectsCrossAccountAndUnknownContracts(t *testing.T) { + require.NoError(t, validateRoutinePlanDependencyShape(testRoutinePlanDependency(), 9)) + + cases := []struct { + name string + mutate func(*planpb.RoutinePlanDependency) + }{ + {name: "cross account", mutate: func(d *planpb.RoutinePlanDependency) { + d.FunctionRef.AccountId = 10 + }}, + {name: "missing database", mutate: func(d *planpb.RoutinePlanDependency) { + d.FunctionRef.DatabaseId = 0 + }}, + {name: "unknown contract", mutate: func(d *planpb.RoutinePlanDependency) { + d.ContractVersion++ + }}, + {name: "missing integrity", mutate: func(d *planpb.RoutinePlanDependency) { + d.ArtifactDigest = "" + }}, + {name: "malformed digest", mutate: func(d *planpb.RoutinePlanDependency) { + d.DefinitionFingerprint = "definition-fingerprint" + }}, + {name: "missing identity", mutate: func(d *planpb.RoutinePlanDependency) { + d.FunctionRef = nil + }}, + {name: "noncanonical language", mutate: func(d *planpb.RoutinePlanDependency) { + d.Language = "PYTHON" + }}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + dependency := testRoutinePlanDependency() + tc.mutate(dependency) + require.ErrorContains(t, + validateRoutinePlanDependencyShape(dependency, 9), + "UNSUPPORTED_ROUTINE_VERSION") + }) + } +} + +func TestRoutinePlanDependenciesChangedRequiresCanonicalLanguage(t *testing.T) { + dependency := testRoutinePlanDependency() + dependency.Language = "PYTHON" + + require.True(t, routinePlanDependenciesChanged( + []*planpb.RoutinePlanDependency{dependency}, + map[uint64]routinePlanCatalogState{41: testRoutinePlanState()}, + )) +} + +func TestRoutinePlanDependenciesIncludesBackgroundQueries(t *testing.T) { + dependency := testRoutinePlanDependency() + plan := &planpb.Plan{ + Plan: &planpb.Plan_Query{Query: &planpb.Query{ + RoutineDependencies: []*planpb.RoutinePlanDependency{dependency}, + BackgroundQueries: []*planpb.Query{{ + RoutineDependencies: []*planpb.RoutinePlanDependency{testRoutinePlanDependency()}, + }}, + }}, + } + dependencies, err := routinePlanDependencies(plan) + require.NoError(t, err) + require.Len(t, dependencies, 2) + require.Same(t, dependency, dependencies[0]) + require.Equal(t, dependency, dependencies[0]) +} + +func TestRoutinePlanDependenciesRejectsUnboundedQueryGraph(t *testing.T) { + root := &planpb.Query{} + current := root + for depth := 0; depth < maxRoutinePlanQueryDepth+1; depth++ { + next := &planpb.Query{} + current.BackgroundQueries = []*planpb.Query{next} + current = next + } + + _, err := routinePlanDependencies(&planpb.Plan{ + Plan: &planpb.Plan_Query{Query: root}, + }) + require.ErrorContains(t, err, "query nesting exceeds") +} + +func TestRoutinePlanDependenciesRejectsOversizedClosureAndCycles(t *testing.T) { + root := &planpb.Query{} + root.RoutineDependencies = make([]*planpb.RoutinePlanDependency, maxRoutinePlanDependencies+1) + _, err := routinePlanDependencies(&planpb.Plan{ + Plan: &planpb.Plan_Query{Query: root}, + }) + require.ErrorContains(t, err, "dependency count exceeds") + + oversized := testRoutinePlanDependency() + oversized.DefinitionFingerprint = strings.Repeat("a", maxRoutinePlanDependencyBytes) + _, err = routinePlanDependencies(&planpb.Plan{ + Plan: &planpb.Plan_Query{Query: &planpb.Query{ + RoutineDependencies: []*planpb.RoutinePlanDependency{oversized}, + }}, + }) + require.ErrorContains(t, err, "dependency bytes exceed") + + cycle := &planpb.Query{} + cycle.BackgroundQueries = []*planpb.Query{cycle} + _, err = routinePlanDependencies(&planpb.Plan{ + Plan: &planpb.Plan_Query{Query: cycle}, + }) + require.ErrorContains(t, err, "graph contains a cycle") +} + +func TestCachedRoutinePlanWithDependencyRequiresCatalogSession(t *testing.T) { + plan := &planpb.Plan{Plan: &planpb.Plan_Query{Query: &planpb.Query{ + RoutineDependencies: []*planpb.RoutinePlanDependency{testRoutinePlanDependency()}, + }}} + plain := &cachedPlan{plans: []*sqlplan.Plan{{Plan: &planpb.Plan_Query{Query: &planpb.Query{}}}}} + withRoutine := &cachedPlan{plans: []*sqlplan.Plan{plan}} + require.True(t, cachedRoutinePlanDependenciesCurrent(nil, plain)) + require.False(t, cachedRoutinePlanDependenciesCurrent(nil, withRoutine)) +} + +func TestValidateRoutinePlanDependenciesUsesCatalogTransactionAndFailsClosed(t *testing.T) { + ctx := context.Background() + plainPlan := &planpb.Plan{Plan: &planpb.Plan_Query{Query: &planpb.Query{}}} + changed, err := validateRoutinePlanDependencies(ctx, nil, plainPlan) + require.NoError(t, err) + require.False(t, changed) + + dependency := testRoutinePlanDependency() + plan := &planpb.Plan{Plan: &planpb.Plan_Query{Query: &planpb.Query{ + RoutineDependencies: []*planpb.RoutinePlanDependency{dependency}, + }}} + _, err = validateRoutinePlanDependencies(ctx, nil, plan) + require.ErrorContains(t, err, "has no session") + + incomplete := testRoutinePlanDependency() + incomplete.NamespaceFingerprint = "" + incompletePlan := &planpb.Plan{Plan: &planpb.Plan_Query{Query: &planpb.Query{ + RoutineDependencies: []*planpb.RoutinePlanDependency{incomplete}, + }}} + changed, err = validateRoutinePlanDependencies(ctx, &routinePlanValidationSession{}, incompletePlan) + require.NoError(t, err) + require.True(t, changed, "an incomplete namespace fence must invalidate without a catalog read") + + exec := &routinePlanValidationExec{} + session := &routinePlanValidationSession{exec: exec} + changed, err = validateRoutinePlanDependencies(ctx, session, plan) + require.NoError(t, err) + require.True(t, changed, "a missing active catalog revision invalidates the prepared plan") + require.Len(t, exec.statements, 3) + require.Equal(t, "begin;", exec.statements[0]) + require.Contains(t, exec.statements[1], "where f.function_id in (41)") + require.Equal(t, "commit;", exec.statements[2]) + + // A present but damaged immutable revision is fully decoded and invalidates + // the cached plan; namespace state is still read in the same transaction. + row := []interface{}{ + uint64(41), uint64(7), uint64(12), uint64(8), uint64(7), + "python", "VOLATILE", strings.Repeat("a", 64), strings.Repeat("b", 64), + strings.Repeat("c", 64), "[]", "{}", int64(udf.PythonSignatureKeySchemaVersion), + strings.Repeat("d", 64), "damaged body", "[]", "bigint", + int64(udf.PythonDefinitionSchemaVersion), udf.PythonABIContract, + udf.PythonAdapterVersion, udf.PythonSDKVersion, udf.NullCallHandler, + "INVOKER", "INVOKER", + } + fullExec := &routinePlanValidationExec{ + catalogResultSets: []interface{}{routinePlanCatalogResultSet(row)}, + namespaceResultSets: []interface{}{emptyRoutineNamespaceResultSet()}, + } + changed, err = validateRoutinePlanDependencies(ctx, + &routinePlanValidationSession{exec: fullExec}, plan) + require.NoError(t, err) + require.True(t, changed) + require.Len(t, fullExec.statements, 4) + require.Contains(t, fullExec.statements[2], "select selected.function_id") + require.Equal(t, "commit;", fullExec.statements[3]) + + for _, tc := range []struct { + name string + catalogResultSets []interface{} + failOn string + want string + rollback bool + }{ + {name: "transaction begin error", failOn: "begin;", want: "could not start"}, + {name: "catalog query error", failOn: "mo_user_defined_function", want: "validation failed", rollback: true}, + {name: "malformed result set", catalogResultSets: []interface{}{struct{}{}}, want: "not the type of result set", rollback: true}, + } { + t.Run(tc.name, func(t *testing.T) { + failingExec := &routinePlanValidationExec{catalogResultSets: tc.catalogResultSets, failOn: tc.failOn} + changed, err := validateRoutinePlanDependencies(ctx, + &routinePlanValidationSession{exec: failingExec}, plan) + require.False(t, changed) + require.ErrorContains(t, err, tc.want) + lastStatement := failingExec.statements[len(failingExec.statements)-1] + if tc.rollback { + require.Equal(t, "rollback;", lastStatement) + } else { + require.Equal(t, "begin;", lastStatement) + } + }) + } +} + +func TestExactlyOneCatalogResultSetRequiresOneCompleteResultSet(t *testing.T) { + ctx := context.Background() + _, err := exactlyOneCatalogResultSet(ctx, nil, "routine dependency catalog") + require.ErrorContains(t, err, "expected exactly one") + + _, err = exactlyOneCatalogResultSet(ctx, []ExecResult{nil, nil}, "routine dependency catalog") + require.ErrorContains(t, err, "returned 2 result sets") + + result := singleInt64Result("function_id", 41) + got, err := exactlyOneCatalogResultSet(ctx, []ExecResult{result}, "routine dependency catalog") + require.NoError(t, err) + require.Same(t, result, got) +} + +func TestRoutinePlanCatalogIdentityRejectsTamperedRevisionBody(t *testing.T) { + raw := pythonCatalogTestBody(t, types.T_int64) + body, err := function.DecodePythonRoutineBody(raw) + require.NoError(t, err) + input, output, signature, err := function.PythonSignatureMetadata(body.ArgTypes, body.ReturnType) + require.NoError(t, err) + fingerprint, err := function.PythonRoutineBodyFingerprint(body) + require.NoError(t, err) + + valid := func(candidate string) bool { + return routinePlanCatalogIdentityValid( + candidate, fingerprint, udf.PythonSignatureKeySchemaVersion, + input, output, signature, input, "bigint", + udf.PythonDefinitionSchemaVersion, udf.PythonABIContract, + udf.PythonAdapterVersion, udf.PythonSDKVersion, udf.NullCallHandler, + ) + } + require.True(t, valid(raw)) + + body.Source = "def f(ctx, value): return value + 1" + tampered, err := json.Marshal(body) + require.NoError(t, err) + require.False(t, valid(string(tampered)), "retaining an old revision fingerprint must invalidate the cached plan") + + require.False(t, routinePlanCatalogIdentityValid( + raw, fingerprint, udf.PythonSignatureKeySchemaVersion, + input, output, signature, input+" ", "bigint", + udf.PythonDefinitionSchemaVersion, udf.PythonABIContract, + udf.PythonAdapterVersion, udf.PythonSDKVersion, udf.NullCallHandler, + )) +} + +func TestRoutinePlanCatalogIdentityAcceptsAndRejectsSQLRevision(t *testing.T) { + const ( + body = "select value + 1" + argTypes = "[\"bigint\"]" + retType = "bigint" + ) + fingerprint, err := function.SQLRoutineFingerprint(body, argTypes, retType) + require.NoError(t, err) + valid := func(candidateBody, candidateArgs, candidateReturn, candidateFingerprint string) bool { + return routinePlanCatalogIdentityValidForLanguage( + udf.LanguageSQL, + candidateBody, candidateFingerprint, 0, "", "", "", + candidateArgs, candidateReturn, udf.SQLDefinitionSchemaVersion, + "", "", "", udf.NullCallHandler, + ) + } + require.True(t, valid(body, argTypes, retType, fingerprint)) + require.False(t, valid("select value + 2", argTypes, retType, fingerprint)) + require.False(t, valid(body, argTypes, "int", fingerprint)) + require.False(t, valid(body, argTypes, retType, strings.Repeat("a", 64))) + require.False(t, routinePlanCatalogIdentityValidForLanguage( + "lua", body, fingerprint, 0, "", "", "", argTypes, retType, + udf.SQLDefinitionSchemaVersion, "", "", "", udf.NullCallHandler, + )) + require.False(t, routinePlanCatalogIdentityValidForLanguage( + "PYTHON", body, fingerprint, udf.PythonSignatureKeySchemaVersion, + "", "", "", argTypes, retType, udf.PythonDefinitionSchemaVersion, + udf.PythonABIContract, udf.PythonAdapterVersion, udf.PythonSDKVersion, + udf.NullCallHandler, + )) +} + +func TestRoutinePlanDependenciesVisitsSharedQueriesOnce(t *testing.T) { + dependency := testRoutinePlanDependency() + query := &planpb.Query{RoutineDependencies: []*planpb.RoutinePlanDependency{dependency}} + for depth := 0; depth < 12; depth++ { + query = &planpb.Query{BackgroundQueries: []*planpb.Query{query, query}} + } + dependencies, err := routinePlanDependencies(&planpb.Plan{Plan: &planpb.Plan_Query{Query: query}}) + require.NoError(t, err) + require.Len(t, dependencies, 1) + require.Same(t, dependency, dependencies[0]) +} diff --git a/pkg/frontend/snapshot.go b/pkg/frontend/snapshot.go index fc073bd5f1966..d47266181f485 100644 --- a/pkg/frontend/snapshot.go +++ b/pkg/frontend/snapshot.go @@ -127,6 +127,7 @@ var ( "mo_role_privs": systemCatalogRestoreRebuild, "mo_role_rule": systemCatalogRestoreCopy, "mo_user_defined_function": systemCatalogRestoreCopy, + "mo_function_revisions": systemCatalogRestoreCopy, "mo_stored_procedure": systemCatalogRestoreCopy, "mo_mysql_compatibility_mode": systemCatalogRestoreSkip, "mo_stages": systemCatalogRestoreCopy, @@ -1980,7 +1981,20 @@ func recreateTable( sourceSnapshot = fmt.Sprintf(" {SNAPSHOT = %s}", escapeSQLString(snapshotName)) } return restoreUserDefinedFunctionCatalogWithCurrentSchema( - ctx, bh, sourceSnapshot, curAccountID, toAccountId, + ctx, bh, sourceSnapshot, curAccountID, toAccountId, tblInfo.createSql, + ) + } + if isCurrentFunctionRevisionCatalog(tblInfo) { + curAccountID, accountErr := defines.GetAccountId(ctx) + if accountErr != nil { + return accountErr + } + sourceSnapshot := fmt.Sprintf(" {MO_TS = %d}", snapshotTs) + if curAccountID != toAccountId { + sourceSnapshot = fmt.Sprintf(" {SNAPSHOT = %s}", escapeSQLString(snapshotName)) + } + return restoreFunctionRevisionCatalogWithCurrentSchema( + ctx, bh, sourceSnapshot, curAccountID, toAccountId, tblInfo.createSql, ) } if isSequence(tblInfo) { diff --git a/pkg/frontend/snapshot_catalog_restore.go b/pkg/frontend/snapshot_catalog_restore.go index fb1e736aae297..32b58d50db84f 100644 --- a/pkg/frontend/snapshot_catalog_restore.go +++ b/pkg/frontend/snapshot_catalog_restore.go @@ -16,14 +16,21 @@ package frontend import ( "context" + "encoding/json" "fmt" "strconv" "strings" + "github.com/matrixorigin/matrixone/pkg/udf/udferr" + "github.com/matrixorigin/matrixone/pkg/util/errutil" + "github.com/matrixorigin/matrixone/pkg/catalog" "github.com/matrixorigin/matrixone/pkg/common/moerr" "github.com/matrixorigin/matrixone/pkg/common/pubsub" "github.com/matrixorigin/matrixone/pkg/defines" + "github.com/matrixorigin/matrixone/pkg/sql/plan/function" + "github.com/matrixorigin/matrixone/pkg/udf" + pythonudf "github.com/matrixorigin/matrixone/pkg/udf/python" ) type systemCatalogRestorePolicy uint8 @@ -79,10 +86,27 @@ var systemCatalogPostRestoreHandlers = []systemCatalogPostRestoreHandler{ const rolePrivilegeRestoreInsertBatchSize = 256 -const userDefinedFunctionCatalogColumns = `function_id, name, owner, args, arg_types, retType, body, language, db, definer, modified_time, created_time, type, security_type, comment, character_set_client, collation_connection, database_collation, sql_mode` +const userDefinedFunctionCatalogColumns = `function_id, active_revision, namespace_version, name, owner, args, arg_types, canonical_input_descriptor, return_descriptor, signature_key_schema_version, signature_fingerprint, retType, body, language, db, definer, modified_time, created_time, type, security_type, comment, character_set_client, collation_connection, database_collation, sql_mode` + +const userDefinedFunctionCatalogSourceColumns = `function_id, active_revision, namespace_version, name, owner, args, ` + + catalog.UserDefinedFunctionArgumentTypesSQL + `, canonical_input_descriptor, return_descriptor, signature_key_schema_version, signature_fingerprint, retType, body, language, db, definer, modified_time, created_time, type, security_type, comment, character_set_client, collation_connection, database_collation, sql_mode` + +// userDefinedFunctionCatalogRevisionSourceColumns preserves immutable heads +// from a snapshot that has the revision columns but predates the exact +// descriptor identity fields. Python rows from such a snapshot remain +// rejected by the current resolver because their identity metadata is absent; +// ordinary SQL rows retain their historical catalog behavior. +const userDefinedFunctionCatalogRevisionSourceColumns = `function_id, active_revision, namespace_version, name, owner, args, ` + + catalog.UserDefinedFunctionArgumentTypesSQL + `, '', '', 0, '', retType, body, language, db, definer, modified_time, created_time, type, security_type, comment, character_set_client, collation_connection, database_collation, sql_mode` -const userDefinedFunctionCatalogSourceColumns = `function_id, name, owner, args, ` + - catalog.UserDefinedFunctionArgumentTypesSQL + `, retType, body, language, db, definer, modified_time, created_time, type, security_type, comment, character_set_client, collation_connection, database_collation, sql_mode` +// userDefinedFunctionCatalogLegacySourceColumns is used for snapshots whose +// historical table predates immutable revision heads. Such rows remain +// usable for existing SQL catalog behavior, while the new Python resolver +// rejects the zero revision and requires an explicit CREATE/replace. +const userDefinedFunctionCatalogLegacySourceColumns = `function_id, 0, 0, name, owner, args, ` + + catalog.UserDefinedFunctionArgumentTypesSQL + `, '', '', 0, '', retType, body, language, db, definer, modified_time, created_time, type, security_type, comment, character_set_client, collation_connection, database_collation, sql_mode` + +const functionRevisionCatalogColumns = `function_id, revision, namespace_version, name, args, arg_types, rettype, body, language, definition_schema_version, abi_contract, adapter_version, artifact_digest, environment_digest, sdk_version, null_policy, volatility, definition_fingerprint, created_time, security_type` // isCurrentSchemaUserDefinedFunctionCatalog identifies the catalog whose // schema is owned by the running binary. Restoring a historical CREATE TABLE @@ -92,6 +116,14 @@ func isCurrentSchemaUserDefinedFunctionCatalog(tblInfo *tableInfo) bool { return tblInfo != nil && tblInfo.dbName == moCatalog && tblInfo.tblName == "mo_user_defined_function" } +// isCurrentFunctionRevisionCatalog identifies the immutable shared revision +// catalog whose schema is owned by the running binary. A historical CREATE +// TABLE must never replace it: SQL and Python resolvers need every contract +// column to reject stale or partially restored definitions before execution. +func isCurrentFunctionRevisionCatalog(tblInfo *tableInfo) bool { + return tblInfo != nil && tblInfo.dbName == moCatalog && tblInfo.tblName == "mo_function_revisions" +} + // restoreUserDefinedFunctionCatalogWithCurrentSchema restores historical UDF // rows into the current catalog shape. The source may predate arg_types, so // the copy deliberately derives it from args through the same ByteJson SQL @@ -103,6 +135,7 @@ func restoreUserDefinedFunctionCatalogWithCurrentSchema( sourceSnapshot string, sourceAccount uint32, targetAccount uint32, + sourceCreateSQL string, ) error { targetCtx := defines.AttachAccountId(ctx, targetAccount) tableName := qualifiedTableName(moCatalog, "mo_user_defined_function") @@ -113,11 +146,22 @@ func restoreUserDefinedFunctionCatalogWithCurrentSchema( return err } + sourceColumns := userDefinedFunctionCatalogLegacySourceColumns + lowerCreateSQL := strings.ToLower(sourceCreateSQL) + if strings.Contains(lowerCreateSQL, "active_revision") && strings.Contains(lowerCreateSQL, "namespace_version") { + sourceColumns = userDefinedFunctionCatalogRevisionSourceColumns + if strings.Contains(lowerCreateSQL, "canonical_input_descriptor") && + strings.Contains(lowerCreateSQL, "return_descriptor") && + strings.Contains(lowerCreateSQL, "signature_key_schema_version") && + strings.Contains(lowerCreateSQL, "signature_fingerprint") { + sourceColumns = userDefinedFunctionCatalogSourceColumns + } + } copySQL := fmt.Sprintf( "insert into %s (%s) select %s from %s%s", tableName, userDefinedFunctionCatalogColumns, - userDefinedFunctionCatalogSourceColumns, + sourceColumns, tableName, sourceSnapshot, ) @@ -127,6 +171,288 @@ func restoreUserDefinedFunctionCatalogWithCurrentSchema( return bh.ExecRestore(targetCtx, copySQL, sourceAccount, targetAccount) } +// validateRestoredFunctionRevisionCatalog validates the shared immutable +// revision table. Each language owns a distinct typed implementation contract; +// accepting a SQL row as Python (or vice versa) would make restore fail for a +// valid mixed catalog or publish a row that the resolver cannot execute. +func validateRestoredFunctionRevisionCatalog( + ctx context.Context, + bh BackgroundExec, + targetCtx context.Context, +) error { + tableName := qualifiedTableName(moCatalog, "mo_function_revisions") + query := fmt.Sprintf( + "select %s from %s order by function_id, revision;", + functionRevisionCatalogColumns, + tableName, + ) + rows, err := getStringColsList(targetCtx, bh, query, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19) + if err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: restored Python revision catalog cannot be validated") + } + for rowIndex, row := range rows { + if len(row) != 20 { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored Python revision row %d has %d columns", rowIndex, len(row)) + } + functionID, err := strconv.ParseUint(row[0], 10, 64) + if err != nil || functionID == 0 { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored Python revision row %d has an invalid function identity", rowIndex) + } + revision, err := strconv.ParseUint(row[1], 10, 64) + if err != nil || revision == 0 { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored Python function %d has an invalid revision", functionID) + } + namespace, err := strconv.ParseUint(row[2], 10, 64) + if err != nil || namespace == 0 { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored Python function %d has an invalid namespace version", functionID) + } + definitionSchema, err := strconv.Atoi(row[9]) + if err != nil { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored function %d revision %d has an invalid definition schema", functionID, revision) + } + if row[8] == udf.LanguageSQL { + if err := validateRestoredSQLFunctionRevision(functionID, revision, row, definitionSchema); err != nil { + return err + } + continue + } + if row[8] != udf.LanguagePython || + definitionSchema != udf.PythonDefinitionSchemaVersion || + row[10] != udf.PythonABIContract || + row[11] != udf.PythonAdapterVersion || + row[14] != udf.PythonSDKVersion || + !strings.EqualFold(row[16], "VOLATILE") || + !strings.EqualFold(row[19], "INVOKER") { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored function %d revision %d has an unsupported execution contract", functionID, revision) + } + + body, err := function.DecodePythonRoutineBody(row[7]) + if err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: restored Python function %d revision %d body is invalid", functionID, revision) + } + if body.DefinitionSchemaVersion != definitionSchema || + body.ABIContract != row[10] || + body.AdapterVersion != row[11] || + body.ArtifactDigest != row[12] || + body.EnvironmentDigest != row[13] || + body.SDKVersion != row[14] || + body.NullPolicy != row[15] { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored Python function %d revision %d metadata does not match its definition", functionID, revision) + } + fingerprint, err := function.PythonRoutineFingerprint(row[7]) + if err != nil || row[17] == "" || row[17] != fingerprint { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored Python function %d revision %d fingerprint mismatch", functionID, revision) + } + // `args` retains the shared logical names while `arg_types` in the + // current Python revision is the exact descriptor identity used for + // overload selection. Validate both representations independently; + // comparing arg_types with the logical OID list would reject every + // current Python revision after restore. + if _, err := userDefinedFunctionArgumentTypesFromJSON(row[4]); err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: restored Python function %d revision %d arguments are invalid", functionID, revision) + } + var args []*function.Arg + if err := json.Unmarshal([]byte(row[4]), &args); err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: restored Python function %d revision %d arguments are invalid", functionID, revision) + } + routine := &function.Udf{ + Language: udf.LanguagePython, + Args: args, + RetType: row[6], + PythonArgTypes: append([]function.PythonTypeDescriptor(nil), body.ArgTypes...), + PythonReturnType: body.ReturnType, + } + if err := routine.ValidatePythonTypeContract(); err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: restored Python function %d revision %d type contract mismatch", functionID, revision) + } + if err := routine.ValidatePythonCatalogSignature(); err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: restored Python function %d revision %d catalog signature mismatch", functionID, revision) + } + expectedInput, _, _, err := function.PythonSignatureMetadata(body.ArgTypes, body.ReturnType) + if err != nil || row[5] != expectedInput { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored Python function %d revision %d argument descriptor mismatch", functionID, revision) + } + } + return nil +} + +func validateRestoredSQLFunctionRevision(functionID, revision uint64, row []string, definitionSchema int) error { + if definitionSchema != udf.SQLDefinitionSchemaVersion || + row[10] != "" || row[11] != "" || row[12] != "" || row[13] != "" || row[14] != "" || + row[15] != udf.NullCallHandler || !strings.EqualFold(row[16], "VOLATILE") || + !strings.EqualFold(row[19], "DEFINER") { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored SQL function %d revision %d has an unsupported execution contract", functionID, revision) + } + logicalArgTypes, err := userDefinedFunctionArgumentTypesFromJSON(row[4]) + if err != nil || logicalArgTypes != row[5] { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored SQL function %d revision %d argument metadata is invalid", functionID, revision) + } + fingerprint, err := function.SQLRoutineFingerprint(row[7], row[5], row[6]) + if err != nil || row[17] == "" || row[17] != fingerprint { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored SQL function %d revision %d fingerprint mismatch", functionID, revision) + } + return nil +} + +// validateRestoredFunctionCatalogHeads checks the other half of the shared +// immutable publication. The revision validator proves each copied row is +// self-consistent; this check proves that the active head points at that exact +// row after restore. +func validateRestoredFunctionCatalogHeads( + ctx context.Context, + bh BackgroundExec, + targetCtx context.Context, +) error { + query := `select cast(f.function_id as char), cast(f.active_revision as char), cast(f.namespace_version as char), + cast(coalesce(r.revision, 0) as char), cast(coalesce(r.namespace_version, 0) as char), + f.canonical_input_descriptor, f.return_descriptor, + cast(f.signature_key_schema_version as char), f.signature_fingerprint, + coalesce(r.arg_types, ''), coalesce(r.rettype, ''), coalesce(r.body, ''), + lower(f.language), coalesce(r.definition_fingerprint, ''), + coalesce(r.security_type, ''), coalesce(f.security_type, '') + from mo_catalog.mo_user_defined_function f + left join mo_catalog.mo_function_revisions r + on r.function_id = f.function_id and r.revision = f.active_revision + and r.namespace_version = f.namespace_version + where lower(f.language) in ("python", "sql") + order by f.function_id;` + rows, err := getStringColsList(targetCtx, bh, query, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) + if err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: restored routine catalog heads cannot be validated") + } + for rowIndex, row := range rows { + if len(row) != 16 { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored routine catalog head row %d has %d columns", rowIndex, len(row)) + } + functionID, err := strconv.ParseUint(row[0], 10, 64) + if err != nil || functionID == 0 { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored routine catalog head row %d has an invalid function identity", rowIndex) + } + activeRevision, err := strconv.ParseUint(row[1], 10, 64) + if err != nil { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored routine function %d has an invalid active revision: %v", functionID, err) + } + namespaceVersion, err := strconv.ParseUint(row[2], 10, 64) + if err != nil { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored routine function %d has an invalid namespace version: %v", functionID, err) + } + language := strings.ToLower(row[12]) + if (language == udf.LanguageSQL || language == udf.LanguagePython) && activeRevision == 0 && namespaceVersion == 0 { + // Legacy SQL rows predate the shared revision table and retain their + // old execution path. Legacy Python demo rows are preserved as inert + // catalog data as well: the current Python resolver has no execution + // path for them and rejects them before user code, while DROP/CREATE + // can replace the row explicitly. A current head is validated below. + continue + } + if activeRevision == 0 { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored %s function %d has no active immutable revision", language, functionID) + } + if namespaceVersion == 0 { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored %s function %d has an invalid namespace version", language, functionID) + } + revision, err := strconv.ParseUint(row[3], 10, 64) + if err != nil || revision != activeRevision { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored %s function %d active revision does not exist", language, functionID) + } + revisionNamespace, err := strconv.ParseUint(row[4], 10, 64) + if err != nil || revisionNamespace != namespaceVersion { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored %s function %d head namespace does not match its revision", language, functionID) + } + if language == udf.LanguageSQL { + if row[10] == "" || row[11] == "" { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored SQL function %d has incomplete active revision", functionID) + } + if !strings.EqualFold(row[14], "DEFINER") || !strings.EqualFold(row[15], "DEFINER") { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored SQL function %d has inconsistent security contract", functionID) + } + expectedFingerprint, fingerprintErr := function.SQLRoutineFingerprint(row[11], row[9], row[10]) + if fingerprintErr != nil || row[13] == "" || row[13] != expectedFingerprint { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored SQL function %d head fingerprint does not match its active revision", functionID) + } + continue + } + if language != udf.LanguagePython { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored function %d has unsupported language %q", functionID, row[12]) + } + if row[5] == "" || row[6] == "" || row[7] == "" || row[8] == "" || row[9] == "" || row[10] == "" || row[11] == "" || row[13] == "" || + !strings.EqualFold(row[14], "INVOKER") || !strings.EqualFold(row[15], "INVOKER") || + !strings.EqualFold(row[14], row[15]) { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored Python function %d has incomplete head identity", functionID) + } + body, err := function.DecodePythonRoutineBody(row[11]) + if err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: restored Python function %d head body is invalid", functionID) + } + input, output, signature, err := function.PythonSignatureMetadata(body.ArgTypes, body.ReturnType) + if err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: restored Python function %d head signature is invalid", functionID) + } + bodyFingerprint, fingerprintErr := function.PythonRoutineFingerprint(row[11]) + if fingerprintErr != nil || row[13] != bodyFingerprint || + row[5] != input || row[6] != output || row[7] != strconv.Itoa(udf.PythonSignatureKeySchemaVersion) || row[8] != signature || row[9] != input { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored Python function %d head identity does not match its active revision", functionID) + } + } + return nil +} + +// restoreFunctionRevisionCatalogWithCurrentSchema restores only a revision +// table that already carries the current immutable shared contract. Older/demo +// revision tables are intentionally left empty after the current table is +// created. Their rows cannot be losslessly interpreted by the new resolver, and +// the corresponding active head will be rejected until the function is +// explicitly recreated with the current DDL. +func restoreFunctionRevisionCatalogWithCurrentSchema( + ctx context.Context, + bh BackgroundExec, + sourceSnapshot string, + sourceAccount uint32, + targetAccount uint32, + sourceCreateSQL string, +) error { + targetCtx := defines.AttachAccountId(ctx, targetAccount) + tableName := qualifiedTableName(moCatalog, "mo_function_revisions") + if err := bh.Exec(targetCtx, dropTableIfExistsSQL(moCatalog, "mo_function_revisions")); err != nil { + return err + } + if err := bh.Exec(targetCtx, MoCatalogMoFunctionRevisionDDL); err != nil { + return err + } + + // Requiring every current column makes the refusal stable for all older + // layouts. Checking the CREATE text also avoids querying a historical table + // with columns that only exist in the target schema. + lowerCreateSQL := strings.ToLower(sourceCreateSQL) + for _, column := range strings.Split(functionRevisionCatalogColumns, ", ") { + if !strings.Contains(lowerCreateSQL, strings.ToLower(column)) { + return nil + } + } + + copySQL := fmt.Sprintf( + "insert into %s (%s) select %s from %s%s", + tableName, + functionRevisionCatalogColumns, + functionRevisionCatalogColumns, + tableName, + sourceSnapshot, + ) + if sourceAccount == targetAccount { + if err := bh.Exec(targetCtx, copySQL); err != nil { + return err + } + } else if err := bh.ExecRestore(targetCtx, copySQL, sourceAccount, targetAccount); err != nil { + return err + } + // A current revision table is executable metadata. Validate the copied + // rows after the transport has completed so a backup/restore or cross + // account path cannot publish a row whose body, logical catalog columns, + // digest, or current ABI disagree. The resolver repeats this check at bind + // time; restore must fail early as well, before a bad head can be reused. + return validateRestoredFunctionRevisionCatalog(ctx, bh, targetCtx) +} + func restoreSystemCatalogsAfterObjects( ctx context.Context, sid string, @@ -151,6 +477,83 @@ func restoreSystemCatalogsAfterObjects( return err } } + if bh == nil { + return nil + } + if err := validateRestoredFunctionCatalogHeads( + ctx, + bh, + defines.AttachAccountId(ctx, targetAccount), + ); err != nil { + return err + } + return publishRestoredPythonArtifacts( + ctx, + sid, + bh, + defines.AttachAccountId(ctx, targetAccount), + targetAccount, + ) +} + +// publishRestoredPythonArtifacts rebuilds the account-scoped immutable +// artifact objects after a catalog restore. Catalog rows and FileService +// objects are separate persistence domains; copying only the revision table +// would leave a syntactically valid head that cannot execute after restore. +// This runs after all catalog identity/head checks, uses the exact restored +// revision body, and publishes write-once objects before restore returns. +func publishRestoredPythonArtifacts( + ctx context.Context, + sid string, + bh BackgroundExec, + targetCtx context.Context, + targetAccount uint32, +) error { + rows, err := getStringColsList( + targetCtx, + bh, + "select language, artifact_digest, body from mo_catalog.mo_function_revisions order by function_id, revision;", + 0, 1, 2, + ) + if err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: restored Python artifacts cannot be inspected") + } + needStore := false + for rowIndex, row := range rows { + if len(row) != 3 { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored revision row %d has %d artifact columns", rowIndex, len(row)) + } + if row[0] == udf.LanguagePython { + needStore = true + break + } + } + if !needStore { + return nil + } + pu := getPuIfPresent(sid) + if pu == nil || pu.FileService == nil { + return moerr.NewNotSupportedNoCtx("Python artifact store is required to restore a current Python revision") + } + store, err := pythonudf.NewFileArtifactStore(pu.FileService, pythonudf.DefaultMaxArtifactBytes) + if err != nil { + return err + } + for rowIndex, row := range rows { + if row[0] != udf.LanguagePython { + continue + } + body, decodeErr := function.DecodePythonRoutineBody(row[2]) + if decodeErr != nil { + return errutil.Wrapf(decodeErr, "UNSUPPORTED_ROUTINE_VERSION: restored Python artifact row %d is invalid", rowIndex) + } + if body.ArtifactDigest != row[1] { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: restored Python artifact row %d digest does not match its revision", rowIndex) + } + if _, publishErr := store.Publish(ctx, uint64(targetAccount), body.Handler, body.Source); publishErr != nil { + return publishErr + } + } return nil } diff --git a/pkg/frontend/snapshot_restore_with_ts.go b/pkg/frontend/snapshot_restore_with_ts.go index a30be51a15902..5b6d50b475ba3 100644 --- a/pkg/frontend/snapshot_restore_with_ts.go +++ b/pkg/frontend/snapshot_restore_with_ts.go @@ -576,6 +576,17 @@ func recreateTableFromTS( fmt.Sprintf(" {MO_TS = %d}", snapshotTs), restoreAccount, toAccountId, + tblInfo.createSql, + ) + } + if isCurrentFunctionRevisionCatalog(tblInfo) { + return restoreFunctionRevisionCatalogWithCurrentSchema( + ctx, + bh, + fmt.Sprintf(" {MO_TS = %d}", snapshotTs), + restoreAccount, + toAccountId, + tblInfo.createSql, ) } if isSequence(tblInfo) { diff --git a/pkg/frontend/snapshot_test.go b/pkg/frontend/snapshot_test.go index 6ae7a25e19cc5..df9b88aa95cde 100644 --- a/pkg/frontend/snapshot_test.go +++ b/pkg/frontend/snapshot_test.go @@ -1804,6 +1804,20 @@ func TestRecreateUserDefinedFunctionCatalogPreservesCurrentSchema(t *testing.T) tblName: "mo_user_defined_function", createSql: legacyCreateSQL, } + currentUDFTable := &tableInfo{ + dbName: moCatalog, + tblName: "mo_user_defined_function", + createSql: MoCatalogMoUserDefinedFunctionDDL, + } + + t.Run("current schema preserves revision head", func(t *testing.T) { + bh := &backgroundExecTest{} + bh.init() + ctx := defines.AttachAccountId(t.Context(), sourceAccount) + require.NoError(t, recreateTable(ctx, "", bh, snapshotName, currentUDFTable, sourceAccount, snapshotTS, false)) + require.Contains(t, bh.executedSQLs[len(bh.executedSQLs)-1], + " select "+userDefinedFunctionCatalogSourceColumns+" from ") + }) t.Run("same account timestamp snapshot", func(t *testing.T) { bh := &backgroundExecTest{} @@ -1814,7 +1828,7 @@ func TestRecreateUserDefinedFunctionCatalogPreservesCurrentSchema(t *testing.T) dropTableIfExistsSQL(moCatalog, udfTable.tblName), MoCatalogMoUserDefinedFunctionDDL, "insert into `mo_catalog`.`mo_user_defined_function` (" + userDefinedFunctionCatalogColumns + - ") select " + userDefinedFunctionCatalogSourceColumns + + ") select " + userDefinedFunctionCatalogLegacySourceColumns + " from `mo_catalog`.`mo_user_defined_function` {MO_TS = 123}", }, bh.executedSQLs) require.NotContains(t, strings.Join(bh.executedSQLs, "\n"), legacyCreateSQL) @@ -1827,7 +1841,7 @@ func TestRecreateUserDefinedFunctionCatalogPreservesCurrentSchema(t *testing.T) require.NoError(t, recreateTable(ctx, "", bh, snapshotName, udfTable, targetAccount, snapshotTS, false)) require.Equal(t, "insert into `mo_catalog`.`mo_user_defined_function` ("+userDefinedFunctionCatalogColumns+ - ") select "+userDefinedFunctionCatalogSourceColumns+ + ") select "+userDefinedFunctionCatalogLegacySourceColumns+ " from `mo_catalog`.`mo_user_defined_function` {SNAPSHOT = 'udf_snapshot'}", bh.executedSQLs[len(bh.executedSQLs)-1], ) @@ -1842,7 +1856,7 @@ func TestRecreateUserDefinedFunctionCatalogPreservesCurrentSchema(t *testing.T) )) require.Equal(t, "insert into `mo_catalog`.`mo_user_defined_function` ("+userDefinedFunctionCatalogColumns+ - ") select "+userDefinedFunctionCatalogSourceColumns+ + ") select "+userDefinedFunctionCatalogLegacySourceColumns+ " from `mo_catalog`.`mo_user_defined_function` {MO_TS = 123}", bh.executedSQLs[len(bh.executedSQLs)-1], ) @@ -1856,7 +1870,7 @@ func TestRecreateUserDefinedFunctionCatalogPreservesCurrentSchema(t *testing.T) require.NoError(t, reCreateTableWithPitr(ctx, "", bh, "udf_pitr", snapshotTS, udfTable)) require.Equal(t, "insert into `mo_catalog`.`mo_user_defined_function` ("+userDefinedFunctionCatalogColumns+ - ") select "+userDefinedFunctionCatalogSourceColumns+ + ") select "+userDefinedFunctionCatalogLegacySourceColumns+ " from `mo_catalog`.`mo_user_defined_function` {MO_TS = 123}", bh.executedSQLs[len(bh.executedSQLs)-1], ) @@ -1864,6 +1878,105 @@ func TestRecreateUserDefinedFunctionCatalogPreservesCurrentSchema(t *testing.T) }) } +func TestRecreatePythonFunctionRevisionCatalogPreservesCurrentSchema(t *testing.T) { + const ( + sourceAccount = uint32(10) + targetAccount = uint32(20) + snapshotName = "python_revision_snapshot" + snapshotTS = int64(123) + ) + legacyCreateSQL := "create table mo_catalog.mo_function_revisions (function_id bigint, revision bigint, name varchar(100), body text)" + legacyTable := &tableInfo{ + dbName: moCatalog, + tblName: "mo_function_revisions", + createSql: legacyCreateSQL, + } + currentTable := &tableInfo{ + dbName: moCatalog, + tblName: "mo_function_revisions", + createSql: MoCatalogMoFunctionRevisionDDL, + } + copySQL := func(sourceSnapshot string) string { + return "insert into `mo_catalog`.`mo_function_revisions` (" + functionRevisionCatalogColumns + + ") select " + functionRevisionCatalogColumns + + " from `mo_catalog`.`mo_function_revisions`" + sourceSnapshot + } + validationSQL := fmt.Sprintf( + "select %s from %s order by function_id, revision;", + functionRevisionCatalogColumns, + qualifiedTableName(moCatalog, "mo_function_revisions"), + ) + + t.Run("same account current revision schema", func(t *testing.T) { + bh := &backgroundExecTest{} + bh.init() + bh.sql2result[validationSQL] = &MysqlResultSet{} + ctx := defines.AttachAccountId(t.Context(), sourceAccount) + require.NoError(t, recreateTable(ctx, "", bh, snapshotName, currentTable, sourceAccount, snapshotTS, false)) + require.Equal(t, []string{ + dropTableIfExistsSQL(moCatalog, currentTable.tblName), + MoCatalogMoFunctionRevisionDDL, + copySQL(" {MO_TS = 123}"), + validationSQL, + }, bh.executedSQLs) + }) + + t.Run("legacy revision rows are not copied", func(t *testing.T) { + bh := &backgroundExecTest{} + bh.init() + ctx := defines.AttachAccountId(t.Context(), sourceAccount) + require.NoError(t, recreateTable(ctx, "", bh, snapshotName, legacyTable, sourceAccount, snapshotTS, false)) + require.Equal(t, []string{ + dropTableIfExistsSQL(moCatalog, legacyTable.tblName), + MoCatalogMoFunctionRevisionDDL, + }, bh.executedSQLs) + require.NotContains(t, strings.Join(bh.executedSQLs, "\n"), legacyCreateSQL) + }) + + t.Run("cross account named snapshot", func(t *testing.T) { + bh := &backgroundExecTest{} + bh.init() + bh.sql2result[validationSQL] = &MysqlResultSet{} + ctx := defines.AttachAccountId(t.Context(), sourceAccount) + require.NoError(t, recreateTable(ctx, "", bh, snapshotName, currentTable, targetAccount, snapshotTS, false)) + require.Equal(t, []string{ + dropTableIfExistsSQL(moCatalog, currentTable.tblName), + MoCatalogMoFunctionRevisionDDL, + copySQL(" {SNAPSHOT = 'python_revision_snapshot'}"), + validationSQL, + }, bh.executedSQLs) + }) + + t.Run("cross account timestamp restore", func(t *testing.T) { + bh := &backgroundExecTest{} + bh.init() + bh.sql2result[validationSQL] = &MysqlResultSet{} + require.NoError(t, recreateTableFromTS( + t.Context(), "", bh, currentTable, snapshotTS, sourceAccount, targetAccount, + )) + require.Equal(t, []string{ + dropTableIfExistsSQL(moCatalog, currentTable.tblName), + MoCatalogMoFunctionRevisionDDL, + copySQL(" {MO_TS = 123}"), + validationSQL, + }, bh.executedSQLs) + }) + + t.Run("point in time recovery", func(t *testing.T) { + bh := &backgroundExecTest{} + bh.init() + bh.sql2result[validationSQL] = &MysqlResultSet{} + ctx := defines.AttachAccountId(t.Context(), sourceAccount) + require.NoError(t, reCreateTableWithPitr(ctx, "", bh, "python_revision_pitr", snapshotTS, currentTable)) + require.Equal(t, []string{ + dropTableIfExistsSQL(moCatalog, currentTable.tblName), + MoCatalogMoFunctionRevisionDDL, + copySQL(" {MO_TS = 123}"), + validationSQL, + }, bh.executedSQLs) + }) +} + func Test_fkTablesTopoSortWithTS(t *testing.T) { convey.Convey("fkTablesTopoSortWithTS ", t, func() { ctrl := gomock.NewController(t) diff --git a/pkg/iceberg/api/import_boundary_test.go b/pkg/iceberg/api/import_boundary_test.go index d628a98ecfcb1..fde304fd1db79 100644 --- a/pkg/iceberg/api/import_boundary_test.go +++ b/pkg/iceberg/api/import_boundary_test.go @@ -23,13 +23,42 @@ import ( "testing" ) -func TestIcebergAdapterImportBoundary(t *testing.T) { +type importBoundaryPolicy struct { + name string + importPrefixes []string + allowedDirectories []string + allowedFiles []string +} + +var importBoundaryPolicies = []importBoundaryPolicy{ + { + name: "Iceberg", + importPrefixes: []string{"github.com/apache/iceberg-go"}, + allowedDirectories: []string{ + "pkg/iceberg/adapter/iceberggo", + }, + }, + { + name: "Arrow", + importPrefixes: []string{ + "github.com/apache/arrow-go", + "github.com/apache/arrow/go", + }, + allowedDirectories: []string{ + "pkg/iceberg/adapter/iceberggo", + "pkg/container/arrowbridge", + "pkg/sql/colexec/external/arrowio", + "pkg/udf/python", + }, + allowedFiles: []string{ + "pkg/sql/colexec/external/reader_arrow.go", + "pkg/sql/compile/compile.go", + }, + }, +} + +func TestIcebergAndArrowImportBoundaries(t *testing.T) { root := findRepoRoot(t) - forbidden := []string{ - "github.com/apache/iceberg-go", - "github.com/apache/arrow-go", - "github.com/apache/arrow/go", - } err := filepath.WalkDir(root, func(path string, d os.DirEntry, walkErr error) error { if walkErr != nil { return walkErr @@ -52,20 +81,18 @@ func TestIcebergAdapterImportBoundary(t *testing.T) { if parseErr != nil { return parseErr } - slashPath := filepath.ToSlash(path) - // Arrow has two approved MatrixOne-owned boundaries: the Iceberg - // adapter and the static-file ingestion bridge. Everywhere else remains - // forbidden so an implementation detail cannot leak into SQL layers. - arrowAllowed := strings.Contains(slashPath, "/pkg/iceberg/adapter/iceberggo/") || - strings.Contains(slashPath, "/pkg/container/arrowbridge/") || - strings.Contains(slashPath, "/pkg/sql/colexec/external/arrowio/") || - strings.HasSuffix(slashPath, "/pkg/sql/colexec/external/reader_arrow.go") || - strings.HasSuffix(slashPath, "/pkg/sql/compile/compile.go") + relativePath, relErr := filepath.Rel(root, path) + if relErr != nil { + return relErr + } + slashPath := filepath.ToSlash(relativePath) for _, imp := range file.Imports { importPath := strings.Trim(imp.Path.Value, `"`) - for _, prefix := range forbidden { - if strings.HasPrefix(importPath, prefix) && !arrowAllowed { - t.Fatalf("forbidden Iceberg/Arrow import outside adapter: %s imports %s", slashPath, importPath) + for _, policy := range importBoundaryPolicies { + if importMatchesPrefix(importPath, policy.importPrefixes) && + !policy.allows(slashPath) { + t.Fatalf("forbidden %s import outside an approved owner: %s imports %s", + policy.name, slashPath, importPath) } } } @@ -76,6 +103,80 @@ func TestIcebergAdapterImportBoundary(t *testing.T) { } } +func (p importBoundaryPolicy) allows(relativePath string) bool { + for _, directory := range p.allowedDirectories { + if relativePath == directory || strings.HasPrefix(relativePath, directory+"/") { + return true + } + } + for _, file := range p.allowedFiles { + if relativePath == file { + return true + } + } + return false +} + +func importMatchesPrefix(importPath string, prefixes []string) bool { + for _, prefix := range prefixes { + if importPath == prefix || strings.HasPrefix(importPath, prefix+"/") { + return true + } + } + return false +} + +func TestImportBoundaryPolicies(t *testing.T) { + tests := []struct { + name string + policy importBoundaryPolicy + relativePath string + importPath string + allowed bool + }{ + { + name: "UDF owns Arrow but not Iceberg", + policy: importBoundaryPolicies[1], + relativePath: "pkg/udf/python/gateway.go", + importPath: "github.com/apache/arrow-go/v18/arrow/flight/gen/flight", + allowed: true, + }, + { + name: "UDF cannot own Iceberg", + policy: importBoundaryPolicies[0], + relativePath: "pkg/udf/python/gateway.go", + importPath: "github.com/apache/iceberg-go/io", + allowed: false, + }, + { + name: "Iceberg adapter owns Iceberg", + policy: importBoundaryPolicies[0], + relativePath: "pkg/iceberg/adapter/iceberggo/io.go", + importPath: "github.com/apache/iceberg-go/io", + allowed: true, + }, + { + name: "sibling package is not an Arrow owner", + policy: importBoundaryPolicies[1], + relativePath: "pkg/udf/pythonish/gateway.go", + importPath: "github.com/apache/arrow-go/v18/arrow", + allowed: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + matches := importMatchesPrefix(tt.importPath, tt.policy.importPrefixes) + if !matches { + t.Fatal("expected policy to match the protected module") + } + if tt.policy.allows(tt.relativePath) != tt.allowed { + t.Fatalf("policy allowed=%v for %s importing %s, want %v", + tt.policy.allows(tt.relativePath), tt.relativePath, tt.importPath, tt.allowed) + } + }) + } +} + func TestIcebergPackagesUseMOErrorAndCauseAwareTimeouts(t *testing.T) { root := findRepoRoot(t) bareFmtErrorf := "fmt." + "Errorf(" @@ -126,3 +227,25 @@ func findRepoRoot(t *testing.T) string { dir = parent } } + +func TestImportBoundaryModuleNames(t *testing.T) { + for _, tc := range []struct { + path string + want bool + }{ + {"github.com/apache/arrow-go/v18/arrow", true}, + {"github.com/apache/arrow/go/v12/arrow", true}, + {"github.com/apache/arrow-gopher/arrow", false}, + {"github.com/apache/arrow/golang", false}, + {"example.com/arrow", false}, + } { + if got := importMatchesPrefix(tc.path, importBoundaryPolicies[1].importPrefixes); got != tc.want { + t.Errorf("%s: got %v, want %v", tc.path, got, tc.want) + } + } + for _, path := range []string{"pkg/container/arrowbridge/reader.go", "pkg/sql/plan/binder.go"} { + if importBoundaryPolicies[0].allows(path) { + t.Errorf("Iceberg unexpectedly allowed in %s", path) + } + } +} diff --git a/pkg/pb/plan/plan.pb.go b/pkg/pb/plan/plan.pb.go index dff90cbf4d436..5d7d28e045b01 100644 --- a/pkg/pb/plan/plan.pb.go +++ b/pkg/pb/plan/plan.pb.go @@ -3062,10 +3062,12 @@ type Function struct { // Planner provenance only. Explicit CAST syntax can share the legacy CAST // overload while optimizers still distinguish it from an implicit cast. // Older CNs safely ignore this unknown field and execute the legacy overload. - SyntaxExplicitCast bool `protobuf:"varint,5,opt,name=syntax_explicit_cast,json=syntaxExplicitCast,proto3" json:"syntax_explicit_cast,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + SyntaxExplicitCast bool `protobuf:"varint,5,opt,name=syntax_explicit_cast,json=syntaxExplicitCast,proto3" json:"syntax_explicit_cast,omitempty"` + // Typed routine metadata. Ordinary builtin Function values leave this nil. + RoutineCall *RoutineCall `protobuf:"bytes,6,opt,name=routine_call,json=routineCall,proto3" json:"routine_call,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Function) Reset() { *m = Function{} } @@ -3136,6 +3138,13 @@ func (m *Function) GetSyntaxExplicitCast() bool { return false } +func (m *Function) GetRoutineCall() *RoutineCall { + if m != nil { + return m.RoutineCall + } + return nil +} + // PreparedNumericMetadata is sparse planner provenance for a numeric overload // or runtime string domain that cannot be represented by Expr.Type alone. // It is kept behind one optional pointer on Expr because the metadata is rare; @@ -10846,9 +10855,14 @@ type Query struct { // execution so a committed concurrent CREATE INDEX can rebuild the plan; // without a definition change, it returns the original key-not-found error. UnresolvedIndexHints []*UnresolvedIndexHint `protobuf:"bytes,16,rep,name=unresolved_index_hints,json=unresolvedIndexHints,proto3" json:"unresolved_index_hints,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + // Exact routine revisions captured while binding this statement. The + // expression tree carries the call-site implementation, while this bounded + // envelope lets prepared and ordinary plan-cache reuse validate the shared + // catalog namespace without walking or reinterpreting user source. + RoutineDependencies []*RoutinePlanDependency `protobuf:"bytes,17,rep,name=routine_dependencies,json=routineDependencies,proto3" json:"routine_dependencies,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Query) Reset() { *m = Query{} } @@ -10996,6 +11010,13 @@ func (m *Query) GetUnresolvedIndexHints() []*UnresolvedIndexHint { return nil } +func (m *Query) GetRoutineDependencies() []*RoutinePlanDependency { + if m != nil { + return m.RoutineDependencies + } + return nil +} + type TransationControl struct { // TransationControl type TclType TransationControl_TclType `protobuf:"varint,1,opt,name=tcl_type,json=tclType,proto3,enum=plan.TransationControl_TclType" json:"tcl_type,omitempty"` @@ -16340,6 +16361,621 @@ func (m *UnresolvedIndexHint) GetIndexName() string { return "" } +// FunctionRef is the exact catalog identity carried by an executable plan. +// A zero revision is invalid for external routines; the planner validates the +// complete call before a fragment is dispatched. +type FunctionRef struct { + FunctionId uint64 `protobuf:"varint,1,opt,name=function_id,json=functionId,proto3" json:"function_id,omitempty"` + Revision uint64 `protobuf:"varint,2,opt,name=revision,proto3" json:"revision,omitempty"` + NamespaceVersion uint64 `protobuf:"varint,3,opt,name=namespace_version,json=namespaceVersion,proto3" json:"namespace_version,omitempty"` + // Function identity is tenant/database scoped. These fields prevent a + // plan fragment from being interpreted in a different catalog namespace. + AccountId uint64 `protobuf:"varint,4,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"` + DatabaseId uint64 `protobuf:"varint,5,opt,name=database_id,json=databaseId,proto3" json:"database_id,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *FunctionRef) Reset() { *m = FunctionRef{} } +func (m *FunctionRef) String() string { return proto.CompactTextString(m) } +func (*FunctionRef) ProtoMessage() {} +func (*FunctionRef) Descriptor() ([]byte, []int) { + return fileDescriptor_2d655ab2f7683c23, []int{153} +} +func (m *FunctionRef) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *FunctionRef) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_FunctionRef.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 *FunctionRef) XXX_Merge(src proto.Message) { + xxx_messageInfo_FunctionRef.Merge(m, src) +} +func (m *FunctionRef) XXX_Size() int { + return m.ProtoSize() +} +func (m *FunctionRef) XXX_DiscardUnknown() { + xxx_messageInfo_FunctionRef.DiscardUnknown(m) +} + +var xxx_messageInfo_FunctionRef proto.InternalMessageInfo + +func (m *FunctionRef) GetFunctionId() uint64 { + if m != nil { + return m.FunctionId + } + return 0 +} + +func (m *FunctionRef) GetRevision() uint64 { + if m != nil { + return m.Revision + } + return 0 +} + +func (m *FunctionRef) GetNamespaceVersion() uint64 { + if m != nil { + return m.NamespaceVersion + } + return 0 +} + +func (m *FunctionRef) GetAccountId() uint64 { + if m != nil { + return m.AccountId + } + return 0 +} + +func (m *FunctionRef) GetDatabaseId() uint64 { + if m != nil { + return m.DatabaseId + } + return 0 +} + +type SqlRoutineImplementation struct { + DefinitionFingerprint []byte `protobuf:"bytes,1,opt,name=definition_fingerprint,json=definitionFingerprint,proto3" json:"definition_fingerprint,omitempty"` + SemanticDefinitionSchemaVersion int32 `protobuf:"varint,2,opt,name=semantic_definition_schema_version,json=semanticDefinitionSchemaVersion,proto3" json:"semantic_definition_schema_version,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SqlRoutineImplementation) Reset() { *m = SqlRoutineImplementation{} } +func (m *SqlRoutineImplementation) String() string { return proto.CompactTextString(m) } +func (*SqlRoutineImplementation) ProtoMessage() {} +func (*SqlRoutineImplementation) Descriptor() ([]byte, []int) { + return fileDescriptor_2d655ab2f7683c23, []int{154} +} +func (m *SqlRoutineImplementation) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SqlRoutineImplementation) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SqlRoutineImplementation.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 *SqlRoutineImplementation) XXX_Merge(src proto.Message) { + xxx_messageInfo_SqlRoutineImplementation.Merge(m, src) +} +func (m *SqlRoutineImplementation) XXX_Size() int { + return m.ProtoSize() +} +func (m *SqlRoutineImplementation) XXX_DiscardUnknown() { + xxx_messageInfo_SqlRoutineImplementation.DiscardUnknown(m) +} + +var xxx_messageInfo_SqlRoutineImplementation proto.InternalMessageInfo + +func (m *SqlRoutineImplementation) GetDefinitionFingerprint() []byte { + if m != nil { + return m.DefinitionFingerprint + } + return nil +} + +func (m *SqlRoutineImplementation) GetSemanticDefinitionSchemaVersion() int32 { + if m != nil { + return m.SemanticDefinitionSchemaVersion + } + return 0 +} + +type PythonRoutineImplementation struct { + Handler string `protobuf:"bytes,1,opt,name=handler,proto3" json:"handler,omitempty"` + // Source is retained only so an old serialized demo plan can be identified + // and rejected. A current executable plan must carry the immutable artifact + // digest and resolve the artifact through the runtime artifact store. + Source string `protobuf:"bytes,2,opt,name=source,proto3" json:"source,omitempty"` // Deprecated: Do not use. + AbiContract string `protobuf:"bytes,3,opt,name=abi_contract,json=abiContract,proto3" json:"abi_contract,omitempty"` + AdapterVersion string `protobuf:"bytes,4,opt,name=adapter_version,json=adapterVersion,proto3" json:"adapter_version,omitempty"` + ArtifactDigest string `protobuf:"bytes,5,opt,name=artifact_digest,json=artifactDigest,proto3" json:"artifact_digest,omitempty"` + EnvironmentDigest string `protobuf:"bytes,6,opt,name=environment_digest,json=environmentDigest,proto3" json:"environment_digest,omitempty"` + SdkVersion string `protobuf:"bytes,7,opt,name=sdk_version,json=sdkVersion,proto3" json:"sdk_version,omitempty"` + DefinitionSchemaVersion int32 `protobuf:"varint,8,opt,name=definition_schema_version,json=definitionSchemaVersion,proto3" json:"definition_schema_version,omitempty"` + Mode string `protobuf:"bytes,9,opt,name=mode,proto3" json:"mode,omitempty"` + NullPolicy string `protobuf:"bytes,10,opt,name=null_policy,json=nullPolicy,proto3" json:"null_policy,omitempty"` + DefinitionFingerprint string `protobuf:"bytes,11,opt,name=definition_fingerprint,json=definitionFingerprint,proto3" json:"definition_fingerprint,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PythonRoutineImplementation) Reset() { *m = PythonRoutineImplementation{} } +func (m *PythonRoutineImplementation) String() string { return proto.CompactTextString(m) } +func (*PythonRoutineImplementation) ProtoMessage() {} +func (*PythonRoutineImplementation) Descriptor() ([]byte, []int) { + return fileDescriptor_2d655ab2f7683c23, []int{155} +} +func (m *PythonRoutineImplementation) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PythonRoutineImplementation) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PythonRoutineImplementation.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 *PythonRoutineImplementation) XXX_Merge(src proto.Message) { + xxx_messageInfo_PythonRoutineImplementation.Merge(m, src) +} +func (m *PythonRoutineImplementation) XXX_Size() int { + return m.ProtoSize() +} +func (m *PythonRoutineImplementation) XXX_DiscardUnknown() { + xxx_messageInfo_PythonRoutineImplementation.DiscardUnknown(m) +} + +var xxx_messageInfo_PythonRoutineImplementation proto.InternalMessageInfo + +func (m *PythonRoutineImplementation) GetHandler() string { + if m != nil { + return m.Handler + } + return "" +} + +// Deprecated: Do not use. +func (m *PythonRoutineImplementation) GetSource() string { + if m != nil { + return m.Source + } + return "" +} + +func (m *PythonRoutineImplementation) GetAbiContract() string { + if m != nil { + return m.AbiContract + } + return "" +} + +func (m *PythonRoutineImplementation) GetAdapterVersion() string { + if m != nil { + return m.AdapterVersion + } + return "" +} + +func (m *PythonRoutineImplementation) GetArtifactDigest() string { + if m != nil { + return m.ArtifactDigest + } + return "" +} + +func (m *PythonRoutineImplementation) GetEnvironmentDigest() string { + if m != nil { + return m.EnvironmentDigest + } + return "" +} + +func (m *PythonRoutineImplementation) GetSdkVersion() string { + if m != nil { + return m.SdkVersion + } + return "" +} + +func (m *PythonRoutineImplementation) GetDefinitionSchemaVersion() int32 { + if m != nil { + return m.DefinitionSchemaVersion + } + return 0 +} + +func (m *PythonRoutineImplementation) GetMode() string { + if m != nil { + return m.Mode + } + return "" +} + +func (m *PythonRoutineImplementation) GetNullPolicy() string { + if m != nil { + return m.NullPolicy + } + return "" +} + +func (m *PythonRoutineImplementation) GetDefinitionFingerprint() string { + if m != nil { + return m.DefinitionFingerprint + } + return "" +} + +// RoutineCall is the common typed call envelope for SQL and external +// language routines. Function.Args remains the normal expression argument +// list so existing expression traversal and CASE/selection ownership stay +// intact; this field carries only immutable routine identity and semantics. +type RoutineCall struct { + ContractVersion int32 `protobuf:"varint,1,opt,name=contract_version,json=contractVersion,proto3" json:"contract_version,omitempty"` + FunctionRef *FunctionRef `protobuf:"bytes,2,opt,name=function_ref,json=functionRef,proto3" json:"function_ref,omitempty"` + Language string `protobuf:"bytes,3,opt,name=language,proto3" json:"language,omitempty"` + ArgumentTypes []*Type `protobuf:"bytes,4,rep,name=argument_types,json=argumentTypes,proto3" json:"argument_types,omitempty"` + ReturnType Type `protobuf:"bytes,5,opt,name=return_type,json=returnType,proto3" json:"return_type"` + Volatility string `protobuf:"bytes,6,opt,name=volatility,proto3" json:"volatility,omitempty"` + NullPolicy string `protobuf:"bytes,7,opt,name=null_policy,json=nullPolicy,proto3" json:"null_policy,omitempty"` + // Types that are valid to be assigned to Implementation: + // + // *RoutineCall_Sql + // *RoutineCall_Python + Implementation isRoutineCall_Implementation `protobuf_oneof:"implementation"` + // Reserved from the current executable contract. Statement identity, + // session values, and group fences are created at execution time; keeping + // them in a prepared plan would allow stale state to cross executions. + Context map[string]string `protobuf:"bytes,10,rep,name=context,proto3" json:"context,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // Deprecated: Do not use. + // These fields are the common semantic contract. They must survive SQL + // lowering and expression/plan cloning; the optimizer may only move a + // routine call when the attached contract permits it. + CallsiteId string `protobuf:"bytes,11,opt,name=callsite_id,json=callsiteId,proto3" json:"callsite_id,omitempty"` + MayError bool `protobuf:"varint,12,opt,name=may_error,json=mayError,proto3" json:"may_error,omitempty"` + SecurityMode string `protobuf:"bytes,13,opt,name=security_mode,json=securityMode,proto3" json:"security_mode,omitempty"` + Leakproof bool `protobuf:"varint,14,opt,name=leakproof,proto3" json:"leakproof,omitempty"` + // State fingerprint of the complete overload namespace at binding snapshot. + // Separate from the selected immutable FunctionRef; missing means no reuse. + NamespaceFingerprint string `protobuf:"bytes,15,opt,name=namespace_fingerprint,json=namespaceFingerprint,proto3" json:"namespace_fingerprint,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *RoutineCall) Reset() { *m = RoutineCall{} } +func (m *RoutineCall) String() string { return proto.CompactTextString(m) } +func (*RoutineCall) ProtoMessage() {} +func (*RoutineCall) Descriptor() ([]byte, []int) { + return fileDescriptor_2d655ab2f7683c23, []int{156} +} +func (m *RoutineCall) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RoutineCall) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RoutineCall.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 *RoutineCall) XXX_Merge(src proto.Message) { + xxx_messageInfo_RoutineCall.Merge(m, src) +} +func (m *RoutineCall) XXX_Size() int { + return m.ProtoSize() +} +func (m *RoutineCall) XXX_DiscardUnknown() { + xxx_messageInfo_RoutineCall.DiscardUnknown(m) +} + +var xxx_messageInfo_RoutineCall proto.InternalMessageInfo + +type isRoutineCall_Implementation interface { + isRoutineCall_Implementation() + MarshalTo([]byte) (int, error) + ProtoSize() int +} + +type RoutineCall_Sql struct { + Sql *SqlRoutineImplementation `protobuf:"bytes,8,opt,name=sql,proto3,oneof" json:"sql,omitempty"` +} +type RoutineCall_Python struct { + Python *PythonRoutineImplementation `protobuf:"bytes,9,opt,name=python,proto3,oneof" json:"python,omitempty"` +} + +func (*RoutineCall_Sql) isRoutineCall_Implementation() {} +func (*RoutineCall_Python) isRoutineCall_Implementation() {} + +func (m *RoutineCall) GetImplementation() isRoutineCall_Implementation { + if m != nil { + return m.Implementation + } + return nil +} + +func (m *RoutineCall) GetContractVersion() int32 { + if m != nil { + return m.ContractVersion + } + return 0 +} + +func (m *RoutineCall) GetFunctionRef() *FunctionRef { + if m != nil { + return m.FunctionRef + } + return nil +} + +func (m *RoutineCall) GetLanguage() string { + if m != nil { + return m.Language + } + return "" +} + +func (m *RoutineCall) GetArgumentTypes() []*Type { + if m != nil { + return m.ArgumentTypes + } + return nil +} + +func (m *RoutineCall) GetReturnType() Type { + if m != nil { + return m.ReturnType + } + return Type{} +} + +func (m *RoutineCall) GetVolatility() string { + if m != nil { + return m.Volatility + } + return "" +} + +func (m *RoutineCall) GetNullPolicy() string { + if m != nil { + return m.NullPolicy + } + return "" +} + +func (m *RoutineCall) GetSql() *SqlRoutineImplementation { + if x, ok := m.GetImplementation().(*RoutineCall_Sql); ok { + return x.Sql + } + return nil +} + +func (m *RoutineCall) GetPython() *PythonRoutineImplementation { + if x, ok := m.GetImplementation().(*RoutineCall_Python); ok { + return x.Python + } + return nil +} + +// Deprecated: Do not use. +func (m *RoutineCall) GetContext() map[string]string { + if m != nil { + return m.Context + } + return nil +} + +func (m *RoutineCall) GetCallsiteId() string { + if m != nil { + return m.CallsiteId + } + return "" +} + +func (m *RoutineCall) GetMayError() bool { + if m != nil { + return m.MayError + } + return false +} + +func (m *RoutineCall) GetSecurityMode() string { + if m != nil { + return m.SecurityMode + } + return "" +} + +func (m *RoutineCall) GetLeakproof() bool { + if m != nil { + return m.Leakproof + } + return false +} + +func (m *RoutineCall) GetNamespaceFingerprint() string { + if m != nil { + return m.NamespaceFingerprint + } + return "" +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*RoutineCall) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*RoutineCall_Sql)(nil), + (*RoutineCall_Python)(nil), + } +} + +// RoutinePlanDependency is the shared cache/prepared-plan validation envelope +// for a resolved routine closure. FunctionRef is the executable identity; +// the integrity fields prove that the implementation attached to the plan is +// the same immutable revision that the resolver admitted. +type RoutinePlanDependency struct { + FunctionRef *FunctionRef `protobuf:"bytes,1,opt,name=function_ref,json=functionRef,proto3" json:"function_ref,omitempty"` + Language string `protobuf:"bytes,2,opt,name=language,proto3" json:"language,omitempty"` + ContractVersion int32 `protobuf:"varint,3,opt,name=contract_version,json=contractVersion,proto3" json:"contract_version,omitempty"` + DefinitionFingerprint string `protobuf:"bytes,4,opt,name=definition_fingerprint,json=definitionFingerprint,proto3" json:"definition_fingerprint,omitempty"` + ArtifactDigest string `protobuf:"bytes,5,opt,name=artifact_digest,json=artifactDigest,proto3" json:"artifact_digest,omitempty"` + EnvironmentDigest string `protobuf:"bytes,6,opt,name=environment_digest,json=environmentDigest,proto3" json:"environment_digest,omitempty"` + Volatility string `protobuf:"bytes,7,opt,name=volatility,proto3" json:"volatility,omitempty"` + NullPolicy string `protobuf:"bytes,8,opt,name=null_policy,json=nullPolicy,proto3" json:"null_policy,omitempty"` + MayError bool `protobuf:"varint,9,opt,name=may_error,json=mayError,proto3" json:"may_error,omitempty"` + SecurityMode string `protobuf:"bytes,10,opt,name=security_mode,json=securityMode,proto3" json:"security_mode,omitempty"` + Leakproof bool `protobuf:"varint,11,opt,name=leakproof,proto3" json:"leakproof,omitempty"` + NamespaceFingerprint string `protobuf:"bytes,12,opt,name=namespace_fingerprint,json=namespaceFingerprint,proto3" json:"namespace_fingerprint,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *RoutinePlanDependency) Reset() { *m = RoutinePlanDependency{} } +func (m *RoutinePlanDependency) String() string { return proto.CompactTextString(m) } +func (*RoutinePlanDependency) ProtoMessage() {} +func (*RoutinePlanDependency) Descriptor() ([]byte, []int) { + return fileDescriptor_2d655ab2f7683c23, []int{157} +} +func (m *RoutinePlanDependency) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RoutinePlanDependency) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RoutinePlanDependency.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 *RoutinePlanDependency) XXX_Merge(src proto.Message) { + xxx_messageInfo_RoutinePlanDependency.Merge(m, src) +} +func (m *RoutinePlanDependency) XXX_Size() int { + return m.ProtoSize() +} +func (m *RoutinePlanDependency) XXX_DiscardUnknown() { + xxx_messageInfo_RoutinePlanDependency.DiscardUnknown(m) +} + +var xxx_messageInfo_RoutinePlanDependency proto.InternalMessageInfo + +func (m *RoutinePlanDependency) GetFunctionRef() *FunctionRef { + if m != nil { + return m.FunctionRef + } + return nil +} + +func (m *RoutinePlanDependency) GetLanguage() string { + if m != nil { + return m.Language + } + return "" +} + +func (m *RoutinePlanDependency) GetContractVersion() int32 { + if m != nil { + return m.ContractVersion + } + return 0 +} + +func (m *RoutinePlanDependency) GetDefinitionFingerprint() string { + if m != nil { + return m.DefinitionFingerprint + } + return "" +} + +func (m *RoutinePlanDependency) GetArtifactDigest() string { + if m != nil { + return m.ArtifactDigest + } + return "" +} + +func (m *RoutinePlanDependency) GetEnvironmentDigest() string { + if m != nil { + return m.EnvironmentDigest + } + return "" +} + +func (m *RoutinePlanDependency) GetVolatility() string { + if m != nil { + return m.Volatility + } + return "" +} + +func (m *RoutinePlanDependency) GetNullPolicy() string { + if m != nil { + return m.NullPolicy + } + return "" +} + +func (m *RoutinePlanDependency) GetMayError() bool { + if m != nil { + return m.MayError + } + return false +} + +func (m *RoutinePlanDependency) GetSecurityMode() string { + if m != nil { + return m.SecurityMode + } + return "" +} + +func (m *RoutinePlanDependency) GetLeakproof() bool { + if m != nil { + return m.Leakproof + } + return false +} + +func (m *RoutinePlanDependency) GetNamespaceFingerprint() string { + if m != nil { + return m.NamespaceFingerprint + } + return "" +} + func init() { proto.RegisterEnum("plan.StringLiteralForm", StringLiteralForm_name, StringLiteralForm_value) proto.RegisterEnum("plan.AggregateConfigType", AggregateConfigType_name, AggregateConfigType_value) @@ -16541,1105 +17177,1154 @@ func init() { proto.RegisterType((*ODKUForeignKeyCheck)(nil), "plan.ODKUForeignKeyCheck") proto.RegisterType((*VectorIndexScanWork)(nil), "plan.VectorIndexScanWork") proto.RegisterType((*UnresolvedIndexHint)(nil), "plan.UnresolvedIndexHint") + proto.RegisterType((*FunctionRef)(nil), "plan.FunctionRef") + proto.RegisterType((*SqlRoutineImplementation)(nil), "plan.SqlRoutineImplementation") + proto.RegisterType((*PythonRoutineImplementation)(nil), "plan.PythonRoutineImplementation") + proto.RegisterType((*RoutineCall)(nil), "plan.RoutineCall") + proto.RegisterMapType((map[string]string)(nil), "plan.RoutineCall.ContextEntry") + proto.RegisterType((*RoutinePlanDependency)(nil), "plan.RoutinePlanDependency") } func init() { proto.RegisterFile("plan.proto", fileDescriptor_2d655ab2f7683c23) } var fileDescriptor_2d655ab2f7683c23 = []byte{ - // 17475 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0xbd, 0x5b, 0x6c, 0x23, 0xd9, - 0x92, 0x20, 0x56, 0x14, 0x29, 0x89, 0x0c, 0x52, 0x54, 0xea, 0x94, 0xaa, 0x8a, 0x55, 0x5d, 0x5d, - 0xa5, 0xce, 0xae, 0xee, 0xae, 0xae, 0xee, 0xae, 0xee, 0xae, 0xea, 0x47, 0xf5, 0x9d, 0x3b, 0x7b, - 0x2f, 0x45, 0x51, 0x25, 0x76, 0x51, 0xa4, 0x6e, 0x92, 0xaa, 0xea, 0xbe, 0xb3, 0x83, 0x44, 0x8a, - 0x99, 0x92, 0xb2, 0x95, 0xcc, 0x64, 0x67, 0x26, 0x4b, 0x52, 0x03, 0x86, 0x2f, 0xfc, 0xe1, 0xf1, - 0x18, 0xfe, 0x58, 0x63, 0xe0, 0xf5, 0x87, 0x01, 0x63, 0x76, 0x81, 0x85, 0x81, 0xb5, 0xfd, 0x61, - 0x63, 0xe1, 0xf5, 0x03, 0x6b, 0x63, 0xbd, 0x06, 0xbc, 0x80, 0x0d, 0x63, 0xe0, 0x85, 0x3d, 0xb6, - 0x17, 0xd8, 0x35, 0x66, 0xfe, 0x6d, 0x03, 0xf6, 0x8f, 0xfd, 0x63, 0x23, 0x22, 0xce, 0xc9, 0x07, - 0xc9, 0xea, 0xc7, 0x9d, 0x19, 0xc0, 0x3f, 0x12, 0x4f, 0x44, 0x9c, 0x93, 0xe7, 0x19, 0x27, 0x22, - 0x4e, 0x9c, 0x38, 0x00, 0x13, 0xcf, 0xf2, 0x1f, 0x4e, 0xc2, 0x20, 0x0e, 0x44, 0x09, 0x7f, 0xdf, - 0xfa, 0xe0, 0xc4, 0x8d, 0x4f, 0xa7, 0x47, 0x0f, 0x47, 0xc1, 0xf8, 0xc3, 0x93, 0xe0, 0x24, 0xf8, - 0x90, 0x90, 0x47, 0xd3, 0x63, 0x4a, 0x51, 0x82, 0x7e, 0x71, 0xa6, 0x5b, 0xe0, 0x05, 0xa3, 0x33, - 0xf9, 0x7b, 0x3d, 0x76, 0xc7, 0x4e, 0x14, 0x5b, 0xe3, 0x09, 0x03, 0xf4, 0xff, 0xad, 0x00, 0xa5, - 0xe1, 0xe5, 0xc4, 0x11, 0x75, 0x58, 0x72, 0xed, 0x46, 0x61, 0xab, 0x70, 0x7f, 0xd9, 0x58, 0x72, - 0x6d, 0xb1, 0x05, 0x55, 0x3f, 0x88, 0x7b, 0x53, 0xcf, 0xb3, 0x8e, 0x3c, 0xa7, 0xb1, 0xb4, 0x55, - 0xb8, 0x5f, 0x36, 0xb2, 0x20, 0xf1, 0x1a, 0x54, 0xac, 0x69, 0x1c, 0x98, 0xae, 0x3f, 0x0a, 0x1b, - 0x45, 0xc2, 0x97, 0x11, 0xd0, 0xf1, 0x47, 0xa1, 0xd8, 0x84, 0xe5, 0x73, 0xd7, 0x8e, 0x4f, 0x1b, - 0x25, 0x2a, 0x91, 0x13, 0x08, 0x8d, 0x46, 0x96, 0xe7, 0x34, 0x96, 0x19, 0x4a, 0x09, 0x84, 0xc6, - 0xf4, 0x91, 0x95, 0xad, 0xc2, 0xfd, 0x8a, 0xc1, 0x09, 0x71, 0x07, 0xc0, 0xf1, 0xa7, 0xe3, 0x97, - 0x96, 0x37, 0x75, 0xa2, 0xc6, 0x2a, 0xa1, 0x32, 0x10, 0xd1, 0x80, 0xd5, 0xd1, 0xa9, 0x15, 0x46, - 0x4e, 0xdc, 0x28, 0x6f, 0x15, 0xee, 0xaf, 0x19, 0x2a, 0x89, 0x15, 0x9b, 0x58, 0xb6, 0x19, 0x4d, - 0xac, 0x91, 0xd3, 0xa8, 0x70, 0xc5, 0x26, 0x96, 0x3d, 0xc0, 0xb4, 0xfe, 0x0b, 0xa8, 0x8c, 0xa3, - 0x93, 0x3d, 0xc7, 0xb2, 0x9d, 0x50, 0xdc, 0x80, 0xd5, 0x71, 0x74, 0x62, 0xc6, 0xd6, 0x89, 0x6c, - 0xf9, 0xca, 0x38, 0x3a, 0x19, 0x5a, 0x27, 0xe2, 0x26, 0x94, 0x09, 0x71, 0x39, 0xe1, 0xa6, 0x2f, - 0x1b, 0x48, 0x88, 0x1d, 0xa5, 0xff, 0xc9, 0x2a, 0xac, 0x76, 0xdd, 0xd8, 0x09, 0x2d, 0x4f, 0x5c, - 0x87, 0x15, 0x37, 0xf2, 0xa7, 0x9e, 0x47, 0xd9, 0xcb, 0x86, 0x4c, 0x89, 0xeb, 0xb0, 0xec, 0x3e, - 0x79, 0x69, 0x79, 0x9c, 0x77, 0xef, 0x8a, 0xc1, 0x49, 0xd1, 0x80, 0x15, 0xf7, 0xe3, 0xcf, 0x10, - 0x51, 0x94, 0x08, 0x99, 0x26, 0xcc, 0xe3, 0x47, 0x88, 0x29, 0x25, 0x18, 0x4a, 0x13, 0xe6, 0xb3, - 0x4f, 0x10, 0x83, 0x9d, 0x56, 0x24, 0x0c, 0xa5, 0xf1, 0x2b, 0x53, 0xfa, 0x0a, 0xf6, 0xdb, 0x1a, - 0x7e, 0x65, 0xaa, 0xbe, 0x32, 0xe5, 0xaf, 0xac, 0x4a, 0x84, 0x4c, 0x13, 0x86, 0xbf, 0x52, 0x4e, - 0x30, 0xc9, 0x57, 0xa6, 0xfc, 0x15, 0xec, 0xb0, 0x12, 0x61, 0xf8, 0x2b, 0x9b, 0x50, 0xb2, 0x11, - 0x0e, 0x5b, 0x85, 0xfb, 0x85, 0xbd, 0x2b, 0x06, 0xa5, 0x10, 0x1a, 0x21, 0xb4, 0x8a, 0xe3, 0x82, - 0xd0, 0x48, 0x42, 0x8f, 0x10, 0x5a, 0xc3, 0xde, 0x40, 0xe8, 0x91, 0x84, 0x1e, 0x23, 0x74, 0x6d, - 0xab, 0x70, 0x7f, 0x09, 0xa1, 0x98, 0x12, 0xb7, 0x60, 0xd5, 0xb6, 0x62, 0x07, 0x11, 0x75, 0xd9, - 0x64, 0x05, 0x40, 0x1c, 0x4e, 0x54, 0xc4, 0xad, 0xcb, 0x46, 0x2b, 0x80, 0xd0, 0xa1, 0x8a, 0x64, - 0x0a, 0xaf, 0x49, 0x7c, 0x16, 0x28, 0x3e, 0x85, 0x9a, 0xed, 0x8c, 0xdc, 0xb1, 0xe5, 0x71, 0x9b, - 0x36, 0xb6, 0x0a, 0xf7, 0xab, 0x8f, 0xd6, 0x1f, 0xd2, 0x52, 0x4a, 0x30, 0x7b, 0x57, 0x8c, 0x1c, - 0x99, 0x78, 0x02, 0x6b, 0x32, 0xfd, 0xf1, 0x23, 0xea, 0x58, 0x41, 0xf9, 0xb4, 0x5c, 0xbe, 0x8f, - 0x1f, 0x3d, 0xd9, 0xbb, 0x62, 0xe4, 0x09, 0xc5, 0x3d, 0xa8, 0x25, 0x2b, 0x0b, 0x33, 0x5e, 0x95, - 0xb5, 0xca, 0x41, 0xb1, 0x59, 0xdf, 0x44, 0x81, 0x8f, 0x04, 0x9b, 0xb2, 0xdf, 0x14, 0x40, 0x6c, - 0x01, 0xd8, 0xce, 0xb1, 0x35, 0xf5, 0x62, 0x44, 0x5f, 0x93, 0x1d, 0x98, 0x81, 0x89, 0x3b, 0x50, - 0x99, 0x4e, 0xb0, 0x95, 0xcf, 0x2d, 0xaf, 0x71, 0x5d, 0x12, 0xa4, 0x20, 0x2c, 0x1d, 0x97, 0x07, - 0x62, 0x6f, 0xc8, 0xd1, 0x55, 0x00, 0x1c, 0xde, 0x97, 0xce, 0x08, 0x51, 0x0d, 0xf9, 0x61, 0x99, - 0xc6, 0xc5, 0xe7, 0x46, 0xdb, 0xae, 0xdf, 0xb8, 0x49, 0x33, 0x98, 0x13, 0xe2, 0x36, 0x14, 0xa3, - 0x70, 0xd4, 0xb8, 0x45, 0xed, 0x07, 0x6e, 0x7f, 0xfb, 0x62, 0x12, 0x1a, 0x08, 0x16, 0x6f, 0xc2, - 0x9a, 0x1b, 0x99, 0x91, 0x13, 0xba, 0x96, 0xe7, 0x7e, 0xe7, 0xd8, 0x8d, 0xd7, 0x28, 0x6f, 0xcd, - 0x8d, 0x06, 0x09, 0x4c, 0xfc, 0x0c, 0x6a, 0x1e, 0x2f, 0x13, 0xf3, 0x38, 0x08, 0xc7, 0x8d, 0xdb, - 0x5b, 0x85, 0xfb, 0xf5, 0x47, 0x37, 0xb8, 0xac, 0x41, 0x1c, 0xba, 0xfe, 0x89, 0x5c, 0x46, 0xbb, - 0x41, 0x38, 0x36, 0xaa, 0x5e, 0x9a, 0xc0, 0x0f, 0x44, 0x44, 0x61, 0x46, 0xc1, 0x34, 0x1c, 0x39, - 0x8d, 0xd7, 0x69, 0x85, 0xd7, 0x18, 0x38, 0x20, 0x98, 0xf8, 0x05, 0xdc, 0x96, 0x83, 0x60, 0xaa, - 0x0f, 0x85, 0xce, 0xb7, 0x53, 0x37, 0x74, 0x22, 0xf3, 0xe5, 0x93, 0x47, 0x8d, 0x3b, 0x54, 0xa9, - 0x9b, 0x92, 0x46, 0x7e, 0xcb, 0x90, 0x14, 0xcf, 0x9f, 0x3c, 0xda, 0x5e, 0x85, 0x65, 0xe2, 0x25, - 0xfa, 0x6d, 0x28, 0x1f, 0x58, 0xa1, 0x35, 0x36, 0x9c, 0x63, 0xa1, 0x41, 0x71, 0x12, 0x44, 0x92, - 0x1d, 0xe0, 0x4f, 0xbd, 0x0b, 0x2b, 0xcf, 0xad, 0x10, 0x71, 0x02, 0x4a, 0xbe, 0x35, 0x76, 0x08, - 0x59, 0x31, 0xe8, 0x37, 0xb2, 0x80, 0xe8, 0x32, 0x8a, 0x9d, 0xb1, 0x64, 0x91, 0x32, 0x85, 0xf0, - 0x13, 0x2f, 0x38, 0x92, 0x4b, 0xbd, 0x6c, 0xc8, 0x94, 0xfe, 0x2f, 0x15, 0x60, 0xa5, 0x15, 0x78, - 0x58, 0xdc, 0x0d, 0x58, 0x0d, 0x1d, 0xcf, 0x4c, 0x3f, 0xb7, 0x12, 0x3a, 0xde, 0x41, 0x10, 0x21, - 0x62, 0x14, 0x30, 0x82, 0x99, 0xcf, 0xca, 0x28, 0x20, 0x84, 0xaa, 0x40, 0x31, 0x53, 0x81, 0x9b, - 0x50, 0x8e, 0x8f, 0x3c, 0x93, 0xe0, 0x25, 0x82, 0xaf, 0xc6, 0x47, 0x5e, 0x0f, 0x51, 0x37, 0x60, - 0xd5, 0x3e, 0x62, 0xcc, 0x32, 0x61, 0x56, 0xec, 0x23, 0x44, 0xe8, 0x5f, 0x40, 0xc5, 0xb0, 0xce, - 0x65, 0x35, 0xae, 0xc1, 0x0a, 0x16, 0x20, 0xb9, 0x7f, 0xc9, 0x58, 0x8e, 0x8f, 0xbc, 0x8e, 0x8d, - 0x60, 0xac, 0x84, 0x6b, 0x53, 0x1d, 0x4a, 0xc6, 0xf2, 0x28, 0xf0, 0x3a, 0xb6, 0x3e, 0x04, 0x68, - 0x05, 0x61, 0xf8, 0x5b, 0x37, 0x61, 0x13, 0x96, 0x6d, 0x67, 0x12, 0x9f, 0x32, 0x07, 0x34, 0x38, - 0xa1, 0x3f, 0x80, 0x32, 0x4e, 0xaf, 0xae, 0x1b, 0xc5, 0xe2, 0x0e, 0x94, 0x3c, 0x37, 0x8a, 0x1b, - 0x85, 0xad, 0xe2, 0xcc, 0xe4, 0x23, 0xb8, 0xbe, 0x05, 0xe5, 0x7d, 0xeb, 0xe2, 0x39, 0x8e, 0x1c, - 0x96, 0x46, 0x43, 0x28, 0x87, 0x44, 0x8e, 0x67, 0x0d, 0x60, 0x68, 0x85, 0x27, 0x4e, 0x4c, 0x0c, - 0xfb, 0xff, 0x2c, 0x40, 0x75, 0x30, 0x3d, 0xfa, 0x76, 0xea, 0x84, 0x97, 0x58, 0xe7, 0xfb, 0x50, - 0x8c, 0x2f, 0x27, 0x94, 0xa3, 0xfe, 0xe8, 0xba, 0x9c, 0x8f, 0x29, 0xfe, 0x21, 0x66, 0x32, 0x90, - 0x04, 0x1b, 0xe1, 0x07, 0xb6, 0xa3, 0xfa, 0x60, 0xd9, 0x58, 0xc1, 0x64, 0xc7, 0xc6, 0xcd, 0x32, - 0x98, 0xc8, 0x51, 0x58, 0x0a, 0x26, 0x62, 0x0b, 0x96, 0x47, 0xa7, 0xae, 0x67, 0xd3, 0x00, 0xe4, - 0xeb, 0xcc, 0x08, 0x1c, 0xa5, 0x30, 0x38, 0x37, 0x23, 0xf7, 0x3b, 0xb5, 0xf9, 0xad, 0x86, 0xc1, - 0xf9, 0xc0, 0xfd, 0xce, 0xd1, 0x87, 0x72, 0x07, 0x06, 0x58, 0x19, 0xb4, 0x9a, 0xdd, 0xa6, 0xa1, - 0x5d, 0xc1, 0xdf, 0xed, 0xaf, 0x3a, 0x83, 0xe1, 0x40, 0x2b, 0x88, 0x3a, 0x40, 0xaf, 0x3f, 0x34, - 0x65, 0x7a, 0x49, 0xac, 0xc0, 0x52, 0xa7, 0xa7, 0x15, 0x91, 0x06, 0xe1, 0x9d, 0x9e, 0x56, 0x12, - 0xab, 0x50, 0x6c, 0xf6, 0xbe, 0xd6, 0x96, 0xe9, 0x47, 0xb7, 0xab, 0xad, 0xe8, 0xff, 0xcf, 0x12, - 0x54, 0xfa, 0x47, 0xdf, 0x38, 0xa3, 0x18, 0xdb, 0x8c, 0xb3, 0xd4, 0x09, 0x5f, 0x3a, 0x21, 0x35, - 0xbb, 0x68, 0xc8, 0x14, 0x36, 0xc4, 0x3e, 0xa2, 0xc6, 0x15, 0x8d, 0x25, 0xfb, 0x88, 0xe8, 0x46, - 0xa7, 0xce, 0xd8, 0xa2, 0xc6, 0x21, 0x1d, 0xa5, 0x70, 0x55, 0x04, 0x47, 0xdf, 0x50, 0xf3, 0x8a, - 0x06, 0xfe, 0x14, 0x77, 0xa1, 0xca, 0x65, 0x64, 0xe7, 0x17, 0x30, 0x68, 0x76, 0xf2, 0xad, 0x64, - 0x27, 0x1f, 0xe5, 0xa4, 0x52, 0x19, 0x29, 0x77, 0x76, 0x06, 0xf5, 0xe4, 0x8c, 0x0e, 0x8e, 0xbe, - 0x61, 0x6c, 0x99, 0x67, 0x74, 0x70, 0xf4, 0x0d, 0xa1, 0xde, 0x83, 0x8d, 0x68, 0x7a, 0x14, 0x8d, - 0x42, 0x77, 0x12, 0xbb, 0x81, 0xcf, 0x34, 0x15, 0xa2, 0xd1, 0xb2, 0x08, 0x22, 0xbe, 0x0f, 0xe5, - 0xc9, 0xf4, 0xc8, 0x74, 0xfd, 0xe3, 0x80, 0x76, 0xaf, 0xea, 0xa3, 0x35, 0x1e, 0x98, 0x83, 0xe9, - 0x51, 0xc7, 0x3f, 0x0e, 0x8c, 0xd5, 0x09, 0xff, 0x10, 0x3a, 0xac, 0xf9, 0x41, 0x6c, 0xa2, 0xa0, - 0x64, 0x8e, 0x9d, 0xd8, 0xa2, 0x6d, 0x8d, 0xc5, 0x9d, 0x6e, 0x30, 0x3a, 0xdb, 0x77, 0x62, 0x4b, - 0x3c, 0x80, 0x72, 0xe4, 0x5b, 0x93, 0xe8, 0x34, 0x88, 0x69, 0x7f, 0xab, 0x3e, 0xaa, 0xcb, 0xb9, - 0x23, 0xa1, 0x46, 0x82, 0xd7, 0xdf, 0x86, 0x55, 0xf9, 0x0d, 0x14, 0x46, 0x62, 0xc7, 0xb7, 0xfc, - 0xd8, 0x4c, 0xc4, 0xab, 0x32, 0x03, 0x3a, 0xb6, 0xfe, 0xf7, 0x0a, 0xa0, 0x0d, 0x32, 0xd5, 0xa6, - 0x0f, 0x2d, 0xe2, 0x32, 0xaf, 0x03, 0x58, 0xa3, 0x51, 0x30, 0xe5, 0x62, 0x78, 0x32, 0x56, 0x24, - 0xa4, 0x63, 0x67, 0xfb, 0xba, 0x98, 0xeb, 0xeb, 0x37, 0xa0, 0xa6, 0xf2, 0x65, 0x18, 0x44, 0x55, - 0xc2, 0x54, 0x6f, 0x47, 0xd3, 0x1c, 0x97, 0x58, 0x8d, 0xa6, 0x9c, 0xfb, 0x3a, 0xac, 0x90, 0x2c, - 0x16, 0xa9, 0x11, 0xe4, 0x94, 0xfe, 0xa7, 0x05, 0x58, 0xeb, 0xf8, 0xb6, 0x73, 0x31, 0x18, 0x59, - 0xbe, 0xea, 0x40, 0x37, 0x32, 0x5d, 0x84, 0x99, 0xd1, 0xc8, 0xf2, 0xa5, 0x3c, 0x54, 0x75, 0xa3, - 0x84, 0x0e, 0xdb, 0xc0, 0x04, 0xf4, 0xa9, 0x25, 0x2a, 0xb1, 0x42, 0x10, 0xfa, 0xd8, 0xdb, 0xb0, - 0x7e, 0xe4, 0x78, 0x81, 0x7f, 0x62, 0xc6, 0x81, 0xc9, 0xf2, 0x20, 0xb7, 0x65, 0x8d, 0xc1, 0xc3, - 0x60, 0x48, 0x72, 0xe1, 0x26, 0x2c, 0x4f, 0xac, 0x30, 0x8e, 0x1a, 0xa5, 0xad, 0x22, 0x2e, 0x79, - 0x4a, 0x60, 0x37, 0xbb, 0x91, 0x39, 0xf5, 0xdd, 0x6f, 0xa7, 0xdc, 0x8c, 0xb2, 0x51, 0x76, 0xa3, - 0x43, 0x4a, 0x8b, 0xfb, 0xa0, 0xf1, 0x97, 0xa9, 0xd8, 0xec, 0x9c, 0xac, 0x13, 0x9c, 0x0a, 0x26, - 0xc6, 0xf8, 0x6f, 0x17, 0xa1, 0xbc, 0x3b, 0xf5, 0x47, 0x38, 0x18, 0xe2, 0x4d, 0x28, 0x1d, 0x4f, - 0xfd, 0x11, 0xb5, 0x25, 0x91, 0x1e, 0x92, 0x35, 0x65, 0x10, 0x12, 0xb9, 0x95, 0x15, 0x9e, 0x20, - 0x97, 0x9b, 0xe3, 0x56, 0x08, 0xa7, 0x91, 0x3b, 0x39, 0x31, 0x47, 0x81, 0x7f, 0xec, 0x9e, 0x50, - 0x8b, 0x6a, 0x46, 0xc5, 0x3a, 0x39, 0x69, 0x11, 0x40, 0x34, 0x61, 0x3d, 0x45, 0xb3, 0xbc, 0x59, - 0x22, 0xc6, 0x74, 0x93, 0x4b, 0x6a, 0x9e, 0x9c, 0x84, 0xce, 0x89, 0x15, 0x3b, 0x4c, 0x4f, 0xbc, - 0x69, 0x2d, 0xc9, 0x4e, 0x7c, 0xe3, 0x23, 0xd8, 0x8c, 0x2e, 0xfd, 0xd8, 0xba, 0x30, 0x9d, 0x8b, - 0x89, 0xe7, 0x8e, 0xdc, 0xd8, 0x1c, 0x59, 0x51, 0x2c, 0x7b, 0x41, 0x30, 0xae, 0x2d, 0x51, 0x2d, - 0x2b, 0x8a, 0xf5, 0xff, 0xb8, 0xc0, 0xad, 0xdc, 0xf5, 0xac, 0x13, 0x51, 0x86, 0x52, 0xaf, 0xdf, - 0x6b, 0x6b, 0x57, 0x44, 0x0d, 0xca, 0x9d, 0xde, 0xb0, 0x6d, 0xf4, 0x9a, 0x5d, 0xad, 0x40, 0xec, - 0x68, 0xd8, 0xdc, 0xee, 0xb6, 0xb5, 0x25, 0xc4, 0x3c, 0xef, 0x77, 0x9b, 0xc3, 0x4e, 0xb7, 0xad, - 0x95, 0x18, 0x63, 0x74, 0x5a, 0x43, 0xad, 0x2c, 0x34, 0xa8, 0x1d, 0x18, 0xfd, 0x9d, 0xc3, 0x56, - 0xdb, 0xec, 0x1d, 0x76, 0xbb, 0x9a, 0x26, 0xae, 0xc2, 0x7a, 0x02, 0xe9, 0x33, 0x70, 0x0b, 0xb3, - 0x3c, 0x6f, 0x1a, 0x4d, 0xe3, 0xa9, 0xf6, 0x4b, 0x51, 0x86, 0x62, 0xf3, 0xe9, 0x53, 0xed, 0x37, - 0xc8, 0xd9, 0x2a, 0x2f, 0x3a, 0x3d, 0xf3, 0x79, 0xb3, 0x7b, 0xd8, 0xd6, 0x7e, 0xb3, 0xa4, 0xd2, - 0x7d, 0x63, 0xa7, 0x6d, 0x68, 0xbf, 0x29, 0x89, 0x0d, 0xa8, 0xfd, 0xba, 0xdf, 0x6b, 0xef, 0x37, - 0x0f, 0x0e, 0xa8, 0x22, 0xbf, 0x29, 0xeb, 0x7f, 0x5e, 0x82, 0x1b, 0x07, 0xa1, 0x33, 0xb1, 0x42, - 0xc7, 0xee, 0x4d, 0xc7, 0x4e, 0xe8, 0x8e, 0x70, 0xd1, 0xd8, 0x56, 0x6c, 0x89, 0x5b, 0x50, 0x3e, - 0xb6, 0x3c, 0xef, 0xc8, 0x1a, 0x9d, 0xc9, 0xf9, 0x97, 0xa4, 0x59, 0x27, 0x08, 0xad, 0x71, 0x66, - 0x47, 0x2a, 0x13, 0x00, 0xf7, 0xa4, 0x77, 0x60, 0x5d, 0x11, 0x2a, 0x81, 0x83, 0x37, 0xed, 0xba, - 0x02, 0x4b, 0x91, 0xe3, 0x53, 0xb8, 0x31, 0x43, 0x68, 0xaa, 0x0d, 0x82, 0xf5, 0x9c, 0xcd, 0x7c, - 0x86, 0x1e, 0x6f, 0x17, 0x0b, 0xb2, 0xa9, 0xcd, 0x71, 0x79, 0x51, 0xb6, 0x16, 0x6f, 0x95, 0x9f, - 0xc1, 0x8d, 0x49, 0x18, 0xbc, 0x74, 0x23, 0x37, 0xf0, 0x49, 0xb8, 0x89, 0xa6, 0x9e, 0x1c, 0xdb, - 0x15, 0xaa, 0xde, 0xb5, 0x0c, 0xda, 0x20, 0x2c, 0x0e, 0xef, 0x2b, 0xf2, 0x4d, 0x1c, 0x27, 0x24, - 0x66, 0xbb, 0x28, 0xdf, 0x81, 0xe3, 0x84, 0x62, 0x07, 0xee, 0xbe, 0x22, 0x1f, 0x4d, 0x4c, 0x6c, - 0x65, 0x99, 0xaa, 0xfb, 0xda, 0xc2, 0xfc, 0x38, 0x19, 0x3b, 0xb6, 0x68, 0xc2, 0xeb, 0xaf, 0x2a, - 0x85, 0x35, 0xc2, 0x0a, 0x95, 0x71, 0x6b, 0x61, 0x19, 0x2f, 0x48, 0x4d, 0xfc, 0x9e, 0x22, 0x58, - 0x7d, 0x84, 0xef, 0x29, 0x62, 0x40, 0x3a, 0xe5, 0xcf, 0x61, 0x53, 0x4a, 0x90, 0x76, 0x30, 0xb6, - 0x5c, 0x5f, 0x8d, 0x6b, 0x75, 0x6e, 0x83, 0x16, 0x4c, 0xb7, 0x43, 0x64, 0xdc, 0xff, 0xfa, 0x3f, - 0x58, 0x86, 0x12, 0x22, 0x85, 0x9e, 0xca, 0x0a, 0x49, 0x2e, 0x6c, 0xe7, 0x76, 0xe9, 0x1f, 0xff, - 0xb3, 0xbb, 0x57, 0x58, 0x4a, 0x78, 0x03, 0x8a, 0x9e, 0x1b, 0xd3, 0xa4, 0x4a, 0x76, 0x18, 0x29, - 0x6d, 0xee, 0x5d, 0x31, 0x10, 0x27, 0xee, 0x40, 0x81, 0xc5, 0x85, 0x64, 0xd3, 0x50, 0xf2, 0xe6, - 0xde, 0x15, 0xa3, 0x30, 0x11, 0xb7, 0xa1, 0xf0, 0x52, 0xca, 0x0e, 0x35, 0xc6, 0xb3, 0xc4, 0x89, - 0xd8, 0x97, 0x62, 0x0b, 0x8a, 0xa3, 0x80, 0xd5, 0xbf, 0x04, 0xcf, 0xf2, 0x17, 0x96, 0x3f, 0x0a, - 0x3c, 0xf1, 0x26, 0x14, 0x43, 0xeb, 0x9c, 0x66, 0x45, 0xc2, 0xa8, 0x12, 0x01, 0x0f, 0x89, 0x42, - 0xeb, 0x1c, 0x2b, 0x71, 0x4c, 0x13, 0x20, 0xa9, 0x84, 0xe2, 0x74, 0xf8, 0x99, 0x63, 0xb1, 0x05, - 0x85, 0x73, 0x1a, 0xe0, 0x44, 0xe3, 0x79, 0xe1, 0xfa, 0x76, 0x70, 0x3e, 0x98, 0x38, 0x23, 0xa4, - 0x38, 0x17, 0x6f, 0x41, 0x31, 0x9a, 0x1e, 0xd1, 0x00, 0x56, 0x1f, 0x6d, 0xcc, 0x49, 0x4e, 0xf8, - 0xa1, 0x68, 0x7a, 0x24, 0xde, 0x86, 0xd2, 0x28, 0x08, 0x43, 0xb9, 0xe7, 0x6a, 0xaa, 0xc2, 0x4a, - 0x68, 0x44, 0x0d, 0x10, 0xf1, 0xf8, 0xc1, 0x58, 0x0e, 0x88, 0x24, 0x4a, 0xa5, 0x36, 0xfc, 0x60, - 0x2c, 0xee, 0x49, 0x51, 0x30, 0xb7, 0xdf, 0x2a, 0x41, 0x11, 0xcb, 0x41, 0x2c, 0x0e, 0xd2, 0xd8, - 0xba, 0x20, 0xf5, 0x32, 0x21, 0x52, 0x12, 0x22, 0xd6, 0x69, 0x6c, 0x5d, 0x88, 0x7b, 0x50, 0x7c, - 0xe9, 0x8c, 0x48, 0xd3, 0x4c, 0xbe, 0x26, 0x07, 0xe9, 0x39, 0x35, 0x0f, 0xd1, 0xc4, 0xf1, 0x03, - 0xcf, 0x26, 0xa5, 0x33, 0x19, 0xcb, 0xdd, 0xc0, 0xb3, 0x9f, 0xd3, 0x58, 0x12, 0x12, 0x05, 0x63, - 0x6b, 0x7a, 0x81, 0xab, 0x41, 0x63, 0x11, 0xd6, 0x9a, 0x5e, 0x74, 0x6c, 0x14, 0x91, 0x7c, 0xfb, - 0x25, 0xa9, 0x9a, 0x05, 0x03, 0x7f, 0x8a, 0x2d, 0x14, 0x91, 0x3c, 0x67, 0x14, 0xbb, 0x2f, 0xdd, - 0xf8, 0x92, 0x94, 0xc9, 0x82, 0x91, 0x05, 0x89, 0x3d, 0xd0, 0x26, 0x92, 0x99, 0x99, 0x3e, 0x73, - 0x33, 0x52, 0x1d, 0xab, 0x8f, 0x5e, 0x97, 0xd3, 0x64, 0x31, 0xab, 0x33, 0xd6, 0x27, 0x79, 0xc4, - 0xf6, 0x0a, 0x94, 0x9c, 0x8b, 0x49, 0xf8, 0x65, 0xa9, 0xbc, 0xa9, 0x35, 0xf4, 0x3d, 0x58, 0x95, - 0xb5, 0x9e, 0xb3, 0xeb, 0xdc, 0x84, 0xb2, 0x1b, 0xe1, 0x7e, 0x13, 0xc5, 0x52, 0x63, 0x59, 0x75, - 0xa3, 0x16, 0x26, 0x51, 0xf0, 0xc0, 0xc2, 0xe5, 0x26, 0x45, 0xbf, 0xf5, 0x7f, 0x50, 0x00, 0x48, - 0xfb, 0x09, 0x1b, 0xe9, 0x39, 0xbe, 0xd2, 0x8e, 0x3c, 0xc7, 0x4f, 0x32, 0x2d, 0xa5, 0x99, 0xe6, - 0xf5, 0xc3, 0xe2, 0x02, 0xfd, 0x70, 0x4e, 0xc7, 0x2b, 0xfd, 0x16, 0x3a, 0xde, 0xf2, 0x0f, 0xe8, - 0x78, 0xfa, 0x4d, 0xa8, 0x24, 0x2a, 0xbe, 0xa8, 0x41, 0xc1, 0x92, 0x02, 0x70, 0xc1, 0xd2, 0xef, - 0xa3, 0xc6, 0xad, 0x94, 0xf8, 0x3c, 0x0e, 0x53, 0x4a, 0x2c, 0x2e, 0x1c, 0xe9, 0x3f, 0x87, 0x9a, - 0x64, 0xaf, 0x81, 0xb7, 0xe3, 0x1c, 0x8b, 0xf7, 0x01, 0x92, 0x74, 0x24, 0xf5, 0x94, 0x74, 0x5d, - 0xee, 0x38, 0xc7, 0x46, 0x06, 0xaf, 0xff, 0xad, 0x65, 0xd2, 0xf8, 0x76, 0x58, 0xd5, 0x92, 0x3a, - 0x55, 0x21, 0xa3, 0x53, 0x25, 0x12, 0xdf, 0x52, 0x5e, 0xaf, 0x3c, 0x75, 0x6d, 0xdb, 0xf1, 0x95, - 0xfe, 0xc8, 0x29, 0x9c, 0xc8, 0x96, 0x77, 0x22, 0x85, 0x04, 0xa1, 0x3e, 0x3a, 0x9e, 0x84, 0x4e, - 0x14, 0xb1, 0xe6, 0x62, 0x79, 0x27, 0x8a, 0x6f, 0x2d, 0x7f, 0x1f, 0xdf, 0xba, 0x09, 0x65, 0x14, - 0x7a, 0xc9, 0x7c, 0xc5, 0xfb, 0xc9, 0xaa, 0x34, 0xef, 0x89, 0x77, 0x60, 0x55, 0x1a, 0x1e, 0x24, - 0xc3, 0x90, 0x4b, 0x61, 0x87, 0x81, 0x86, 0xc2, 0x92, 0x11, 0x2e, 0x18, 0x8f, 0x1d, 0x3f, 0x56, - 0x92, 0xba, 0x4c, 0x8a, 0xf7, 0xa0, 0x12, 0xf8, 0x26, 0x5b, 0x27, 0x24, 0xc7, 0x90, 0x4b, 0xb3, - 0xef, 0x1f, 0x12, 0xd4, 0x28, 0x07, 0xf2, 0x17, 0x56, 0xc5, 0x0b, 0xce, 0xcd, 0x91, 0x15, 0xda, - 0xc4, 0x35, 0xca, 0xc6, 0xaa, 0x17, 0x9c, 0xb7, 0xac, 0xd0, 0x66, 0xcd, 0xe5, 0x5b, 0x7f, 0x3a, - 0x26, 0x4e, 0xb1, 0x66, 0xc8, 0x94, 0xb8, 0x0d, 0x95, 0x91, 0x37, 0x8d, 0x62, 0x27, 0xdc, 0xbe, - 0x64, 0x7b, 0x93, 0x91, 0x02, 0xb0, 0x5e, 0x93, 0xd0, 0x1d, 0x5b, 0xe1, 0x25, 0xb1, 0x85, 0xb2, - 0xa1, 0x92, 0x24, 0x3e, 0x9e, 0xb9, 0xf6, 0x05, 0x1b, 0x9d, 0x0c, 0x4e, 0x20, 0xfd, 0x29, 0x99, - 0x04, 0x23, 0x5a, 0xfb, 0x65, 0x43, 0x25, 0x69, 0x1c, 0xe8, 0x27, 0xad, 0xf6, 0x8a, 0x21, 0x53, - 0x39, 0xb5, 0x7b, 0xe3, 0x95, 0x6a, 0xb7, 0x98, 0xd5, 0x7c, 0x82, 0xd0, 0x3d, 0x71, 0xa5, 0xde, - 0x72, 0x95, 0x35, 0x1f, 0x06, 0x11, 0xc1, 0xe7, 0xb0, 0x76, 0xe2, 0xf8, 0x4e, 0x68, 0xc5, 0x8e, - 0x8d, 0x22, 0x02, 0x99, 0x89, 0xaa, 0x6a, 0x98, 0x9f, 0x2a, 0x14, 0xf2, 0xd1, 0xda, 0x49, 0x26, - 0x85, 0xb5, 0x94, 0xb2, 0xef, 0x35, 0x9e, 0x2d, 0x9c, 0x42, 0xa1, 0x5a, 0x7e, 0x31, 0xa9, 0xec, - 0x75, 0x16, 0xaa, 0x19, 0x3c, 0xe4, 0x2a, 0xeb, 0xdf, 0xc2, 0xaa, 0x1c, 0x5b, 0x14, 0x68, 0x91, - 0x93, 0xe4, 0xf7, 0x3c, 0x16, 0x68, 0x11, 0x8e, 0xeb, 0x56, 0x16, 0xc9, 0x2b, 0x55, 0xce, 0xda, - 0x1a, 0x03, 0xd9, 0xb0, 0x83, 0x7a, 0x07, 0xce, 0x2b, 0xd3, 0x3a, 0x72, 0x3d, 0xe4, 0x7d, 0x45, - 0xa9, 0x4f, 0x4d, 0x3d, 0xaf, 0xc9, 0x20, 0xbd, 0x0f, 0x65, 0x35, 0x13, 0xfe, 0x52, 0xbe, 0xa9, - 0x4f, 0xa0, 0x96, 0xed, 0xa1, 0xbf, 0x9c, 0x86, 0xb0, 0x5e, 0x11, 0xc5, 0x41, 0x98, 0xb0, 0xb1, - 0xb2, 0x1b, 0x0d, 0x28, 0xad, 0xff, 0xf1, 0x12, 0x54, 0x49, 0xbf, 0xe9, 0x93, 0xf6, 0x26, 0xde, - 0x07, 0x31, 0x0a, 0x1d, 0x2b, 0x76, 0x4c, 0xe7, 0x22, 0x0e, 0x2d, 0xa9, 0xc5, 0xb0, 0x28, 0xaa, - 0x31, 0xa6, 0x8d, 0x08, 0x56, 0x64, 0xee, 0x42, 0x75, 0x62, 0x85, 0x91, 0xd2, 0xa0, 0xf9, 0xeb, - 0xc0, 0x20, 0xa9, 0xbf, 0x6a, 0xfe, 0x09, 0xca, 0xac, 0x71, 0x70, 0xe6, 0xf8, 0x6c, 0x3b, 0x60, - 0xab, 0x49, 0x9d, 0xe0, 0x43, 0x04, 0x0f, 0xdc, 0xef, 0x50, 0xda, 0x01, 0x14, 0x84, 0x64, 0x67, - 0x33, 0x6f, 0xb8, 0xcd, 0x0d, 0xce, 0xd4, 0xef, 0xe1, 0xf3, 0x84, 0xc6, 0xc8, 0xd0, 0xeb, 0xbf, - 0x06, 0x48, 0x31, 0xe2, 0x16, 0x5c, 0x7f, 0xde, 0x19, 0x74, 0xb6, 0x3b, 0xdd, 0xce, 0xf0, 0x6b, - 0xf3, 0xb0, 0x37, 0x38, 0x68, 0xb7, 0x3a, 0xbb, 0x9d, 0xf6, 0x8e, 0x76, 0x45, 0x5c, 0x07, 0x91, - 0xc1, 0xd1, 0xcf, 0x6e, 0x5b, 0x2b, 0x88, 0x06, 0x6c, 0x66, 0xe0, 0x9d, 0x9e, 0xc2, 0x2c, 0xe9, - 0xff, 0x4b, 0x01, 0xd6, 0x0e, 0x78, 0xe9, 0x3d, 0x73, 0x2e, 0x77, 0xd8, 0x88, 0x36, 0x52, 0x6c, - 0xb3, 0x64, 0xd0, 0x6f, 0x71, 0x07, 0xaa, 0x93, 0x33, 0xe7, 0xd2, 0xcc, 0x19, 0x9c, 0x2a, 0x08, - 0x6a, 0x11, 0x83, 0x7c, 0x17, 0x56, 0x02, 0x6a, 0x82, 0x14, 0xa2, 0x36, 0xe6, 0xda, 0x66, 0x48, - 0x02, 0xd4, 0x44, 0x93, 0xa2, 0xb2, 0x2a, 0xaf, 0x2c, 0x8c, 0x3a, 0x76, 0x13, 0x96, 0x11, 0x85, - 0xd2, 0x37, 0xa9, 0x90, 0x94, 0x10, 0x1f, 0xc1, 0xda, 0x28, 0x18, 0x4f, 0x4c, 0x95, 0x5d, 0x8a, - 0x53, 0x79, 0xc6, 0x5e, 0x45, 0x92, 0x03, 0x2e, 0x4b, 0xff, 0xd3, 0x22, 0x94, 0xa9, 0x0e, 0x92, - 0xb7, 0xbb, 0xf6, 0x85, 0xe2, 0xed, 0x15, 0x63, 0xd9, 0xb5, 0x51, 0x2c, 0xf8, 0x01, 0xad, 0x37, - 0xd1, 0x66, 0x8b, 0x59, 0x6d, 0x36, 0x5d, 0xce, 0xa5, 0xdc, 0x72, 0x5e, 0xa4, 0xc8, 0x2e, 0x2f, - 0x52, 0x64, 0x71, 0x72, 0x31, 0x8d, 0x73, 0xe1, 0x26, 0xfa, 0x02, 0x10, 0xa8, 0x8d, 0x90, 0x2c, - 0xe7, 0x5e, 0xcd, 0x73, 0xee, 0x06, 0xac, 0xd2, 0xe4, 0xf0, 0xd8, 0xfa, 0x52, 0x36, 0x54, 0x32, - 0x33, 0x0c, 0x95, 0x1f, 0x1a, 0x86, 0xa4, 0xd9, 0x96, 0x77, 0xc2, 0xd6, 0x17, 0xd5, 0xec, 0xa6, - 0x77, 0x12, 0x88, 0x8f, 0xe1, 0x5a, 0x8a, 0x96, 0xad, 0x21, 0xe5, 0x97, 0xce, 0x13, 0x0c, 0x91, - 0x50, 0x52, 0x8b, 0x48, 0xcd, 0x7d, 0x00, 0x1b, 0x99, 0x2c, 0xa4, 0xbb, 0x45, 0xc4, 0xf8, 0x2b, - 0xc6, 0x7a, 0x42, 0x4e, 0x62, 0x75, 0x24, 0xde, 0xc5, 0x7e, 0x1a, 0x79, 0x53, 0x9b, 0xd9, 0xe8, - 0x74, 0xec, 0x47, 0x8d, 0x35, 0xea, 0xe0, 0x75, 0x05, 0x6f, 0x31, 0xf8, 0xcb, 0x52, 0xb9, 0xae, - 0xad, 0x1b, 0xf5, 0x74, 0x39, 0x98, 0x91, 0x13, 0xeb, 0x7f, 0xb8, 0x0c, 0x6b, 0xbb, 0x41, 0xe8, - 0xb8, 0x27, 0x7e, 0x3a, 0x6d, 0xe7, 0xac, 0x32, 0x6a, 0x2a, 0x2f, 0x65, 0xa6, 0xf2, 0x5d, 0xa8, - 0x1e, 0x73, 0x46, 0x64, 0xb9, 0x34, 0x5f, 0x4b, 0x06, 0x48, 0xd0, 0xf0, 0xc8, 0x43, 0xd6, 0xa8, - 0x08, 0x28, 0x73, 0x89, 0x32, 0xab, 0x4c, 0x28, 0x31, 0x88, 0x9f, 0xd1, 0xde, 0x69, 0x3b, 0x9e, - 0x13, 0xf3, 0xf8, 0xd6, 0x95, 0x3c, 0x98, 0xab, 0xd3, 0x43, 0xc3, 0x39, 0x6e, 0x92, 0x00, 0x8f, - 0x5b, 0xe9, 0x0e, 0x91, 0xcb, 0xbc, 0x72, 0xdf, 0x5d, 0xf9, 0x91, 0x79, 0x25, 0x1b, 0x7e, 0x04, - 0xd7, 0x42, 0xe7, 0xd8, 0x09, 0x1d, 0x7f, 0xe4, 0xd8, 0x66, 0x66, 0xda, 0xf2, 0x0c, 0xb9, 0x9a, - 0x22, 0x3b, 0xc9, 0x04, 0xde, 0x07, 0x2d, 0xa9, 0xab, 0xc9, 0xac, 0x93, 0xa6, 0x4d, 0xfd, 0xd1, - 0x9b, 0xdf, 0xfb, 0xd9, 0x3e, 0x91, 0x1a, 0x75, 0x55, 0x71, 0x4e, 0xcb, 0xe2, 0xb8, 0xfa, 0xaa, - 0xb8, 0xca, 0x4f, 0x2a, 0x8e, 0xdb, 0xc2, 0x69, 0x7d, 0x08, 0x95, 0x84, 0x44, 0xd4, 0xa0, 0x6c, - 0xb4, 0xa5, 0xe5, 0xe2, 0x8a, 0xa8, 0xc2, 0x6a, 0xab, 0x39, 0x68, 0x35, 0x77, 0x90, 0x81, 0xd5, - 0xa0, 0x3c, 0x68, 0x0f, 0xd9, 0x5a, 0xb1, 0x24, 0xd6, 0xa1, 0x8a, 0xa9, 0x9d, 0xf6, 0x6e, 0xf3, - 0xb0, 0x3b, 0xd4, 0x8a, 0x62, 0x0d, 0x2a, 0xbd, 0xbe, 0xd9, 0x6c, 0x0d, 0x3b, 0xfd, 0x9e, 0x56, - 0xd2, 0x3d, 0x58, 0x9f, 0xf9, 0x30, 0x72, 0x4d, 0x46, 0x9b, 0x7d, 0xa3, 0xf3, 0xb4, 0xd3, 0x33, - 0xdb, 0x5f, 0x1d, 0x74, 0x3b, 0xad, 0x0e, 0x7e, 0xe9, 0x26, 0x5c, 0xcb, 0xe3, 0x54, 0xc1, 0x05, - 0xa1, 0xc3, 0x9d, 0x3c, 0xaa, 0xdb, 0x7e, 0xda, 0x6c, 0x7d, 0x6d, 0x36, 0xf7, 0xb7, 0x3b, 0x4f, - 0x0f, 0xfb, 0x87, 0x03, 0x6d, 0x49, 0x37, 0xa1, 0xdc, 0x3a, 0x75, 0x46, 0x67, 0xaf, 0x9a, 0x85, - 0x64, 0x7c, 0x76, 0x46, 0x67, 0x52, 0x03, 0x9d, 0x31, 0x3e, 0x3b, 0xa3, 0x33, 0x5c, 0x8c, 0x6a, - 0xa7, 0xfb, 0xd6, 0x93, 0x56, 0xb5, 0x8a, 0xdc, 0xe6, 0xbe, 0xf5, 0xf4, 0x36, 0x54, 0x0e, 0xac, - 0x30, 0x76, 0xa9, 0x93, 0x9e, 0xc0, 0x5a, 0x92, 0xd8, 0x71, 0x8e, 0x95, 0x78, 0x2b, 0x12, 0xb5, - 0x35, 0x41, 0x19, 0x79, 0x42, 0xfd, 0x7d, 0xa8, 0x65, 0x01, 0xe2, 0x36, 0x14, 0x6d, 0xe7, 0x78, - 0xc1, 0xf6, 0x8b, 0x60, 0xfd, 0x39, 0xd4, 0x5a, 0x4a, 0x5c, 0x7b, 0x55, 0xcb, 0x1e, 0x41, 0x9d, - 0x38, 0xf2, 0xe8, 0x48, 0xb1, 0xe4, 0xa5, 0x05, 0x2c, 0xb9, 0x86, 0x34, 0xad, 0x23, 0xc9, 0x93, - 0x3f, 0x85, 0xea, 0x41, 0x18, 0x4c, 0x9c, 0x30, 0xa6, 0x62, 0x35, 0x28, 0x9e, 0x39, 0x97, 0xb2, - 0x54, 0xfc, 0x99, 0x1e, 0x19, 0x2c, 0x65, 0x8f, 0x0c, 0x1e, 0x41, 0x59, 0x65, 0xfb, 0xd1, 0x79, - 0x7e, 0x81, 0x5b, 0x1b, 0xe5, 0x71, 0x9d, 0x08, 0x3f, 0xf6, 0x10, 0x60, 0x92, 0x00, 0x64, 0xc7, - 0x29, 0x7d, 0x5f, 0x16, 0x6e, 0x64, 0x28, 0xf4, 0xd7, 0x61, 0xf5, 0xb9, 0xeb, 0x9c, 0xcb, 0xe6, - 0xbf, 0x74, 0x9d, 0x73, 0xd5, 0x7c, 0xfc, 0xad, 0xff, 0x57, 0x00, 0x65, 0xe2, 0x7f, 0x3b, 0xaf, - 0x3e, 0xa5, 0xf9, 0x29, 0xaa, 0xc3, 0x96, 0x64, 0x57, 0xa5, 0x05, 0x0a, 0x0b, 0x33, 0xaf, 0xd7, - 0x01, 0x32, 0xbc, 0x98, 0x77, 0x96, 0x4a, 0x9c, 0xb0, 0x60, 0x94, 0xb9, 0x49, 0x8a, 0xc1, 0x69, - 0xc4, 0x06, 0xd4, 0x14, 0x20, 0x1e, 0xb2, 0x44, 0x4c, 0x26, 0x53, 0xd6, 0x1a, 0xae, 0x2a, 0xad, - 0xfe, 0xc8, 0x73, 0x94, 0xad, 0x81, 0xc4, 0x64, 0x4c, 0xd0, 0x3e, 0xe3, 0x84, 0x11, 0x6e, 0x27, - 0xf2, 0x00, 0x5f, 0x26, 0xc5, 0x3b, 0x50, 0xc2, 0x4d, 0x58, 0xda, 0x06, 0xae, 0xaa, 0x1e, 0xcc, - 0x48, 0x11, 0x06, 0x11, 0x88, 0xfb, 0xb0, 0x4a, 0x5c, 0xca, 0xc1, 0x9d, 0x20, 0xd3, 0xdb, 0x6a, - 0x53, 0x36, 0x14, 0x5a, 0xbc, 0x0b, 0xcb, 0xc7, 0x67, 0xce, 0x25, 0x6f, 0x03, 0x49, 0x99, 0x39, - 0x66, 0x62, 0x30, 0x85, 0xb8, 0x07, 0xf5, 0xd0, 0x39, 0x36, 0xe9, 0xdc, 0x06, 0x79, 0x78, 0xd4, - 0xa8, 0x13, 0x8b, 0xae, 0x85, 0xce, 0x71, 0x0b, 0x81, 0xc3, 0x23, 0x2f, 0x12, 0x6f, 0xc3, 0x0a, - 0x2d, 0x2e, 0x54, 0x18, 0x32, 0x5f, 0x56, 0x2b, 0xd5, 0x90, 0x58, 0xf1, 0x31, 0x80, 0x54, 0x4b, - 0xcc, 0xa3, 0x4b, 0x12, 0xbe, 0x93, 0xc5, 0x94, 0x9d, 0xff, 0x59, 0xe5, 0xe5, 0x1d, 0x58, 0xc6, - 0x49, 0x12, 0x35, 0x6e, 0x50, 0xc9, 0x1b, 0xf9, 0x19, 0x44, 0x35, 0x25, 0xbc, 0xb8, 0x0f, 0x65, - 0x9c, 0x28, 0xb4, 0xaa, 0x1b, 0x59, 0x3d, 0x4d, 0xce, 0x2a, 0xdc, 0xb9, 0x9d, 0xf3, 0xc1, 0xb7, - 0x9e, 0x78, 0x00, 0x25, 0x1b, 0x17, 0xf3, 0x4d, 0x2a, 0xf1, 0x7a, 0x66, 0x5c, 0x90, 0x8b, 0xee, - 0x38, 0xc7, 0xa4, 0x3a, 0x12, 0x8d, 0xd8, 0x83, 0x3a, 0x4e, 0xa3, 0x47, 0x24, 0x8c, 0x61, 0xf7, - 0x35, 0x6e, 0x51, 0xae, 0x37, 0x66, 0x72, 0xf5, 0x24, 0x11, 0x75, 0x76, 0xdb, 0x8f, 0xc3, 0x4b, - 0x63, 0xcd, 0xcf, 0xc2, 0xc4, 0x2d, 0x28, 0xbb, 0x51, 0x37, 0x18, 0x9d, 0x25, 0x47, 0xc4, 0x49, - 0x5a, 0x7c, 0x01, 0x6b, 0x34, 0xb1, 0x30, 0x89, 0x1f, 0x97, 0xe7, 0xc3, 0xd9, 0x29, 0xa3, 0x50, - 0x46, 0x9e, 0x12, 0x77, 0x50, 0x37, 0x32, 0x63, 0x67, 0x3c, 0x09, 0x42, 0xd4, 0xf0, 0x5e, 0x57, - 0x67, 0x0d, 0x43, 0x05, 0x42, 0x41, 0x29, 0xf1, 0x4d, 0x31, 0x83, 0xe3, 0xe3, 0xc8, 0x89, 0xe9, - 0x3c, 0xb8, 0x64, 0xd4, 0x95, 0x8b, 0x4a, 0x9f, 0xa0, 0x24, 0xa8, 0x44, 0xa6, 0x7d, 0xe9, 0x5b, - 0x63, 0x77, 0xd4, 0xb8, 0xcb, 0x8a, 0xa4, 0x1b, 0xed, 0x30, 0x20, 0xab, 0xcb, 0x6d, 0xe5, 0x74, - 0xb9, 0xab, 0xb0, 0x6c, 0x1f, 0xe1, 0x72, 0x7c, 0x83, 0x8a, 0x2d, 0xd9, 0x47, 0x1d, 0x5b, 0x7c, - 0x40, 0x56, 0x66, 0x66, 0x81, 0x0d, 0x3d, 0x6b, 0x8d, 0x4b, 0x38, 0xa3, 0x91, 0x52, 0x88, 0x2d, - 0xa8, 0xee, 0x3a, 0x56, 0x3c, 0x0d, 0x9d, 0x5d, 0xcf, 0x3a, 0x69, 0xbc, 0x49, 0x25, 0x65, 0x41, - 0x58, 0x3b, 0x2f, 0x38, 0x71, 0x47, 0x16, 0xad, 0xfc, 0x7b, 0x2c, 0x17, 0x4b, 0x48, 0xc7, 0x4e, - 0x55, 0x18, 0x4b, 0x0a, 0xbb, 0x6f, 0x65, 0x55, 0x18, 0xcb, 0x53, 0x07, 0x2b, 0x69, 0x5f, 0x38, - 0x93, 0x60, 0x74, 0xda, 0x78, 0x9b, 0xd6, 0xdb, 0x9a, 0xea, 0x8a, 0x36, 0x02, 0xc5, 0x3b, 0xb0, - 0x2e, 0xd5, 0x7a, 0x53, 0x39, 0xd6, 0xbc, 0x43, 0x74, 0x75, 0x09, 0x6e, 0x49, 0xff, 0x1a, 0x1d, - 0xd6, 0xb8, 0x40, 0xdb, 0x1c, 0x59, 0xa3, 0x53, 0xa7, 0x71, 0x9f, 0x2b, 0x4e, 0xc5, 0xd9, 0x2d, - 0x04, 0xdd, 0x7a, 0x4a, 0x0a, 0x25, 0x0d, 0xd7, 0xa7, 0x33, 0x5c, 0x31, 0xb7, 0xa6, 0x33, 0xec, - 0x73, 0xef, 0x4a, 0x96, 0x39, 0x6e, 0x2f, 0xd3, 0xf6, 0x71, 0xeb, 0x97, 0x20, 0xe6, 0x27, 0xda, - 0x0f, 0xb1, 0xe8, 0x65, 0xc9, 0xa2, 0x7f, 0xb6, 0xf4, 0xa4, 0xa0, 0xff, 0x8f, 0x05, 0x58, 0xcb, - 0xb1, 0xa0, 0x85, 0x7b, 0x0d, 0x0b, 0xe2, 0xd6, 0x58, 0x1a, 0xb2, 0x38, 0xa1, 0xd4, 0x3f, 0xd7, - 0x3f, 0xf1, 0x9c, 0x8c, 0xfa, 0x47, 0x69, 0xf1, 0x0b, 0xb8, 0x7a, 0x3c, 0xf5, 0xbc, 0xd8, 0xb9, - 0x88, 0x95, 0x59, 0x3f, 0x74, 0x8e, 0xa5, 0x1d, 0x77, 0xee, 0xb8, 0x68, 0x43, 0xd1, 0xb2, 0x69, - 0xcb, 0x70, 0x8e, 0xc5, 0xef, 0x82, 0x48, 0x0a, 0x60, 0x69, 0x0b, 0xf3, 0x2f, 0x2f, 0xce, 0xaf, - 0x29, 0x52, 0xea, 0x06, 0xc3, 0x39, 0xd6, 0xff, 0xbb, 0x22, 0xd4, 0xf6, 0xac, 0xe8, 0x74, 0xdf, - 0x9a, 0x0c, 0x62, 0x2b, 0x8e, 0x70, 0x61, 0x9c, 0x5a, 0xd1, 0xe9, 0xd8, 0x9a, 0xb0, 0xb2, 0x58, - 0x60, 0x8b, 0xa3, 0x84, 0x91, 0xa6, 0x78, 0x0b, 0xca, 0x98, 0xec, 0xfb, 0x07, 0xcf, 0xa4, 0xf9, - 0x2f, 0x49, 0x23, 0x43, 0x8e, 0x4e, 0xa7, 0xc7, 0xc7, 0x49, 0x53, 0x55, 0x52, 0xdc, 0x83, 0x35, - 0xf9, 0x93, 0xf4, 0xb1, 0x0b, 0x79, 0xda, 0x91, 0x07, 0x8a, 0xc7, 0x50, 0x95, 0x80, 0xa1, 0xda, - 0x3e, 0xea, 0x89, 0x99, 0x38, 0x45, 0x18, 0x59, 0x2a, 0xf1, 0x2b, 0xb8, 0x96, 0x49, 0xee, 0x06, - 0xe1, 0xfe, 0xd4, 0x8b, 0xdd, 0x56, 0x4f, 0xca, 0xae, 0xaf, 0xcd, 0x65, 0x4f, 0x49, 0x8c, 0xc5, - 0x39, 0xf3, 0xb5, 0xdd, 0x77, 0x7d, 0xda, 0x8d, 0x8a, 0x46, 0x1e, 0x38, 0x43, 0x65, 0x5d, 0xd0, - 0x26, 0x94, 0xa7, 0xb2, 0x2e, 0x90, 0x4d, 0x49, 0xc0, 0xbe, 0x13, 0x9f, 0x06, 0xb6, 0x14, 0x46, - 0xaf, 0xe6, 0xaa, 0xc5, 0x28, 0x23, 0x4f, 0x89, 0xdd, 0xe9, 0x4f, 0x3d, 0x6f, 0xe4, 0xc7, 0xa4, - 0xff, 0x14, 0x0d, 0x95, 0xc4, 0x0d, 0x3a, 0xb4, 0xfc, 0x13, 0x27, 0x6a, 0x54, 0xb7, 0x8a, 0xf7, - 0x0b, 0x86, 0x4c, 0xe9, 0x7f, 0x67, 0x09, 0x96, 0x79, 0x24, 0x5f, 0x83, 0xca, 0x11, 0x9d, 0x46, - 0xfb, 0xd3, 0xb1, 0x3a, 0x35, 0x26, 0x40, 0x6f, 0x3a, 0x66, 0xb5, 0x43, 0x9a, 0x6f, 0x0b, 0x06, - 0xfd, 0xc6, 0x22, 0x83, 0x69, 0x8c, 0xdf, 0x2a, 0x12, 0x54, 0xa6, 0xb0, 0x12, 0x61, 0x70, 0x4e, - 0xb3, 0xa1, 0x44, 0x08, 0x95, 0xa4, 0x83, 0x69, 0xda, 0xeb, 0x31, 0xd3, 0x32, 0xe1, 0xca, 0x04, - 0x68, 0xf9, 0xf1, 0xac, 0xe9, 0x7a, 0x65, 0xde, 0x74, 0x7d, 0x07, 0x50, 0xa9, 0x19, 0x39, 0x7d, - 0xdf, 0x69, 0xf5, 0xe4, 0xb9, 0x52, 0x06, 0x82, 0x2b, 0xd4, 0x0e, 0x26, 0xf2, 0xc0, 0x08, 0x7f, - 0x8a, 0xcf, 0x92, 0xd9, 0x49, 0x6d, 0x94, 0x3a, 0xa4, 0xdc, 0x0b, 0xb3, 0xf3, 0xd8, 0xc8, 0xd1, - 0x61, 0x49, 0xb8, 0xc1, 0xb1, 0x0e, 0x89, 0x3f, 0xf5, 0x36, 0x80, 0x11, 0x9c, 0x47, 0x4e, 0x4c, - 0x67, 0x34, 0x37, 0xa8, 0x89, 0x39, 0x1f, 0x94, 0xe0, 0xfc, 0x20, 0x88, 0x12, 0x03, 0xd0, 0xd2, - 0x62, 0x03, 0x90, 0xfe, 0x21, 0xac, 0xa2, 0xf4, 0x63, 0xc5, 0x96, 0xb8, 0x27, 0xad, 0xd8, 0x2c, - 0xb3, 0xc9, 0xf3, 0x81, 0xf4, 0x1b, 0xd2, 0x18, 0xde, 0x55, 0xdf, 0xa5, 0x3c, 0x6f, 0x64, 0x0c, - 0x19, 0xc9, 0xce, 0x2b, 0x0b, 0x94, 0xf2, 0xd4, 0x6b, 0x50, 0xc1, 0xaa, 0xd1, 0x61, 0xbb, 0x3a, - 0x75, 0x0c, 0x83, 0xf3, 0x16, 0xa6, 0xf5, 0x7f, 0x5a, 0x80, 0x6a, 0x3f, 0xb4, 0x71, 0xcb, 0x1f, - 0x4c, 0x9c, 0xd1, 0x0f, 0xda, 0xab, 0x50, 0xfa, 0x0a, 0x3c, 0xcf, 0xa2, 0xcd, 0x45, 0x1a, 0x12, - 0x12, 0x80, 0xf8, 0x18, 0x4a, 0xc7, 0xb8, 0x89, 0x14, 0xb3, 0x2a, 0x5f, 0xa6, 0x78, 0xf5, 0x1b, - 0xb7, 0x15, 0x83, 0x48, 0xf5, 0xdf, 0x4b, 0xbe, 0x4f, 0x7b, 0x4d, 0xf6, 0xf8, 0xf7, 0x0a, 0x39, - 0x92, 0x0c, 0x5a, 0x5a, 0x41, 0x94, 0xa1, 0xb4, 0xd3, 0x1e, 0xb4, 0x58, 0x2d, 0x42, 0x05, 0x69, - 0x60, 0xee, 0x76, 0x8c, 0xc1, 0x50, 0x2b, 0x91, 0x67, 0x0a, 0x01, 0xba, 0xcd, 0xc1, 0x50, 0x2b, - 0x0b, 0x80, 0x95, 0xc3, 0x5e, 0xe7, 0x57, 0x87, 0x6d, 0x4d, 0xd3, 0xff, 0x49, 0x01, 0x20, 0x3d, - 0x3f, 0x12, 0xef, 0x41, 0xf5, 0x9c, 0x52, 0x66, 0xe6, 0x48, 0x3d, 0xdb, 0x46, 0x60, 0x34, 0x49, - 0x86, 0x1f, 0x40, 0x2d, 0xd9, 0x24, 0x51, 0x6a, 0x9a, 0x3f, 0x5b, 0xaf, 0x26, 0xf8, 0xed, 0x4b, - 0xf1, 0x3e, 0x94, 0x03, 0x6c, 0x07, 0x92, 0x16, 0xb3, 0x22, 0x53, 0xa6, 0xf9, 0xc6, 0x6a, 0xc0, - 0x09, 0x94, 0xae, 0x8e, 0x43, 0x65, 0x18, 0x4a, 0x48, 0x77, 0x11, 0xd4, 0xf2, 0xac, 0x69, 0xe4, - 0x18, 0x8c, 0x4f, 0x76, 0x89, 0xe5, 0x74, 0x97, 0xd0, 0x7f, 0x0d, 0xf5, 0x81, 0x35, 0x9e, 0xf0, - 0x5e, 0x42, 0x0d, 0x13, 0x50, 0xc2, 0x39, 0x21, 0xa7, 0x1e, 0xfd, 0xc6, 0x45, 0x77, 0xe0, 0x84, - 0x23, 0xc7, 0x57, 0x6b, 0x54, 0x25, 0x91, 0xfd, 0x1e, 0xe2, 0x6e, 0x62, 0x04, 0xe7, 0x6a, 0x3b, - 0x51, 0x69, 0xfd, 0xdf, 0x2b, 0x40, 0x35, 0x53, 0x0d, 0xf1, 0x21, 0x94, 0x48, 0x0c, 0x2f, 0x64, - 0x19, 0x61, 0x86, 0x80, 0x7f, 0xb3, 0xe0, 0x86, 0x84, 0xe2, 0x6d, 0x58, 0x8e, 0x62, 0x2b, 0x54, - 0x47, 0x91, 0x5a, 0x26, 0xc7, 0x76, 0x30, 0xf5, 0x6d, 0x83, 0xd1, 0x42, 0x87, 0xa2, 0xe3, 0xdb, - 0xd2, 0x94, 0x36, 0x4f, 0x85, 0x48, 0x7d, 0x0b, 0x2a, 0x49, 0xf1, 0x38, 0x05, 0x8c, 0xfe, 0x8b, - 0x81, 0x76, 0x45, 0x54, 0x60, 0xd9, 0x68, 0xf6, 0x9e, 0xb6, 0xb5, 0x82, 0xfe, 0xf7, 0x0a, 0x00, - 0x69, 0x2e, 0xf1, 0x30, 0x57, 0xdb, 0x5b, 0xb3, 0xa5, 0x3e, 0xa4, 0xbf, 0x99, 0xca, 0xde, 0x86, - 0xca, 0xd4, 0x27, 0xa0, 0x63, 0xcb, 0x9d, 0x28, 0x05, 0xa0, 0xee, 0xa8, 0xbc, 0x64, 0x67, 0x74, - 0xc7, 0x97, 0x96, 0xa7, 0xff, 0x0c, 0x2a, 0x49, 0x71, 0xa8, 0x9b, 0xef, 0xf6, 0xbb, 0xdd, 0xfe, - 0x8b, 0x4e, 0xef, 0xa9, 0x76, 0x05, 0x93, 0x07, 0x46, 0xbb, 0xd5, 0xde, 0xc1, 0x64, 0x01, 0xe7, - 0x6c, 0xeb, 0xd0, 0x30, 0xda, 0xbd, 0xa1, 0x69, 0xf4, 0x5f, 0x68, 0x4b, 0xfa, 0x1f, 0x14, 0x60, - 0xad, 0xef, 0xd9, 0xad, 0xc0, 0x6b, 0x59, 0x13, 0x94, 0xb3, 0xc4, 0x2f, 0x60, 0xe3, 0x68, 0x8a, - 0xb2, 0xfe, 0xc4, 0xb3, 0x46, 0xce, 0x69, 0xe0, 0xd9, 0x8e, 0x5a, 0x84, 0xb9, 0xc3, 0x56, 0x79, - 0x76, 0xa2, 0x11, 0xf1, 0x41, 0x4a, 0x2b, 0x3e, 0x85, 0xda, 0x24, 0x0c, 0x8e, 0x1c, 0x75, 0x90, - 0xb5, 0xf4, 0xca, 0xbc, 0x55, 0xa2, 0x93, 0x87, 0xcc, 0xff, 0xf5, 0x32, 0xd4, 0x76, 0x1c, 0x7b, - 0x3a, 0xf9, 0x32, 0x70, 0xfd, 0x56, 0x7c, 0x21, 0x3e, 0x81, 0x5a, 0xe0, 0x91, 0xc1, 0xca, 0xcc, - 0x38, 0xc0, 0x2d, 0x2a, 0x07, 0x02, 0x6a, 0x01, 0xb9, 0xcb, 0x7d, 0x00, 0x57, 0xa5, 0xb9, 0x84, - 0xad, 0xa7, 0x17, 0x9c, 0x19, 0xd7, 0xcc, 0xb2, 0xa1, 0x31, 0x8a, 0x37, 0x68, 0x22, 0xff, 0x1d, - 0xd8, 0xcc, 0x90, 0x23, 0x63, 0x61, 0xfa, 0xe2, 0xdc, 0x1a, 0xdb, 0x48, 0xf2, 0x26, 0xae, 0x79, - 0x5f, 0xc2, 0xa6, 0xaa, 0xe1, 0x88, 0x7b, 0x8f, 0x33, 0x97, 0xb2, 0x4a, 0x55, 0xae, 0x77, 0x65, - 0x85, 0x37, 0x82, 0x2c, 0x90, 0xca, 0xfa, 0x18, 0xae, 0xd9, 0xd8, 0x7a, 0x93, 0x3b, 0xff, 0xcc, - 0x71, 0x26, 0xa6, 0x97, 0xf1, 0x5b, 0x21, 0xe4, 0x36, 0xe2, 0x9e, 0x39, 0xce, 0xa4, 0x6b, 0x45, - 0xb1, 0x78, 0x02, 0x1b, 0xd6, 0xf1, 0xb1, 0x33, 0x8a, 0x1d, 0xdb, 0xc4, 0x6d, 0x6c, 0xa1, 0x95, - 0x16, 0x65, 0xa5, 0x75, 0x45, 0x86, 0xcb, 0xb1, 0x15, 0x78, 0xe2, 0x29, 0xdc, 0x9c, 0x9c, 0x5e, - 0x46, 0x24, 0x48, 0x8f, 0x4e, 0x71, 0xb7, 0xcd, 0x94, 0xb0, 0xba, 0xa0, 0x84, 0xeb, 0x8a, 0xbc, - 0xc5, 0xd4, 0xaa, 0xa0, 0x27, 0x70, 0x53, 0x75, 0x1f, 0xea, 0x77, 0xf9, 0x3e, 0x2f, 0x53, 0x9f, - 0x5f, 0x93, 0xfd, 0x86, 0xf8, 0x4c, 0xc7, 0xdf, 0x07, 0x8d, 0x1d, 0xb1, 0x8e, 0x71, 0xea, 0xd2, - 0xd7, 0xa5, 0x73, 0x7a, 0x9d, 0xe0, 0xbb, 0xb4, 0xf8, 0x90, 0x7d, 0xdc, 0x07, 0xcd, 0x19, 0xbb, - 0xb1, 0x69, 0x91, 0xb4, 0xca, 0x94, 0x7c, 0x2a, 0x56, 0x47, 0xb8, 0x34, 0xdb, 0x21, 0xe5, 0x67, - 0xa0, 0x49, 0xa2, 0x63, 0xd2, 0x01, 0xb0, 0x35, 0xd5, 0x05, 0xad, 0xa9, 0x33, 0xd5, 0x2e, 0x12, - 0x61, 0x2b, 0xf6, 0x41, 0x28, 0x1b, 0x24, 0x59, 0x56, 0x58, 0x91, 0x65, 0x15, 0x5a, 0x3a, 0x1e, - 0xf5, 0x77, 0x9e, 0x1d, 0xa6, 0xea, 0x31, 0x35, 0x46, 0x2d, 0x80, 0xe3, 0x3c, 0x38, 0xd2, 0xff, - 0xcb, 0x15, 0xa8, 0xb0, 0xd9, 0x0d, 0xa7, 0xf1, 0x7d, 0x58, 0x0d, 0x8e, 0xbe, 0x21, 0x51, 0xf6, - 0x15, 0x9e, 0x53, 0x2b, 0xc1, 0xd1, 0x37, 0x28, 0xff, 0xbe, 0xa7, 0x44, 0x10, 0xdb, 0x39, 0x96, - 0xab, 0xa6, 0x9e, 0x57, 0x32, 0xa5, 0x48, 0xb2, 0xe3, 0x1c, 0xa3, 0x74, 0xe9, 0xfa, 0x91, 0x13, - 0xc6, 0x6c, 0x36, 0x5d, 0x7d, 0xf5, 0xe2, 0x60, 0x32, 0xb2, 0xa4, 0x3e, 0x86, 0xaa, 0x34, 0x4d, - 0x52, 0xa6, 0xf2, 0xab, 0x33, 0x31, 0x19, 0x65, 0xfa, 0x02, 0xea, 0xe9, 0xf6, 0x43, 0xf9, 0x2a, - 0xaf, 0xcc, 0xb7, 0x96, 0x50, 0x52, 0xd6, 0x47, 0x70, 0x3d, 0x3a, 0x73, 0x27, 0xa6, 0xac, 0x69, - 0xe0, 0xd3, 0xf1, 0xaa, 0x39, 0x39, 0x93, 0x03, 0x28, 0x10, 0xdb, 0x21, 0x64, 0xdf, 0xef, 0x4d, - 0x3d, 0xef, 0xe0, 0x4c, 0xbc, 0x0b, 0x1b, 0x92, 0x7c, 0x92, 0xcc, 0x27, 0x1a, 0xc5, 0x65, 0xa3, - 0xce, 0x88, 0x03, 0x39, 0x8f, 0xc4, 0xe7, 0xd0, 0xe0, 0x39, 0x24, 0x1b, 0xc5, 0xd3, 0x9c, 0x67, - 0x08, 0x9f, 0x81, 0x5e, 0x23, 0x3c, 0x9b, 0x54, 0x9b, 0x84, 0xa5, 0x89, 0xf2, 0x11, 0x6c, 0xba, - 0x27, 0x7e, 0x10, 0xaa, 0x2c, 0x72, 0xfa, 0xcb, 0xc3, 0x51, 0xc1, 0xb8, 0x66, 0x66, 0xd1, 0x60, - 0x4b, 0xe4, 0xf2, 0xbc, 0x34, 0x63, 0x72, 0xcb, 0xc0, 0x1c, 0xa8, 0x85, 0xd6, 0xb3, 0xeb, 0xf3, - 0x92, 0x5d, 0x36, 0x8c, 0xe0, 0xbc, 0x63, 0xe3, 0x92, 0x96, 0xa4, 0x6a, 0x8d, 0xc4, 0x17, 0xd4, - 0x9a, 0x75, 0x6a, 0x8d, 0x60, 0x64, 0x32, 0x53, 0xb0, 0x45, 0xbf, 0x04, 0x31, 0xb7, 0xa4, 0xa3, - 0x86, 0xf6, 0xca, 0xfe, 0xd6, 0x66, 0x56, 0x36, 0xad, 0x81, 0xb9, 0x15, 0xbd, 0xb1, 0x68, 0x0d, - 0x8c, 0xf2, 0x2b, 0xb9, 0x0d, 0x8d, 0xfc, 0x97, 0xcf, 0x1d, 0xf7, 0xe4, 0x94, 0x66, 0x97, 0xf4, - 0xfb, 0xcf, 0xe7, 0xbf, 0x96, 0xfd, 0xf2, 0x0b, 0xa2, 0xfd, 0x41, 0xce, 0x72, 0xf5, 0xc7, 0x73, - 0x16, 0xfd, 0x3f, 0x28, 0x40, 0x85, 0x67, 0x06, 0x2e, 0xa2, 0x37, 0xa0, 0xf8, 0x3d, 0x0b, 0x08, - 0x71, 0xe2, 0x01, 0x6c, 0x58, 0xb6, 0x3d, 0x33, 0xa0, 0xbc, 0x93, 0xae, 0x5b, 0xb6, 0x9d, 0x1b, - 0xcd, 0xfb, 0xa0, 0xb9, 0x91, 0xa9, 0x0c, 0x51, 0xa9, 0x77, 0x65, 0xd9, 0xa8, 0xbb, 0x91, 0xb4, - 0x43, 0xf1, 0xa9, 0x64, 0x6e, 0x4d, 0x96, 0xbe, 0x7f, 0x4d, 0xea, 0x02, 0xc0, 0x70, 0x68, 0xdb, - 0x6c, 0xc5, 0x17, 0x5f, 0x96, 0xca, 0x05, 0x0d, 0xf4, 0xff, 0xa6, 0x0a, 0xd5, 0xa6, 0x6f, 0x79, - 0x97, 0xdf, 0x39, 0xe4, 0x1a, 0x4a, 0x27, 0x41, 0x93, 0xa9, 0x9c, 0xa5, 0xec, 0x61, 0x51, 0x21, - 0x08, 0xd5, 0xec, 0x2e, 0x54, 0x83, 0x69, 0x9c, 0xe0, 0xd9, 0xe7, 0x02, 0x18, 0x44, 0x04, 0x49, - 0xfe, 0xe4, 0xfc, 0x53, 0xe5, 0x27, 0x85, 0x36, 0xcd, 0x9f, 0x28, 0x39, 0x49, 0x7e, 0x22, 0x78, - 0x13, 0xd6, 0x62, 0x77, 0xec, 0x90, 0xcb, 0xcb, 0x74, 0xec, 0xd8, 0x7c, 0x8d, 0x86, 0x6f, 0x66, - 0xb4, 0x24, 0x0c, 0x4b, 0x19, 0x3b, 0xe3, 0x20, 0xbc, 0xe4, 0x52, 0x56, 0xb8, 0x14, 0x06, 0x51, - 0x29, 0xef, 0x83, 0x38, 0xb7, 0xdc, 0xd8, 0xcc, 0x17, 0xc5, 0x8a, 0xa5, 0x86, 0x98, 0x61, 0xb6, - 0xb8, 0xeb, 0xb0, 0x62, 0xbb, 0xd1, 0x59, 0xa7, 0x2f, 0x95, 0x4a, 0x99, 0xc2, 0xb6, 0x44, 0x23, - 0x0b, 0x65, 0xda, 0xd8, 0x61, 0xee, 0x5f, 0x34, 0x2a, 0x08, 0xd9, 0x46, 0x00, 0xca, 0x44, 0xbe, - 0x13, 0x9f, 0x07, 0x21, 0xe6, 0x64, 0x9d, 0x31, 0x05, 0xa0, 0xec, 0x88, 0xa4, 0xf8, 0x21, 0x62, - 0x0f, 0x45, 0x23, 0x49, 0xa3, 0x36, 0xc6, 0xac, 0x82, 0xb0, 0x35, 0xae, 0x7e, 0x0a, 0x11, 0xf7, - 0xa0, 0x4e, 0xd5, 0x27, 0x9d, 0x12, 0xdb, 0x40, 0x2b, 0xbf, 0x68, 0xd4, 0x10, 0x4a, 0x86, 0x35, - 0xa4, 0xfa, 0x02, 0x6e, 0xe6, 0xda, 0x67, 0x5a, 0x61, 0x68, 0x5d, 0x9a, 0x63, 0xeb, 0x9b, 0x20, - 0x24, 0x23, 0x68, 0xd1, 0xb8, 0x9e, 0xed, 0xb6, 0x26, 0xa2, 0xf7, 0x11, 0xfb, 0xca, 0xac, 0xae, - 0x1f, 0x84, 0x64, 0x21, 0x5d, 0x98, 0x15, 0xb1, 0x64, 0xce, 0xa3, 0x01, 0x26, 0x05, 0x37, 0xe2, - 0x1b, 0x3d, 0x46, 0x95, 0x60, 0xdb, 0x04, 0x42, 0x15, 0x2f, 0x7a, 0xcc, 0x7b, 0xec, 0x86, 0xf4, - 0x4b, 0x7f, 0x4c, 0x9b, 0x2a, 0x23, 0x4e, 0x1d, 0xcb, 0xa6, 0x35, 0x4b, 0x88, 0x3d, 0xc7, 0x22, - 0x27, 0xad, 0xe8, 0xb1, 0x39, 0x99, 0xc6, 0x7c, 0x15, 0xc7, 0x58, 0x8e, 0x1e, 0x1f, 0x4c, 0x63, - 0x09, 0x3e, 0x71, 0x62, 0xf2, 0xac, 0x20, 0xf0, 0x53, 0xbe, 0x31, 0x16, 0x3d, 0x56, 0x07, 0x6e, - 0xd7, 0x64, 0xdf, 0x3e, 0x96, 0x27, 0x6a, 0x3a, 0xac, 0x25, 0x48, 0x73, 0x3c, 0xe5, 0xbb, 0x37, - 0x45, 0xa3, 0xaa, 0x08, 0xf6, 0xa7, 0x1e, 0x0e, 0x2c, 0x99, 0xc2, 0xcc, 0x10, 0xab, 0x72, 0x83, - 0x87, 0x8e, 0x20, 0x06, 0xd6, 0xe6, 0x35, 0xe0, 0x84, 0x79, 0xea, 0xc6, 0x64, 0xa9, 0x2d, 0x1a, - 0x65, 0x02, 0xec, 0xb9, 0x31, 0xae, 0x63, 0x46, 0xca, 0x19, 0x48, 0x45, 0xdc, 0x24, 0xa2, 0x75, - 0x42, 0xec, 0x13, 0x9c, 0x0a, 0x42, 0x21, 0x22, 0x4b, 0x8b, 0xe5, 0xdd, 0x22, 0xd2, 0x7a, 0x86, - 0x14, 0x4b, 0x7d, 0x1b, 0x38, 0xb3, 0x89, 0x53, 0x8f, 0xcb, 0x7c, 0x8d, 0x0d, 0x1c, 0x04, 0xde, - 0x71, 0xa3, 0x33, 0x2a, 0xf1, 0x1e, 0xd4, 0x33, 0x74, 0x58, 0xde, 0x6d, 0x9e, 0x19, 0x09, 0x59, - 0xae, 0x8e, 0xa1, 0x33, 0x0e, 0x62, 0xd9, 0xcc, 0xd7, 0x33, 0x75, 0x34, 0x08, 0x9e, 0xaf, 0xa3, - 0xa4, 0xc5, 0x32, 0xef, 0x64, 0xea, 0xc8, 0xa4, 0x58, 0xea, 0x1b, 0x50, 0x3b, 0x0f, 0xdd, 0x38, - 0x76, 0xa4, 0x90, 0x73, 0x97, 0x3b, 0x56, 0xc2, 0x68, 0xf5, 0xbf, 0x01, 0x35, 0xee, 0x79, 0xc9, - 0xdf, 0xb6, 0x98, 0x44, 0xc2, 0x14, 0x83, 0x90, 0xbd, 0x31, 0x76, 0x7d, 0x32, 0xc7, 0x16, 0x8d, - 0x0a, 0x43, 0xf6, 0x5d, 0x3f, 0x8b, 0xb6, 0x2e, 0xc8, 0x28, 0x9b, 0xa2, 0xad, 0x0b, 0x5a, 0x92, - 0x13, 0xd7, 0xf3, 0x78, 0xe1, 0xbf, 0x29, 0x97, 0x24, 0x42, 0x68, 0xdd, 0x27, 0x68, 0xfa, 0xfa, - 0xbd, 0x0c, 0x9a, 0xbe, 0x8d, 0x13, 0x87, 0xd0, 0xf8, 0xe9, 0xb7, 0xe4, 0xc4, 0x41, 0x00, 0x7e, - 0x39, 0x45, 0x5a, 0x17, 0x64, 0x72, 0x4d, 0x90, 0xd6, 0x85, 0xe4, 0x5b, 0xb4, 0x53, 0x60, 0xde, - 0x77, 0x12, 0xbe, 0x85, 0x20, 0xcc, 0x9d, 0x25, 0xb0, 0x2e, 0xc8, 0xc6, 0x9a, 0x21, 0xb0, 0x2e, - 0xc8, 0xb8, 0xe0, 0x58, 0x36, 0x57, 0xfc, 0x5d, 0x2e, 0x1e, 0x01, 0x54, 0xef, 0x2d, 0xa8, 0x45, - 0x8f, 0xcd, 0x14, 0xff, 0x80, 0xb3, 0x47, 0x8f, 0x0d, 0x45, 0x71, 0x0f, 0xea, 0xc9, 0xd4, 0x60, - 0x9a, 0xf7, 0x78, 0xe0, 0x6d, 0x39, 0x35, 0xe8, 0x72, 0xca, 0x6f, 0x0a, 0x70, 0x8b, 0x8f, 0x38, - 0x89, 0xfd, 0xef, 0x3b, 0x51, 0x64, 0x9d, 0x38, 0xbb, 0x41, 0xb8, 0x3b, 0xfd, 0xee, 0xbb, 0x4b, - 0x71, 0x1f, 0xd6, 0x0f, 0xac, 0xd0, 0xf1, 0xe3, 0xc4, 0xf3, 0x40, 0x1a, 0x55, 0x67, 0xc1, 0xe2, - 0x09, 0x68, 0x0c, 0x62, 0x9f, 0xfc, 0x96, 0x3a, 0x37, 0x9f, 0x3d, 0x88, 0x9a, 0xa3, 0xd2, 0xff, - 0x69, 0x01, 0x2a, 0x3b, 0x6e, 0x14, 0x1b, 0xb8, 0x5d, 0x8a, 0x2f, 0x40, 0xf3, 0x82, 0x73, 0x54, - 0xf6, 0x49, 0x8c, 0xce, 0xe8, 0x9c, 0x72, 0x97, 0x4c, 0x15, 0xcd, 0x3a, 0x11, 0xa6, 0x9a, 0xe2, - 0x17, 0xa0, 0x4d, 0x27, 0x93, 0x7c, 0xd6, 0xa5, 0x57, 0x64, 0x25, 0xc2, 0x34, 0xeb, 0x7b, 0x50, - 0xcd, 0x7c, 0x75, 0x81, 0x5e, 0x0a, 0xe9, 0xb7, 0x90, 0x38, 0xf3, 0x9d, 0x05, 0x77, 0x82, 0x20, - 0x2d, 0x5d, 0xff, 0x8f, 0x96, 0x40, 0x93, 0x16, 0x5d, 0xcb, 0x76, 0x42, 0x72, 0x60, 0xc8, 0x59, - 0x34, 0x0a, 0x3f, 0x68, 0xd1, 0xd8, 0x82, 0x65, 0xcf, 0x1d, 0x27, 0x2e, 0xc8, 0xb9, 0x03, 0x60, - 0x42, 0xe0, 0x58, 0x07, 0xa1, 0x7b, 0x42, 0xb6, 0x97, 0xec, 0x35, 0x11, 0x3a, 0x28, 0xd8, 0x9d, - 0xfa, 0x23, 0x1a, 0xa2, 0x87, 0x00, 0xb6, 0x1b, 0xc5, 0x26, 0x59, 0x23, 0xf3, 0x66, 0xec, 0xa4, - 0xff, 0x8d, 0x8a, 0x9d, 0x0c, 0xc5, 0x7d, 0xd0, 0x32, 0x72, 0xb2, 0x9f, 0x18, 0x12, 0x97, 0x8d, - 0x54, 0x7e, 0x6e, 0xf9, 0x2d, 0x3f, 0x9e, 0xa3, 0x44, 0x99, 0x70, 0x65, 0x8e, 0x12, 0xe5, 0xc1, - 0xfb, 0xa0, 0x05, 0x2f, 0x9d, 0xd0, 0x3c, 0x76, 0xe2, 0xd1, 0xa9, 0xc9, 0xcd, 0x5a, 0xe5, 0x83, - 0x1b, 0x84, 0xef, 0x22, 0xb8, 0x8b, 0x50, 0xfd, 0x02, 0xae, 0x3e, 0x77, 0x46, 0x71, 0x10, 0x76, - 0x12, 0xcf, 0x17, 0x79, 0x47, 0x2f, 0x0c, 0xbc, 0xc4, 0xb6, 0x8f, 0xbf, 0xc5, 0x3b, 0x80, 0x1a, - 0x87, 0x33, 0x52, 0x3d, 0xb4, 0x50, 0x21, 0x71, 0x46, 0xd8, 0x4f, 0xcb, 0xa9, 0x6c, 0x34, 0x2f, - 0xf8, 0x30, 0x52, 0xff, 0xdb, 0xab, 0xb0, 0x9e, 0xf9, 0x34, 0x5d, 0x6e, 0x79, 0x04, 0x35, 0x79, - 0x04, 0x90, 0x3a, 0x7d, 0x2d, 0xf8, 0x50, 0x95, 0x89, 0x58, 0xd4, 0x7a, 0x02, 0x5a, 0x36, 0xcf, - 0xf7, 0x68, 0x41, 0xf5, 0x4c, 0x36, 0xd4, 0x85, 0xee, 0xc1, 0x32, 0x9f, 0xcc, 0xe5, 0xea, 0x99, - 0x9c, 0x7a, 0x32, 0x52, 0xfc, 0x35, 0x58, 0xe3, 0x93, 0x5f, 0x53, 0xde, 0xe2, 0x29, 0x65, 0x15, - 0xbc, 0x05, 0x9d, 0x67, 0xd4, 0x98, 0x9e, 0xd2, 0x91, 0xf8, 0x00, 0x6a, 0xe4, 0xda, 0x6d, 0xbe, - 0x24, 0xd2, 0xbc, 0x37, 0x29, 0x9b, 0xe1, 0x08, 0xcf, 0x25, 0x89, 0xf7, 0x60, 0x03, 0xe7, 0x86, - 0xe5, 0x8f, 0x1c, 0x9a, 0x68, 0x64, 0xa7, 0xe4, 0x53, 0x62, 0x4d, 0x21, 0x92, 0x23, 0x98, 0xdf, - 0x81, 0x8a, 0xed, 0x86, 0x0e, 0x13, 0xad, 0xfe, 0x18, 0x9b, 0x65, 0x4a, 0x2f, 0x1e, 0xe3, 0xde, - 0xe6, 0xdb, 0x2e, 0xe9, 0x18, 0x3c, 0x47, 0xca, 0x73, 0x75, 0xab, 0x27, 0x24, 0x34, 0x5f, 0xc4, - 0x67, 0xc4, 0xef, 0xb8, 0x7a, 0x3c, 0xc3, 0x2b, 0x8b, 0x67, 0xf8, 0x9a, 0x22, 0xe3, 0x59, 0xfe, - 0x1e, 0x54, 0x27, 0xa1, 0x63, 0x1e, 0xbb, 0x5e, 0xec, 0x84, 0xa8, 0x88, 0xcf, 0xda, 0x49, 0x60, - 0x12, 0x3a, 0xbb, 0x8c, 0x5d, 0xe8, 0x78, 0x54, 0x5d, 0xe8, 0x78, 0x24, 0x1e, 0xc2, 0x55, 0xd7, - 0x77, 0x63, 0xd7, 0xf2, 0x4c, 0xb6, 0x1e, 0xb1, 0x95, 0xb8, 0x46, 0x47, 0x6e, 0x1b, 0x12, 0x75, - 0x80, 0x18, 0x32, 0x17, 0x8b, 0xcf, 0x60, 0xe3, 0xd8, 0x0d, 0x71, 0x79, 0x12, 0xf7, 0xe2, 0x66, - 0xaf, 0xcd, 0x35, 0x7b, 0x9d, 0x88, 0x0c, 0xa4, 0xe1, 0x76, 0xbf, 0x0f, 0xe2, 0x68, 0x3a, 0x3a, - 0x73, 0x62, 0xd3, 0xb9, 0x98, 0x58, 0xbe, 0x6d, 0x46, 0xb1, 0x33, 0x21, 0x25, 0x6e, 0xcd, 0xd0, - 0x18, 0xd3, 0x26, 0xc4, 0x20, 0x76, 0x26, 0xe2, 0x2d, 0xa8, 0xc7, 0xa7, 0xb8, 0x25, 0x44, 0x66, - 0xe4, 0x58, 0xe1, 0xe8, 0x94, 0x2f, 0x60, 0x1b, 0x6b, 0x12, 0x3a, 0x20, 0xa0, 0x78, 0x0c, 0x6b, - 0x24, 0xc8, 0x26, 0x37, 0xe2, 0xb4, 0x85, 0x37, 0xe2, 0x6a, 0x48, 0xa4, 0x52, 0xe2, 0x31, 0x5c, - 0x9f, 0x04, 0x51, 0x2c, 0xbb, 0xd2, 0x4c, 0xd7, 0x39, 0x09, 0x75, 0x65, 0xe3, 0x2a, 0x62, 0xb9, - 0x27, 0xfb, 0x6a, 0xad, 0x8b, 0xcf, 0x80, 0x04, 0x64, 0x13, 0x85, 0x60, 0xa9, 0x97, 0xcd, 0x4f, - 0x60, 0x5c, 0x82, 0x2f, 0x82, 0xf0, 0x8c, 0x25, 0x62, 0xfc, 0xa5, 0xff, 0x9d, 0xf7, 0xa1, 0xd4, - 0x0b, 0x6c, 0x47, 0x7c, 0x04, 0x15, 0xba, 0xa3, 0x93, 0xd9, 0x29, 0xa4, 0xa1, 0x0a, 0xd1, 0xf4, - 0x87, 0x58, 0x7e, 0xd9, 0x97, 0xbf, 0x5e, 0x7d, 0xed, 0xf3, 0x0d, 0x32, 0xb0, 0x92, 0xb3, 0x1e, - 0xd6, 0xa3, 0xaa, 0xee, 0x32, 0x5b, 0x71, 0x64, 0x30, 0x06, 0x85, 0x74, 0x72, 0x1c, 0x08, 0x1d, - 0x9f, 0x96, 0xdb, 0xb2, 0x91, 0xa4, 0xc9, 0xac, 0x1d, 0x06, 0xc8, 0x0a, 0x58, 0x94, 0x5d, 0x5e, - 0x60, 0xd6, 0x66, 0x3c, 0xc9, 0xb6, 0x1f, 0x41, 0xe5, 0x9b, 0xc0, 0xf5, 0xb9, 0xe2, 0x2b, 0x73, - 0x15, 0xff, 0x32, 0x70, 0x7d, 0xae, 0xf8, 0x37, 0xf2, 0x97, 0x78, 0x13, 0x56, 0x03, 0x9f, 0xcb, - 0x5e, 0x9d, 0x2b, 0x7b, 0x25, 0xf0, 0xbb, 0x7c, 0x5b, 0x62, 0xcd, 0x8d, 0xcc, 0x90, 0x74, 0x5d, - 0xcc, 0x29, 0x9d, 0xfc, 0xaa, 0x6e, 0x64, 0x20, 0x0c, 0x8b, 0xc5, 0x39, 0x2f, 0x07, 0x89, 0x0a, - 0xab, 0xcc, 0xcf, 0x79, 0x46, 0x53, 0x81, 0x6f, 0x41, 0xf9, 0x24, 0x0c, 0xc8, 0x52, 0xb0, 0x60, - 0x75, 0xac, 0x12, 0x6e, 0xfb, 0x12, 0xf5, 0x30, 0xfa, 0xe9, 0xfa, 0x27, 0x26, 0x9d, 0x54, 0xe0, - 0xba, 0x28, 0x1b, 0x35, 0x05, 0xa4, 0x33, 0x88, 0xb7, 0xa0, 0x6c, 0x9d, 0x9c, 0x98, 0xf2, 0xd2, - 0xc7, 0x5c, 0x59, 0xd6, 0xc9, 0x09, 0x7d, 0xf2, 0x21, 0xac, 0x9d, 0xbb, 0xbe, 0x19, 0x4d, 0x9c, - 0x11, 0xd3, 0xae, 0xcd, 0x77, 0xe5, 0xb9, 0xeb, 0x23, 0x0f, 0x21, 0xfa, 0xec, 0x7e, 0x5a, 0xff, - 0xf1, 0xfb, 0xe9, 0xfa, 0xab, 0xf6, 0x53, 0x1d, 0x56, 0xa4, 0x53, 0x81, 0x36, 0x47, 0x22, 0x31, - 0xe2, 0x63, 0xa8, 0x86, 0x96, 0x7f, 0x66, 0x4a, 0x8f, 0xc9, 0xaf, 0xb3, 0xd6, 0x76, 0xc3, 0xf2, - 0xcf, 0xa4, 0xc3, 0x24, 0x84, 0xc9, 0xef, 0xbc, 0xee, 0xbd, 0xf1, 0x03, 0xf6, 0xb0, 0x8c, 0x99, - 0x4d, 0x7c, 0xbf, 0x99, 0xed, 0x53, 0xb2, 0x67, 0x39, 0x7e, 0x6c, 0xaa, 0x0c, 0x57, 0x17, 0x67, - 0xa8, 0x31, 0x59, 0x9f, 0xb3, 0x61, 0x03, 0xe8, 0xb4, 0xcb, 0xa4, 0xa3, 0xb1, 0xcd, 0x5c, 0x03, - 0x92, 0x63, 0x30, 0x03, 0xc2, 0xf4, 0x48, 0xac, 0x09, 0xeb, 0xe9, 0x1d, 0x50, 0xbe, 0x78, 0x7b, - 0x2d, 0x7b, 0xde, 0x9f, 0xbb, 0x34, 0xaa, 0x2c, 0x68, 0x6e, 0xee, 0x26, 0xe9, 0x9b, 0xb0, 0xc6, - 0xce, 0xd3, 0xdc, 0x6f, 0x91, 0xf4, 0x57, 0xaf, 0x11, 0x90, 0xfb, 0x29, 0x22, 0x49, 0x45, 0x9a, - 0xf5, 0xe2, 0x0b, 0x52, 0xb7, 0x52, 0x3e, 0xce, 0x76, 0xbc, 0xf8, 0xc2, 0xa8, 0xd8, 0xea, 0x27, - 0x6a, 0x11, 0x47, 0xae, 0x6f, 0xe3, 0xd4, 0x8b, 0xad, 0x93, 0xa8, 0xd1, 0xa0, 0x95, 0x59, 0x95, - 0xb0, 0xa1, 0x75, 0x12, 0x89, 0x4f, 0xa0, 0x66, 0xb1, 0xd5, 0x82, 0xeb, 0x7d, 0x33, 0x7b, 0x3a, - 0x94, 0xb1, 0x67, 0x18, 0x55, 0x2b, 0x63, 0xdc, 0xf8, 0x1c, 0x84, 0xf2, 0x79, 0xca, 0xd8, 0xd2, - 0x6f, 0xcd, 0xcd, 0xc6, 0x75, 0xe9, 0xf4, 0x94, 0x58, 0xd2, 0xef, 0x82, 0x14, 0x05, 0x98, 0x1d, - 0xbf, 0x46, 0x15, 0x02, 0x06, 0x11, 0x23, 0xfe, 0x1c, 0xd6, 0xf2, 0xe6, 0x9a, 0xdb, 0x0b, 0x5c, - 0x87, 0x78, 0xe3, 0xae, 0x8d, 0xb2, 0x06, 0x9c, 0x37, 0xf9, 0x2e, 0x33, 0xa9, 0x5a, 0x94, 0x91, - 0xdd, 0x63, 0x6a, 0x7e, 0x10, 0xb7, 0x14, 0x0c, 0x3b, 0x50, 0x19, 0x53, 0xe3, 0x0b, 0xd2, 0xce, - 0x92, 0x0e, 0x4c, 0x6c, 0x50, 0x46, 0xc5, 0x4d, 0xcc, 0x51, 0x3b, 0x20, 0x94, 0x83, 0x02, 0x4a, - 0xa9, 0xec, 0x7e, 0x4b, 0xca, 0x58, 0xe2, 0x4d, 0x34, 0x2b, 0xc4, 0x1a, 0xec, 0xaa, 0x9c, 0x15, - 0x6b, 0x9f, 0x40, 0x1d, 0xb7, 0xd2, 0xcc, 0x97, 0xf5, 0x6c, 0xa3, 0x0e, 0x42, 0x27, 0xfd, 0x78, - 0x6d, 0x92, 0x49, 0x89, 0x5f, 0xc0, 0x46, 0x26, 0xe7, 0xf4, 0x8c, 0x32, 0xbf, 0x49, 0x99, 0x37, - 0x67, 0x32, 0x1f, 0x9e, 0x61, 0xf6, 0xfa, 0x24, 0x97, 0x16, 0x9b, 0xb0, 0xdc, 0x89, 0xda, 0xbe, - 0x4d, 0x4a, 0x5a, 0xd9, 0xe0, 0x84, 0x78, 0x0c, 0x35, 0xb6, 0x88, 0x90, 0x61, 0x32, 0x6a, 0xbc, - 0x9d, 0x3d, 0xfe, 0x25, 0xb3, 0x08, 0x5b, 0x37, 0xab, 0x5e, 0xf2, 0x3b, 0xc2, 0x8d, 0x98, 0xcf, - 0xe6, 0xb3, 0x2c, 0xf2, 0x9d, 0xf9, 0x21, 0x27, 0xa2, 0xdd, 0x94, 0x4f, 0x1a, 0x70, 0x33, 0x9c, - 0xfa, 0x64, 0x25, 0x91, 0x39, 0x79, 0xdf, 0xa7, 0xfc, 0xf7, 0x29, 0xbf, 0x8c, 0x8e, 0x61, 0x30, - 0x19, 0xe7, 0x25, 0xde, 0x74, 0x3d, 0xcc, 0x82, 0x48, 0x2a, 0x78, 0x45, 0x99, 0x7c, 0x9a, 0x42, - 0x65, 0xbe, 0xfb, 0x53, 0xca, 0xa4, 0x93, 0x16, 0x2a, 0x53, 0x40, 0x69, 0x3a, 0x75, 0x6d, 0x52, - 0x19, 0x6b, 0x06, 0xfd, 0x46, 0xb1, 0x20, 0x74, 0x46, 0xd3, 0x30, 0x72, 0x5f, 0x3a, 0x66, 0xe4, - 0xfa, 0x67, 0xa4, 0x2c, 0x96, 0x8d, 0xb5, 0x04, 0x3a, 0x70, 0xfd, 0x33, 0x64, 0x19, 0xce, 0x45, - 0xec, 0x84, 0x3e, 0x5f, 0x02, 0x7f, 0x3f, 0xcb, 0x32, 0xda, 0x84, 0xc0, 0x75, 0x6e, 0x80, 0x93, - 0xfc, 0x9e, 0x19, 0xd9, 0x88, 0x47, 0xf6, 0xe1, 0x8f, 0x1a, 0xd9, 0x01, 0x8d, 0xec, 0xdb, 0x50, - 0x76, 0xfd, 0xd8, 0x09, 0x5f, 0x5a, 0x5e, 0xe3, 0xc3, 0x39, 0x6e, 0x9c, 0xe0, 0xc4, 0x3d, 0x58, - 0x8d, 0x3c, 0x17, 0xd7, 0x7b, 0xe3, 0xa3, 0x39, 0x32, 0x85, 0x12, 0xf7, 0xa1, 0x92, 0x84, 0x6c, - 0x69, 0x7c, 0x3c, 0x47, 0x97, 0x22, 0xc5, 0x1d, 0x28, 0x9d, 0xe3, 0x84, 0x7a, 0x34, 0x7f, 0x5c, - 0x8f, 0x70, 0xdc, 0xbe, 0x8f, 0x51, 0xf9, 0xa7, 0xed, 0xfb, 0xf1, 0xdc, 0xf6, 0xbd, 0xeb, 0x7a, - 0x1e, 0x6f, 0xdf, 0xc7, 0xf2, 0x17, 0x6e, 0x7e, 0x94, 0x03, 0x5b, 0xf2, 0xc9, 0xfc, 0xe6, 0x87, - 0xb8, 0xe7, 0x14, 0xdc, 0xa6, 0x1a, 0xd1, 0x19, 0x34, 0x1f, 0xa5, 0x7f, 0x9a, 0xed, 0xab, 0xfc, - 0xe1, 0xb4, 0x01, 0x51, 0x92, 0x16, 0xaf, 0x83, 0x3c, 0x62, 0x27, 0xed, 0xeb, 0x33, 0x0e, 0x21, - 0xc0, 0x10, 0x54, 0xbc, 0x3e, 0x82, 0x35, 0xe5, 0x3b, 0x8d, 0x9f, 0x8b, 0x1a, 0x9f, 0xcf, 0xd5, - 0x20, 0x4f, 0x20, 0x76, 0xa0, 0x76, 0x3c, 0xfd, 0xee, 0xbb, 0xcb, 0x31, 0xdb, 0x04, 0x1a, 0x4f, - 0xa8, 0x22, 0x5b, 0x6a, 0x63, 0x7d, 0x95, 0xcd, 0xc0, 0xc8, 0xe5, 0x12, 0x0f, 0x41, 0xb8, 0xc7, - 0x3c, 0x9e, 0xbb, 0x61, 0x30, 0x66, 0xbd, 0xbf, 0xf1, 0x85, 0x3c, 0x97, 0x98, 0xc3, 0x90, 0x43, - 0x8e, 0xe3, 0xdb, 0xe6, 0x38, 0x92, 0x62, 0xc2, 0xcf, 0xa8, 0x9e, 0x92, 0x79, 0x25, 0xa1, 0x9d, - 0xd4, 0x81, 0x2b, 0xd2, 0xee, 0x47, 0x2c, 0x35, 0x7c, 0x01, 0x38, 0x5d, 0x5f, 0xa6, 0x59, 0x7f, - 0xe7, 0x7b, 0xb3, 0x22, 0xad, 0xca, 0xfa, 0x04, 0xea, 0x7c, 0x1a, 0x42, 0x12, 0x19, 0x4e, 0xd1, - 0x9f, 0x67, 0x39, 0x57, 0xf6, 0x18, 0xd7, 0xa8, 0xd9, 0xd9, 0x43, 0xdd, 0xcf, 0x61, 0x3d, 0x73, - 0x18, 0x42, 0x9f, 0xfd, 0xdd, 0xec, 0x67, 0x93, 0xd3, 0x10, 0x63, 0x6d, 0xaa, 0x7e, 0xd2, 0x27, - 0xe7, 0x44, 0xec, 0xbf, 0xf6, 0x23, 0x44, 0xec, 0x37, 0x21, 0x5d, 0x91, 0xe6, 0x28, 0x76, 0x1a, - 0xbf, 0x60, 0xe6, 0x9f, 0x00, 0x5b, 0xb1, 0x23, 0x1e, 0x03, 0x58, 0x93, 0x89, 0x77, 0xc9, 0x53, - 0xf3, 0x97, 0x34, 0x35, 0x37, 0x33, 0x53, 0xb3, 0x89, 0x48, 0x9a, 0x9b, 0x15, 0x4b, 0xfd, 0x44, - 0x05, 0x97, 0x84, 0x77, 0x7b, 0xec, 0x51, 0xfb, 0x9b, 0xd9, 0xb5, 0x7d, 0x10, 0x44, 0xf1, 0xce, - 0xd8, 0xc3, 0x56, 0xc0, 0x24, 0xf9, 0x2d, 0xba, 0x70, 0x35, 0xf0, 0x4d, 0x7b, 0x3a, 0xf1, 0xdc, - 0x11, 0xf6, 0x00, 0x9f, 0x42, 0x36, 0xb6, 0xb3, 0xf7, 0x93, 0xe8, 0x8b, 0x7d, 0x7f, 0x47, 0x11, - 0xc9, 0xd3, 0xcd, 0x8d, 0x60, 0x16, 0x44, 0x06, 0x2b, 0x1a, 0x83, 0xe4, 0x6a, 0x4f, 0x8b, 0x45, - 0x03, 0x82, 0xaa, 0xbb, 0x3d, 0x4f, 0x60, 0x3d, 0xa5, 0xc2, 0x06, 0x46, 0x8d, 0x9d, 0xec, 0x4c, - 0xce, 0xdc, 0x82, 0x5c, 0x53, 0x19, 0x11, 0x16, 0x51, 0xdf, 0x05, 0x9e, 0x37, 0x9d, 0x48, 0x56, - 0xda, 0x68, 0xcb, 0xbe, 0x23, 0x20, 0x73, 0xc9, 0x8c, 0x4d, 0xcf, 0x19, 0x37, 0x76, 0xb3, 0x36, - 0x3d, 0x67, 0x8c, 0x62, 0x86, 0xf4, 0xb3, 0x7f, 0xe9, 0x3a, 0xe7, 0x51, 0xe3, 0x29, 0x69, 0x7e, - 0xf2, 0xce, 0xdf, 0x73, 0x04, 0xe1, 0xbe, 0xcf, 0x7a, 0x2c, 0x91, 0x34, 0xf6, 0xf8, 0xd2, 0x17, - 0x83, 0x90, 0x42, 0xb4, 0xa0, 0x41, 0xec, 0x5c, 0xae, 0xd5, 0x9c, 0x1f, 0x4c, 0x67, 0x6e, 0x49, - 0x5e, 0x43, 0x5a, 0x76, 0xb3, 0x39, 0xc8, 0x78, 0xc4, 0xfc, 0x12, 0x5e, 0x5f, 0x5c, 0x88, 0x0a, - 0x3b, 0xf0, 0x25, 0xc9, 0x1b, 0x37, 0x17, 0xe4, 0x96, 0xb1, 0x07, 0x7e, 0x06, 0x6b, 0x27, 0x16, - 0xf5, 0x84, 0x67, 0x8e, 0x03, 0xdb, 0x69, 0x3c, 0xcb, 0x86, 0xcb, 0xa1, 0x41, 0x7b, 0x6a, 0x61, - 0xa7, 0x78, 0xfb, 0x81, 0xed, 0x18, 0xd5, 0x93, 0x34, 0x21, 0x9e, 0x40, 0x23, 0x9d, 0x84, 0x53, - 0x1f, 0xbf, 0x8b, 0x2a, 0xb5, 0xeb, 0x8f, 0xe2, 0x46, 0x97, 0xfa, 0xf4, 0x7a, 0x82, 0x3f, 0x44, - 0xf4, 0x8e, 0xc4, 0x8a, 0x16, 0x68, 0xc4, 0x1c, 0xe4, 0x2e, 0x16, 0xb9, 0xb6, 0xd3, 0xd8, 0xcf, - 0x86, 0xc3, 0x60, 0xd6, 0x89, 0x24, 0xb4, 0x5f, 0x0d, 0x5c, 0xdb, 0x31, 0xea, 0xc7, 0xb9, 0xb4, - 0x78, 0x17, 0x36, 0x94, 0x3e, 0x62, 0x9e, 0x5a, 0xd1, 0xa9, 0x79, 0xe6, 0x5c, 0x36, 0x7a, 0xd4, - 0xe0, 0xba, 0x54, 0x46, 0xf6, 0xac, 0xe8, 0xf4, 0x99, 0x73, 0x29, 0x1e, 0xa0, 0x4e, 0x4d, 0xdb, - 0xa6, 0x1b, 0x99, 0x47, 0x56, 0x18, 0xba, 0x4e, 0xd8, 0xe8, 0xf3, 0x11, 0x1a, 0x23, 0x3a, 0xd1, - 0x36, 0x83, 0x51, 0x8f, 0xce, 0x0e, 0x86, 0x54, 0xd7, 0x0f, 0x88, 0x8f, 0x6a, 0x19, 0x77, 0x24, - 0xd6, 0xd6, 0x3f, 0x82, 0x7a, 0xd2, 0x7f, 0xec, 0x94, 0xf3, 0xab, 0xb9, 0x7d, 0xa2, 0x26, 0x3b, - 0x6d, 0x40, 0x5e, 0x39, 0xef, 0x43, 0x2d, 0xc9, 0xe1, 0xf8, 0x76, 0xc3, 0x98, 0x37, 0x1b, 0x4a, - 0x7a, 0xdc, 0x5d, 0x3e, 0x85, 0x1b, 0x3c, 0xcd, 0xf9, 0xe8, 0xe4, 0xcc, 0xb9, 0x4c, 0xa2, 0x9f, - 0x0c, 0xa8, 0xfe, 0x9b, 0x84, 0xee, 0x20, 0xf6, 0x99, 0x73, 0x19, 0x25, 0xdc, 0xf3, 0x26, 0xb9, - 0x16, 0x8c, 0xe4, 0x8d, 0x61, 0x36, 0xab, 0xcb, 0xb6, 0x0c, 0x79, 0x6c, 0x90, 0xa0, 0x95, 0xe0, - 0x0d, 0xe9, 0xae, 0x26, 0x9a, 0xb0, 0xc1, 0x76, 0xa0, 0x6c, 0x98, 0x97, 0x43, 0xaa, 0xe4, 0xb5, - 0x85, 0x0a, 0xb9, 0xb1, 0xfe, 0x72, 0xc6, 0x48, 0xf6, 0x14, 0x6e, 0x25, 0x67, 0xa5, 0xce, 0xb7, - 0x53, 0x8b, 0xae, 0x5b, 0x9d, 0x39, 0x97, 0xcc, 0x16, 0x5f, 0xcc, 0xcd, 0xee, 0x1b, 0x8a, 0xba, - 0x2d, 0x89, 0x9f, 0x39, 0x97, 0xc4, 0x1b, 0xef, 0x41, 0xdd, 0x8a, 0x82, 0x63, 0xa9, 0xc5, 0x8e, - 0x02, 0xaf, 0xf1, 0x9c, 0xc6, 0xa1, 0x86, 0x50, 0x43, 0x1d, 0xcd, 0xf6, 0xe0, 0x6a, 0x3a, 0x62, - 0x96, 0x77, 0x12, 0x84, 0x6e, 0x7c, 0x3a, 0x6e, 0xfc, 0x3a, 0x6b, 0x6d, 0xa2, 0x09, 0x95, 0x4c, - 0xfe, 0xa6, 0x22, 0x32, 0xd2, 0xb1, 0x4e, 0x60, 0xe2, 0x09, 0xdc, 0x4c, 0xcb, 0x8b, 0x83, 0x89, - 0xe9, 0x9b, 0xe7, 0x6e, 0x7c, 0x6a, 0x92, 0x5f, 0xf3, 0xef, 0xc9, 0xc8, 0x1a, 0x8a, 0x60, 0x18, - 0x4c, 0x7a, 0x2f, 0xdc, 0xf8, 0x74, 0xe8, 0x3a, 0x91, 0xd8, 0x86, 0x3b, 0x96, 0x6d, 0x4d, 0x62, - 0x5c, 0x10, 0x98, 0x31, 0x89, 0x06, 0x12, 0xf8, 0xa6, 0x33, 0x9e, 0xc4, 0x97, 0x8d, 0xbf, 0x4e, - 0xd9, 0x6f, 0x29, 0xaa, 0x61, 0x30, 0xd9, 0x95, 0x34, 0x7d, 0xbf, 0x8d, 0x14, 0xfa, 0x3f, 0x5f, - 0x86, 0xb2, 0x32, 0x56, 0x88, 0x2a, 0xac, 0x1e, 0xf6, 0x9e, 0xf5, 0xfa, 0x2f, 0x7a, 0x1c, 0x2c, - 0xaa, 0x39, 0x18, 0xb4, 0x8d, 0xa1, 0x66, 0x8b, 0x3a, 0x00, 0x85, 0x53, 0x31, 0x07, 0xad, 0x66, - 0x8f, 0x83, 0x47, 0x51, 0x10, 0x17, 0x4e, 0x2f, 0x89, 0x0d, 0x58, 0xdb, 0x3d, 0xec, 0xf1, 0x95, - 0x23, 0x02, 0x15, 0x11, 0xd4, 0xfe, 0x8a, 0xfd, 0xfe, 0x18, 0x54, 0x42, 0xd0, 0x7e, 0x73, 0xd8, - 0x36, 0x3a, 0x0a, 0xb4, 0x2c, 0xae, 0xc1, 0x46, 0x42, 0xa5, 0x4a, 0xd0, 0x56, 0x11, 0xfc, 0xbc, - 0xdd, 0x1a, 0xf6, 0x0d, 0xb3, 0xd3, 0xdb, 0x69, 0x7f, 0xc5, 0xd4, 0x65, 0xac, 0xdf, 0x81, 0xd1, - 0xff, 0xb2, 0xdd, 0x1a, 0x6a, 0x40, 0xae, 0x84, 0x4f, 0x9f, 0x6a, 0x55, 0x51, 0x83, 0xf2, 0x4e, - 0x67, 0x30, 0xec, 0xf4, 0x5a, 0x43, 0xad, 0x86, 0xd5, 0xde, 0xed, 0x74, 0x87, 0x6d, 0x43, 0x5b, - 0x13, 0x65, 0x28, 0x7d, 0xd9, 0xef, 0xf4, 0xb4, 0x3a, 0x05, 0x97, 0x69, 0xee, 0x1f, 0x74, 0xdb, - 0xda, 0x3a, 0x42, 0x07, 0x7d, 0x63, 0xa8, 0x69, 0x08, 0x7d, 0xd1, 0xe9, 0xed, 0xf4, 0x5f, 0x68, - 0x1b, 0xa2, 0x02, 0xcb, 0x87, 0x3d, 0xfc, 0xba, 0x10, 0x6b, 0x50, 0xa1, 0x9f, 0x66, 0xb3, 0xdb, - 0xd5, 0xae, 0x66, 0xfc, 0x0f, 0x37, 0x11, 0x45, 0xde, 0x8c, 0x03, 0xac, 0xc3, 0x35, 0x6c, 0x51, - 0x92, 0x24, 0xea, 0xeb, 0x58, 0xce, 0x7e, 0xa7, 0x77, 0x38, 0xd0, 0x6e, 0x20, 0x31, 0xfd, 0x24, - 0x4c, 0x03, 0xcb, 0xe9, 0xf4, 0xa8, 0x43, 0xef, 0xe0, 0xef, 0x9d, 0x76, 0xb7, 0x3d, 0x6c, 0x6b, - 0x77, 0xb1, 0x55, 0xdd, 0x7e, 0xeb, 0x99, 0xd9, 0x3f, 0xd0, 0xde, 0xc0, 0x9e, 0x3d, 0x30, 0xda, - 0xa6, 0x24, 0x7c, 0x53, 0x68, 0x50, 0xdb, 0x3d, 0xfc, 0xf5, 0xaf, 0xbf, 0x36, 0x65, 0xa3, 0xde, - 0xc2, 0x6f, 0xa6, 0x14, 0xe6, 0xe1, 0x33, 0xed, 0xed, 0x19, 0xd0, 0xe0, 0x99, 0xf6, 0x0e, 0x76, - 0x8a, 0xea, 0x6b, 0xed, 0x3e, 0x12, 0x18, 0xed, 0xd6, 0xa1, 0x31, 0xe8, 0x3c, 0x6f, 0x9b, 0xad, - 0x61, 0x5b, 0x7b, 0x97, 0x7a, 0xa1, 0xd3, 0x7b, 0xa6, 0x3d, 0xc0, 0x6a, 0xe2, 0x2f, 0xee, 0xe4, - 0xf7, 0x84, 0x80, 0x7a, 0x4a, 0x4b, 0xb0, 0xf7, 0x91, 0x64, 0xdb, 0xe8, 0x37, 0x77, 0x5a, 0xcd, - 0xc1, 0x50, 0xfb, 0x00, 0xdb, 0x38, 0x38, 0xe8, 0x76, 0x86, 0xda, 0x43, 0x6c, 0xc8, 0xd3, 0xe6, - 0x70, 0xaf, 0x6d, 0x68, 0x1f, 0x8a, 0x75, 0xa8, 0x0e, 0x3b, 0xfb, 0x6d, 0x53, 0xf6, 0xe9, 0x23, - 0xfc, 0xc6, 0x6e, 0xa7, 0xdb, 0xd5, 0x1e, 0x93, 0xff, 0x5c, 0xd3, 0x18, 0x76, 0x68, 0x7c, 0x3f, - 0xc1, 0x02, 0x9a, 0x07, 0x07, 0xdd, 0xaf, 0xb5, 0x4f, 0xb1, 0x81, 0xfb, 0x87, 0xdd, 0x61, 0xc7, - 0x3c, 0x3c, 0xd8, 0x69, 0x0e, 0xdb, 0xda, 0x67, 0x34, 0xca, 0xfd, 0xc1, 0x70, 0x67, 0xbf, 0xab, - 0x7d, 0x4e, 0x65, 0xd2, 0x4c, 0x6b, 0x75, 0xfb, 0xbd, 0xb6, 0xf6, 0x04, 0xe9, 0x9b, 0x3b, 0xcd, - 0x83, 0x21, 0xd6, 0x6e, 0xd8, 0x3f, 0xd0, 0xbe, 0xd0, 0x4b, 0xe5, 0x15, 0x6d, 0x45, 0x2f, 0x95, - 0xb7, 0xb4, 0x2d, 0xbd, 0x54, 0xd6, 0x35, 0xfd, 0x41, 0x75, 0xd0, 0x3f, 0x34, 0x5a, 0x5c, 0x7b, - 0xfd, 0x6f, 0x16, 0xa0, 0xac, 0xac, 0x5a, 0xf8, 0xe1, 0x4e, 0xaf, 0xd7, 0x36, 0xb4, 0x2b, 0x58, - 0xb9, 0x6e, 0x7b, 0x77, 0xa8, 0x15, 0xc8, 0xfd, 0xb0, 0xf3, 0x74, 0x6f, 0xa8, 0x2d, 0xe1, 0xcf, - 0xfe, 0x21, 0xf6, 0x73, 0x91, 0x3a, 0xa8, 0xbd, 0xdf, 0xd1, 0x4a, 0xf8, 0xab, 0xd9, 0x1b, 0x76, - 0xb4, 0x65, 0x9a, 0x46, 0x9d, 0xde, 0xd3, 0x6e, 0x5b, 0x5b, 0x41, 0xe8, 0x7e, 0xd3, 0x78, 0xa6, - 0xad, 0x72, 0xa1, 0x3b, 0xed, 0xaf, 0xb4, 0xb2, 0x58, 0x81, 0xa5, 0xee, 0x23, 0xad, 0x82, 0xa0, - 0x9d, 0xf6, 0xce, 0xe1, 0x81, 0x06, 0x94, 0x7b, 0xd0, 0xdf, 0xd5, 0xaa, 0xd8, 0x09, 0xf8, 0xcb, - 0xa4, 0xcf, 0xd6, 0xf4, 0xfb, 0xb0, 0xda, 0x3c, 0x39, 0xa1, 0xbd, 0x0d, 0x3b, 0xea, 0xb0, 0xdb, - 0xe5, 0x55, 0xb7, 0xdd, 0x1f, 0x0e, 0xfb, 0xfb, 0x5a, 0x01, 0x67, 0x38, 0xb6, 0x70, 0x49, 0xef, - 0x40, 0x59, 0x09, 0xf6, 0x99, 0xc0, 0x4a, 0x65, 0x28, 0x1d, 0x18, 0xed, 0xe7, 0xec, 0x4c, 0xdb, - 0x6b, 0x7f, 0x85, 0xf5, 0xc7, 0x5f, 0x58, 0x50, 0x11, 0x6b, 0xc0, 0x11, 0x90, 0x28, 0xb2, 0x52, - 0xb7, 0xd3, 0x6b, 0x37, 0x0d, 0x6d, 0x59, 0x7f, 0x02, 0xd5, 0xcc, 0x0e, 0x8b, 0x13, 0xe3, 0x69, - 0xf3, 0x00, 0x27, 0x57, 0xd7, 0x94, 0xc5, 0x5e, 0x07, 0x91, 0x80, 0xd2, 0x31, 0x2b, 0xe8, 0x9f, - 0xc2, 0xc6, 0x9c, 0x40, 0x45, 0x15, 0x6f, 0x76, 0x64, 0xc5, 0x3b, 0x4f, 0x7b, 0x7d, 0xa3, 0xcd, - 0x41, 0x9e, 0xe4, 0x68, 0x2e, 0xe9, 0xef, 0x41, 0x25, 0x91, 0xfc, 0x70, 0x76, 0xb7, 0x8c, 0xfe, - 0x60, 0xc0, 0x83, 0x7f, 0x05, 0xd3, 0xd4, 0xdd, 0x9c, 0x2e, 0xe8, 0x2e, 0xd4, 0xf3, 0xdb, 0xb0, - 0xd8, 0x82, 0xdb, 0x3c, 0xff, 0xb7, 0x0f, 0x3b, 0xdd, 0x1d, 0x73, 0xd0, 0xd9, 0x69, 0xcf, 0xdc, - 0x1e, 0xbf, 0x05, 0xd7, 0xe7, 0x28, 0x38, 0xc2, 0x54, 0x41, 0xdc, 0x84, 0x6b, 0x73, 0x38, 0x9a, - 0xf5, 0x4b, 0xfa, 0x01, 0x88, 0x79, 0x06, 0x2d, 0x6e, 0x43, 0x23, 0x69, 0xb3, 0xd9, 0xec, 0x3e, - 0xed, 0x1b, 0x9d, 0xe1, 0xde, 0xbe, 0x49, 0xfc, 0xe2, 0xca, 0xab, 0xb0, 0x7b, 0xcd, 0xc1, 0x9e, - 0x56, 0xf8, 0xb2, 0x54, 0xbe, 0xab, 0x6d, 0x7d, 0x59, 0x2a, 0xdf, 0xd3, 0xde, 0xd2, 0x07, 0xb0, - 0xa1, 0xa4, 0x67, 0xba, 0x9b, 0x4f, 0x66, 0x9d, 0x4d, 0x58, 0xee, 0x3a, 0x2f, 0x1d, 0x4f, 0x5d, - 0xe5, 0xa6, 0x04, 0x42, 0xfb, 0x47, 0xdf, 0x74, 0x92, 0x80, 0x88, 0x94, 0x40, 0x75, 0xb9, 0x97, - 0x89, 0xc9, 0x48, 0xe1, 0x14, 0xfe, 0x8d, 0x02, 0x94, 0x13, 0x99, 0xfc, 0x1e, 0x2c, 0x0d, 0x07, - 0xf2, 0x40, 0x68, 0xf3, 0x61, 0x1a, 0x80, 0x77, 0xa8, 0x7e, 0x19, 0x4b, 0xc3, 0x81, 0x78, 0x1f, - 0x56, 0x38, 0x2c, 0x9c, 0x3c, 0x02, 0xda, 0xcc, 0xcb, 0xf9, 0x43, 0xc2, 0x19, 0x92, 0x46, 0x7c, - 0x0a, 0x95, 0xa4, 0xb6, 0xd2, 0x1a, 0x7d, 0x23, 0x9f, 0x21, 0x41, 0x1b, 0x29, 0xa5, 0xde, 0x85, - 0x7a, 0xbe, 0x40, 0x71, 0x07, 0x80, 0x8b, 0xcc, 0x9c, 0xdd, 0x66, 0x20, 0xe2, 0x16, 0xa8, 0x68, - 0x75, 0x3b, 0x54, 0xb1, 0xb5, 0x24, 0x7a, 0xdd, 0x8e, 0xfe, 0xef, 0x2e, 0x03, 0xa4, 0x5a, 0x3d, - 0x76, 0x44, 0x62, 0x63, 0x5f, 0x96, 0x5e, 0xbe, 0xaf, 0x41, 0xc5, 0x0b, 0x2c, 0x3b, 0x1b, 0x48, - 0xb7, 0x8c, 0x00, 0x9a, 0x63, 0xd9, 0x78, 0x33, 0x15, 0x19, 0x3a, 0xe6, 0x3a, 0xac, 0x1c, 0x07, - 0xe1, 0xd8, 0x8a, 0xe5, 0xbd, 0x7d, 0x99, 0xa2, 0x90, 0x32, 0xe4, 0xa4, 0x66, 0x9b, 0x9e, 0xeb, - 0x3b, 0x1c, 0x38, 0xab, 0x64, 0xd4, 0x24, 0xb0, 0x8b, 0x30, 0x14, 0xae, 0x1d, 0x7f, 0xe4, 0x05, - 0x28, 0xd6, 0x1c, 0xf1, 0xad, 0x85, 0x9a, 0x01, 0x0a, 0xb4, 0x7d, 0xc9, 0xad, 0x0d, 0xc7, 0xae, - 0x6f, 0xc5, 0xd2, 0x7b, 0x87, 0x5a, 0xab, 0x20, 0x58, 0xdd, 0x6f, 0xa2, 0x40, 0x9a, 0xdc, 0x39, - 0xa0, 0x49, 0x19, 0x01, 0x54, 0xdd, 0xd7, 0x01, 0x9c, 0x68, 0x64, 0x4d, 0xb8, 0xf0, 0x0a, 0x47, - 0x72, 0x93, 0x90, 0xed, 0x4b, 0xd1, 0x85, 0xfa, 0xf0, 0x08, 0x95, 0x89, 0x60, 0xc7, 0x8a, 0xad, - 0x56, 0xe0, 0x49, 0x63, 0xf8, 0xbd, 0x59, 0xf3, 0xc7, 0xc3, 0x3c, 0x19, 0xdf, 0x9c, 0x9b, 0xc9, - 0x2b, 0x3e, 0x81, 0x9a, 0x3b, 0x72, 0x8e, 0x9c, 0xf0, 0x84, 0x05, 0xad, 0x6a, 0xee, 0xc2, 0x3d, - 0x63, 0x48, 0xc8, 0xaa, 0xba, 0x69, 0x02, 0x95, 0xb4, 0x71, 0xe0, 0x9f, 0x04, 0xf6, 0x11, 0xe7, - 0xaa, 0x65, 0x0d, 0x7b, 0xfb, 0x88, 0xe1, 0x3c, 0x92, 0x88, 0xf2, 0xfc, 0x2e, 0xac, 0x63, 0xcf, - 0x47, 0x71, 0xe8, 0x58, 0x63, 0xce, 0xb6, 0x96, 0x9d, 0x81, 0x58, 0xa3, 0x01, 0x21, 0x29, 0x6f, - 0x3d, 0x25, 0xa6, 0xec, 0x9f, 0xa4, 0xd7, 0xd9, 0x29, 0x6f, 0x3d, 0xe7, 0x55, 0xcf, 0x18, 0xfe, - 0xe8, 0x71, 0x9a, 0x10, 0x0f, 0x01, 0xce, 0xac, 0xe3, 0x33, 0x8b, 0xf3, 0xac, 0x67, 0xab, 0xf9, - 0x0c, 0xe1, 0x94, 0xa3, 0x72, 0xa6, 0x7e, 0xde, 0x6a, 0xc2, 0xd5, 0x05, 0xbd, 0xf6, 0x93, 0xae, - 0x81, 0xfd, 0xdd, 0x02, 0xd4, 0xf3, 0x6d, 0x99, 0x89, 0x8a, 0x59, 0x49, 0xa2, 0x62, 0x0a, 0x28, - 0x4d, 0x82, 0x50, 0xdd, 0xd8, 0xa0, 0xdf, 0x69, 0x90, 0xea, 0x62, 0x36, 0x48, 0x75, 0x03, 0x56, - 0x43, 0x87, 0x6f, 0x5f, 0x73, 0xa4, 0x06, 0x95, 0xc4, 0x09, 0x3b, 0x99, 0x46, 0xa7, 0x8e, 0xad, - 0xb4, 0x49, 0xbe, 0x46, 0x50, 0x63, 0xa0, 0xd4, 0x26, 0x6f, 0xc0, 0xaa, 0x35, 0x71, 0x49, 0x41, - 0x91, 0x11, 0x16, 0xad, 0x89, 0xfb, 0xcc, 0xb9, 0xd4, 0xbf, 0x83, 0x6a, 0xa6, 0xef, 0xb0, 0x42, - 0x67, 0xae, 0xaf, 0x22, 0x4b, 0xd0, 0x6f, 0xac, 0xbc, 0x0c, 0x2a, 0xc8, 0x77, 0x41, 0x64, 0x0a, - 0x3f, 0xac, 0xae, 0xf1, 0xd1, 0xe9, 0xac, 0x3a, 0xea, 0x97, 0xc0, 0x5f, 0x21, 0x0c, 0x97, 0x35, - 0x56, 0xc4, 0x0e, 0xce, 0x7d, 0x59, 0xf1, 0x24, 0xad, 0xff, 0x17, 0x4b, 0x50, 0x49, 0x06, 0x01, - 0x5b, 0x78, 0x14, 0x06, 0x67, 0x4e, 0x18, 0xc9, 0xaf, 0xab, 0x24, 0xf5, 0x48, 0x30, 0x71, 0x47, - 0xea, 0x52, 0x34, 0x25, 0xc4, 0xed, 0xec, 0x15, 0x48, 0x8e, 0x56, 0x92, 0xb9, 0xf1, 0x78, 0x07, - 0xc0, 0x9a, 0xc6, 0xc1, 0x28, 0x18, 0x8f, 0xdd, 0x58, 0x7e, 0x39, 0x03, 0xc1, 0x32, 0x49, 0x45, - 0x93, 0xbd, 0xc5, 0x89, 0x0c, 0x53, 0x58, 0xc9, 0x31, 0x85, 0xdb, 0x50, 0x89, 0x9c, 0x89, 0x15, - 0x5a, 0x71, 0x10, 0xca, 0xd5, 0x9c, 0x02, 0x28, 0xb0, 0x25, 0x6a, 0x56, 0x2a, 0x6e, 0x5d, 0xd1, - 0x58, 0xa5, 0x74, 0xc7, 0x16, 0x5b, 0x74, 0x15, 0xc9, 0x4c, 0xd0, 0xec, 0x87, 0x0d, 0xa7, 0x56, - 0x34, 0x90, 0x14, 0x02, 0x4a, 0xe4, 0x13, 0xc3, 0x5e, 0x78, 0xf4, 0x5b, 0xbc, 0x03, 0x14, 0x3e, - 0x3d, 0x98, 0xc6, 0x66, 0xe4, 0x8c, 0x02, 0xdf, 0x8e, 0xa4, 0x1f, 0x5e, 0x5d, 0x82, 0x07, 0x0c, - 0xd5, 0xff, 0xdb, 0x25, 0xa8, 0x66, 0xd6, 0x28, 0xb9, 0x20, 0x59, 0x13, 0x3a, 0xf9, 0x4a, 0xee, - 0x6f, 0x57, 0x24, 0x84, 0x43, 0x84, 0x8c, 0xac, 0xd8, 0xf2, 0x82, 0x93, 0x4c, 0xf0, 0x13, 0x09, - 0xe9, 0xd8, 0xe4, 0x15, 0x68, 0x8d, 0x1d, 0x0e, 0x67, 0x2e, 0x2f, 0xef, 0x27, 0x80, 0x74, 0x5e, - 0x96, 0xb2, 0xf3, 0x52, 0x63, 0xf7, 0x51, 0xee, 0x45, 0xf2, 0x16, 0xbd, 0x0b, 0x55, 0x65, 0x49, - 0xc2, 0xaf, 0x48, 0x0f, 0x47, 0x05, 0xea, 0xd8, 0xe2, 0x6d, 0x48, 0x83, 0xc3, 0x9b, 0x56, 0x64, - 0x06, 0xc7, 0xea, 0xde, 0x5c, 0x02, 0x6e, 0x46, 0xfd, 0xe3, 0xc4, 0xed, 0x88, 0xac, 0x02, 0x92, - 0x47, 0x22, 0x80, 0xa4, 0x94, 0x87, 0x70, 0x55, 0x1e, 0x61, 0xd2, 0xc4, 0x77, 0x3c, 0xdb, 0x74, - 0x6d, 0xf6, 0x9f, 0x5e, 0x36, 0x36, 0x12, 0xd4, 0x2e, 0x62, 0x3a, 0x36, 0xd9, 0x5c, 0xa4, 0x02, - 0x6e, 0xbb, 0x27, 0x4e, 0x14, 0xcb, 0x5b, 0x5e, 0x35, 0x06, 0xee, 0x10, 0x4c, 0xff, 0xbf, 0x57, - 0xa0, 0x92, 0x30, 0xaf, 0x1f, 0xea, 0xcc, 0x37, 0x61, 0x6d, 0x14, 0xf8, 0x3e, 0x7b, 0x0a, 0xa4, - 0xfd, 0x59, 0x4b, 0x81, 0x74, 0x4f, 0x57, 0x64, 0x88, 0xd4, 0x2d, 0x74, 0x8e, 0xd5, 0xb1, 0x91, - 0x62, 0x9e, 0xcb, 0xfb, 0xe8, 0xb7, 0xa0, 0x8c, 0x5c, 0xef, 0xc8, 0x8a, 0x54, 0x37, 0x27, 0x69, - 0x9c, 0xd1, 0xa3, 0xc0, 0xf3, 0xa4, 0x27, 0x83, 0x0c, 0x83, 0x9b, 0x42, 0xc4, 0x23, 0x0a, 0x84, - 0x4c, 0x8e, 0x00, 0x2b, 0xb4, 0x1f, 0x34, 0x32, 0xdc, 0x98, 0x7d, 0x01, 0xf6, 0xb9, 0xf2, 0x86, - 0x22, 0x14, 0xbf, 0x00, 0x4d, 0xf2, 0x8e, 0x49, 0xe8, 0xd8, 0x24, 0xc5, 0xc9, 0x4b, 0x0a, 0x9b, - 0x99, 0xcc, 0x07, 0x0a, 0x67, 0xac, 0x33, 0x75, 0x02, 0xc0, 0x99, 0x9a, 0x0e, 0xc3, 0xc4, 0x8a, - 0x4f, 0xd9, 0xf5, 0xbd, 0x62, 0xd4, 0x13, 0xf0, 0x01, 0x42, 0xc5, 0x27, 0x70, 0x3d, 0x74, 0x22, - 0xd7, 0x9e, 0x5a, 0x9e, 0x99, 0x1f, 0x08, 0x0e, 0xaa, 0xbb, 0xa9, 0xb0, 0xbb, 0x99, 0x01, 0xc1, - 0xe2, 0xc7, 0xd6, 0x05, 0x1d, 0x02, 0x79, 0x9e, 0xe3, 0xb9, 0xd1, 0x58, 0x46, 0x64, 0xac, 0x8f, - 0xad, 0x8b, 0x83, 0x14, 0x4a, 0x37, 0x92, 0x26, 0x9e, 0x3b, 0x13, 0xe5, 0x8f, 0xc7, 0x12, 0xe1, - 0x06, 0xa3, 0x85, 0x0e, 0x6b, 0x58, 0x20, 0xd9, 0x3b, 0x13, 0x67, 0xf6, 0xa2, 0x51, 0x1d, 0x5b, - 0x6c, 0x49, 0x08, 0xce, 0xe9, 0x5a, 0x7e, 0x42, 0xc3, 0xfe, 0xb3, 0xd2, 0x85, 0x55, 0x12, 0xb1, - 0x0b, 0x2d, 0x55, 0x8d, 0x67, 0x87, 0x1a, 0xd6, 0x3a, 0xbb, 0x0f, 0x49, 0xb0, 0x1a, 0xd3, 0x9b, - 0xc0, 0x47, 0xa9, 0x38, 0x45, 0xd6, 0x89, 0x62, 0x95, 0xd2, 0xbc, 0x12, 0xa6, 0x91, 0x13, 0x32, - 0xfb, 0x34, 0x89, 0xf1, 0x72, 0xa4, 0xbf, 0x35, 0x04, 0x13, 0x03, 0x7d, 0x86, 0x1c, 0xf8, 0x3e, - 0x68, 0x44, 0xa7, 0x4e, 0x5e, 0xa2, 0xc0, 0xa7, 0x53, 0xdb, 0x9a, 0x51, 0x47, 0xb8, 0x3c, 0x57, - 0x89, 0x02, 0x5f, 0x7c, 0x0e, 0x0d, 0xa2, 0x9c, 0xb8, 0x13, 0x07, 0xc5, 0x17, 0xe4, 0x3c, 0x27, - 0x0e, 0xe7, 0x10, 0x5b, 0xc5, 0xfb, 0x35, 0xe3, 0x1a, 0xe2, 0x0f, 0x24, 0x7a, 0x80, 0x58, 0xca, - 0xf8, 0x00, 0x36, 0x32, 0x55, 0x91, 0x43, 0xc3, 0x71, 0xc3, 0xd6, 0x93, 0xca, 0xc8, 0x51, 0xf9, - 0x08, 0x36, 0xa5, 0x8f, 0x89, 0x24, 0xe7, 0xe9, 0x44, 0x07, 0xb7, 0x65, 0x43, 0x48, 0x1c, 0xe5, - 0xe0, 0x79, 0x27, 0xde, 0x80, 0x1a, 0x59, 0x1f, 0x64, 0x84, 0x4d, 0x19, 0x3b, 0xac, 0x4a, 0x30, - 0x0e, 0x60, 0xa7, 0xff, 0x8d, 0x02, 0x88, 0xf9, 0xa9, 0xfa, 0xaa, 0x68, 0x38, 0x38, 0xd5, 0x54, - 0x28, 0x0a, 0xfc, 0x2d, 0xde, 0x85, 0xd5, 0x71, 0xc0, 0xe2, 0x54, 0xf1, 0x15, 0xb1, 0xe8, 0x56, - 0xc6, 0x01, 0x89, 0x57, 0xef, 0xc0, 0xfa, 0x28, 0xf0, 0xe5, 0xa0, 0x31, 0x77, 0xe1, 0xb5, 0x56, - 0x4f, 0xc1, 0xc8, 0x63, 0xf4, 0xff, 0xbc, 0x00, 0xf5, 0xfc, 0x02, 0x10, 0x6f, 0x53, 0x3c, 0xee, - 0x5c, 0x44, 0xef, 0x3c, 0x45, 0x7f, 0x42, 0x71, 0xba, 0x17, 0x55, 0xf1, 0x75, 0x00, 0x12, 0x12, - 0x78, 0x34, 0x64, 0x80, 0x5e, 0x82, 0xd0, 0x08, 0xdc, 0x85, 0x2a, 0x3f, 0x38, 0xc1, 0xf8, 0x12, - 0x8d, 0x16, 0xe7, 0x88, 0x88, 0xe0, 0xa3, 0x8c, 0xc7, 0x07, 0x7b, 0x74, 0x2c, 0x5e, 0xa4, 0x09, - 0x95, 0xfe, 0xf7, 0x0b, 0x00, 0xe9, 0x1a, 0xc0, 0x99, 0x78, 0xe6, 0x5c, 0xd2, 0x32, 0x55, 0x5b, - 0xec, 0x99, 0x73, 0x79, 0x20, 0xeb, 0x26, 0xdd, 0x0e, 0x23, 0x79, 0xe7, 0xb3, 0x66, 0x54, 0xd8, - 0xd3, 0x30, 0xe2, 0x20, 0x4b, 0xd2, 0xd1, 0x30, 0x53, 0x75, 0xf6, 0x2d, 0x8c, 0x28, 0x8c, 0xc6, - 0x3a, 0xe7, 0xa6, 0xa1, 0x8f, 0xdc, 0x97, 0x2a, 0x9c, 0x14, 0x3b, 0x46, 0x76, 0x14, 0x14, 0x09, - 0xb9, 0x9c, 0x94, 0x90, 0x2f, 0x61, 0xb1, 0x1b, 0x64, 0x42, 0xa8, 0x7b, 0x4a, 0xe0, 0x6f, 0xc6, - 0x31, 0x6d, 0xb0, 0x89, 0x29, 0xbe, 0xa0, 0x62, 0x48, 0xb1, 0x15, 0xfe, 0x35, 0xba, 0xab, 0x2a, - 0xc3, 0x47, 0x48, 0xb9, 0x3f, 0x09, 0x0b, 0xf1, 0x36, 0x8e, 0xb4, 0xa7, 0xb6, 0x87, 0xc4, 0x8f, - 0x6d, 0xd9, 0x58, 0x1b, 0x05, 0x1e, 0x6f, 0x0d, 0x08, 0xd4, 0xff, 0xcd, 0x65, 0x80, 0xf4, 0x10, - 0x36, 0xb7, 0x62, 0x0b, 0xf9, 0x15, 0xfb, 0x08, 0xae, 0xcb, 0xf8, 0x7e, 0xc9, 0x85, 0x2c, 0xd7, - 0x37, 0x8f, 0x2c, 0x25, 0xc2, 0x09, 0x89, 0xe5, 0x6b, 0x34, 0x1d, 0x7f, 0xdb, 0x8a, 0xc5, 0x13, - 0xe4, 0x91, 0x69, 0x9e, 0xf8, 0x72, 0xf2, 0xca, 0x29, 0xba, 0x96, 0x66, 0x1f, 0x5e, 0x4e, 0xc4, - 0x47, 0x14, 0x26, 0x29, 0x74, 0xa2, 0x53, 0x33, 0x8e, 0xb2, 0x1f, 0xe3, 0x5b, 0xf1, 0x1b, 0x12, - 0x39, 0x8c, 0x92, 0x6f, 0x7d, 0x04, 0xd7, 0x24, 0x93, 0x98, 0xa9, 0x1e, 0xbb, 0x4b, 0x4a, 0x23, - 0x74, 0xb6, 0x76, 0x34, 0xf2, 0x74, 0x32, 0xad, 0x1e, 0x46, 0x29, 0xe3, 0xc8, 0x63, 0x67, 0xc8, - 0x20, 0xd8, 0x74, 0xbc, 0x2c, 0x25, 0x17, 0x4e, 0x08, 0x1d, 0x4a, 0xb8, 0x42, 0x88, 0x19, 0xd7, - 0x1f, 0xd5, 0x1f, 0xd2, 0xc3, 0x2f, 0x14, 0xc0, 0x3c, 0xb0, 0x1d, 0x83, 0x70, 0xe2, 0x03, 0xdc, - 0xa1, 0xd3, 0x66, 0xab, 0xe8, 0xfd, 0x55, 0x69, 0xc7, 0x4e, 0x1a, 0x6a, 0x70, 0x1c, 0xff, 0xf7, - 0x40, 0x64, 0x6a, 0xae, 0xa8, 0x6b, 0x44, 0xbd, 0x9e, 0x54, 0x5b, 0x12, 0xbf, 0x03, 0x54, 0xc5, - 0xf4, 0x6a, 0xd1, 0xcc, 0x59, 0x2c, 0x22, 0xe5, 0x75, 0xa4, 0x6b, 0x69, 0xeb, 0x4c, 0x2b, 0x36, - 0xe3, 0x53, 0x87, 0x8c, 0xde, 0x7c, 0xb7, 0x68, 0x23, 0x69, 0x68, 0x33, 0x1e, 0x9e, 0x3a, 0x6d, - 0xe2, 0xb5, 0x89, 0xb7, 0xcb, 0xfa, 0xf7, 0x7b, 0xbb, 0x7c, 0x06, 0x8d, 0xfc, 0x79, 0x47, 0xa6, - 0xbb, 0x99, 0x8d, 0x6f, 0x66, 0xef, 0x6c, 0x25, 0x3d, 0xfe, 0x00, 0x36, 0x50, 0x26, 0xcc, 0xe5, - 0x95, 0x8e, 0x69, 0xeb, 0xa7, 0x56, 0x94, 0x3d, 0x20, 0xd1, 0xff, 0xd1, 0x0a, 0xd4, 0xf3, 0xc7, - 0xd2, 0x1c, 0x4f, 0x8d, 0xf7, 0xf9, 0x02, 0x49, 0x3b, 0xc9, 0x6e, 0xfe, 0x1a, 0x54, 0xf8, 0x62, - 0x17, 0x32, 0x63, 0x15, 0x7a, 0xfa, 0x4c, 0xb2, 0xe0, 0x77, 0x61, 0x75, 0x72, 0xf6, 0x03, 0x0c, - 0x72, 0xc2, 0x61, 0x4f, 0xde, 0x85, 0xd5, 0xe9, 0x59, 0x1a, 0x22, 0x7c, 0x21, 0xe9, 0xf4, 0x4c, - 0x7a, 0x3a, 0xdf, 0x94, 0x07, 0xea, 0xf2, 0xd6, 0xd7, 0x78, 0xea, 0xc5, 0xae, 0x49, 0x47, 0x02, - 0x72, 0x69, 0x5f, 0x67, 0x82, 0x0e, 0xe1, 0x29, 0x72, 0x02, 0x1d, 0x62, 0x22, 0xbf, 0x93, 0xc1, - 0x96, 0x12, 0x99, 0x65, 0xd9, 0x00, 0x0e, 0xae, 0x44, 0xcd, 0x79, 0x17, 0x34, 0xd4, 0x34, 0x3c, - 0x77, 0x14, 0x27, 0x54, 0xab, 0x44, 0xb5, 0xae, 0xe0, 0x8a, 0xf4, 0x2d, 0xa8, 0xcb, 0xbb, 0x39, - 0x8a, 0x90, 0xc3, 0x01, 0xac, 0x31, 0x54, 0x91, 0x7d, 0x06, 0x37, 0x02, 0xfb, 0x6c, 0xaa, 0xae, - 0x99, 0x59, 0xe1, 0x91, 0x1b, 0x87, 0x56, 0x12, 0x67, 0xae, 0x6c, 0x5c, 0x43, 0x34, 0x73, 0x81, - 0x66, 0x8a, 0x24, 0x5f, 0x45, 0xce, 0xa2, 0x8a, 0x07, 0xaa, 0xc7, 0x1a, 0x43, 0x55, 0xf1, 0x9f, - 0xc0, 0xf5, 0x24, 0xfe, 0x89, 0x33, 0x76, 0xfc, 0xd8, 0x0c, 0x1d, 0x72, 0xf5, 0x92, 0x51, 0xfe, - 0x37, 0x55, 0x18, 0x14, 0x42, 0x1a, 0x8c, 0x13, 0x8f, 0xe0, 0xda, 0x4c, 0x2e, 0x39, 0x82, 0x3c, - 0xf7, 0xaf, 0xe6, 0x32, 0xc9, 0xc1, 0x6c, 0xc3, 0xdd, 0x99, 0x3c, 0xb9, 0x68, 0x9e, 0x98, 0x7b, - 0x8d, 0x72, 0xdf, 0xce, 0xe5, 0xce, 0x46, 0xad, 0xc4, 0x62, 0x3e, 0x87, 0xc6, 0x4c, 0x31, 0x38, - 0x22, 0xcc, 0x28, 0x39, 0x6a, 0xe9, 0xb5, 0x5c, 0xfe, 0x67, 0xce, 0x25, 0x33, 0xd6, 0x5f, 0xc0, - 0xed, 0x99, 0x8c, 0xb9, 0xee, 0x97, 0xd7, 0xf0, 0x6e, 0xe6, 0x32, 0xf7, 0x33, 0x43, 0x81, 0x53, - 0x15, 0x3f, 0xc5, 0xc1, 0x11, 0x35, 0x92, 0x18, 0x71, 0x6f, 0xea, 0x51, 0x7c, 0xc4, 0x77, 0x18, - 0xc9, 0x67, 0xaa, 0x1b, 0xb3, 0x67, 0xaa, 0x44, 0xc8, 0x07, 0xa9, 0x6f, 0xc3, 0xba, 0x22, 0xe4, - 0x93, 0xa5, 0x88, 0x84, 0x9c, 0x65, 0x63, 0x4d, 0x92, 0xd0, 0x81, 0x52, 0xa4, 0xff, 0xd1, 0x32, - 0xd4, 0xb2, 0x3e, 0x3f, 0x3f, 0xe6, 0xd2, 0xdb, 0x4f, 0xba, 0x32, 0x2a, 0xd5, 0x3c, 0xea, 0x13, - 0x5c, 0xcd, 0xc5, 0x44, 0xcd, 0x6b, 0x4e, 0x63, 0x94, 0x68, 0x48, 0xf5, 0x0a, 0x3c, 0x15, 0x21, - 0x88, 0xf9, 0x37, 0xee, 0x5c, 0x32, 0x38, 0xd0, 0x47, 0x32, 0x00, 0x19, 0x85, 0x84, 0xa4, 0xe0, - 0x0c, 0xf3, 0x3e, 0xd0, 0x35, 0x15, 0x11, 0x92, 0x82, 0x51, 0x3c, 0x82, 0xf5, 0x34, 0xdc, 0x13, - 0x67, 0x59, 0x99, 0xcb, 0xb2, 0x96, 0xc4, 0x7a, 0x92, 0x41, 0xc6, 0xd7, 0xdc, 0xc8, 0x0c, 0x3c, - 0x5b, 0x85, 0xed, 0x5b, 0x55, 0x1e, 0x99, 0x7d, 0xcf, 0x96, 0xa1, 0xf9, 0x98, 0xc6, 0x77, 0xce, - 0x15, 0x4d, 0xe2, 0xb5, 0xd9, 0x73, 0xce, 0x25, 0xcd, 0x43, 0xb8, 0x8a, 0xcd, 0x95, 0x6b, 0x82, - 0x83, 0x75, 0x04, 0xa1, 0x5c, 0x43, 0xc8, 0xdc, 0x78, 0x09, 0x0d, 0x24, 0x22, 0x73, 0x5d, 0x33, - 0x0c, 0xce, 0x4d, 0x7f, 0x3a, 0x3e, 0x62, 0x36, 0x2f, 0x85, 0x79, 0x79, 0x5d, 0xd3, 0x08, 0xce, - 0x7b, 0x84, 0xc2, 0xfe, 0x7a, 0x00, 0x1b, 0x6a, 0x95, 0x8e, 0xe8, 0x34, 0x4b, 0xdd, 0x38, 0x5e, - 0x36, 0xd6, 0x19, 0xd1, 0x24, 0x38, 0xd2, 0xbe, 0x9b, 0xd0, 0xf2, 0xc5, 0x51, 0xa2, 0xe5, 0xd5, - 0x53, 0x8f, 0xd3, 0x5b, 0xa3, 0x48, 0xda, 0x82, 0x3b, 0x71, 0x68, 0x8d, 0xce, 0xcc, 0x57, 0x2d, - 0x1f, 0x79, 0x51, 0xf5, 0x35, 0xa2, 0x6a, 0x2e, 0x5c, 0x3c, 0x3f, 0x66, 0xf5, 0xd5, 0x7f, 0x78, - 0xf5, 0xe9, 0x7f, 0x58, 0x82, 0x8d, 0x39, 0x67, 0x29, 0x54, 0xa8, 0xd3, 0x57, 0xc2, 0xf0, 0x27, - 0x0a, 0xcf, 0x63, 0x2b, 0x1e, 0x9d, 0xa2, 0x8e, 0x76, 0xec, 0x5e, 0xa8, 0x17, 0xd2, 0x08, 0x76, - 0x40, 0x20, 0xe4, 0xa5, 0x2c, 0x57, 0xb1, 0x3b, 0x29, 0x0b, 0x39, 0x2c, 0xb2, 0xb1, 0x6f, 0xb6, - 0x0a, 0xf9, 0x51, 0x7a, 0x45, 0xc8, 0x8f, 0x5b, 0x50, 0xf1, 0x03, 0xba, 0x46, 0x3c, 0x39, 0x93, - 0x7c, 0x7b, 0xd5, 0x0f, 0xe2, 0xbe, 0x7f, 0x70, 0x86, 0x0c, 0x6a, 0x1a, 0xd1, 0x45, 0xb0, 0x23, - 0x27, 0x8c, 0x4e, 0xdd, 0xc4, 0x6d, 0x81, 0x85, 0x85, 0xab, 0xd3, 0xc8, 0xd9, 0x4f, 0x70, 0xd2, - 0xde, 0xd4, 0x84, 0x1a, 0xcd, 0x64, 0x7f, 0x14, 0x90, 0x23, 0x14, 0x3b, 0xde, 0xdf, 0x59, 0xe0, - 0x21, 0xf6, 0xcc, 0xb9, 0x6c, 0x4b, 0x2a, 0x03, 0x37, 0x04, 0x95, 0x10, 0xef, 0x52, 0x34, 0xa7, - 0x23, 0x27, 0xb5, 0x91, 0xe6, 0xd9, 0x40, 0x85, 0xb0, 0xb4, 0x0b, 0x3d, 0x83, 0x9b, 0xbc, 0x95, - 0x8c, 0x27, 0x81, 0x8f, 0xe3, 0x91, 0x66, 0x8c, 0xf2, 0x3e, 0xc5, 0x99, 0x2d, 0xec, 0x3a, 0x6d, - 0x35, 0x32, 0xc7, 0x81, 0x2a, 0x0b, 0xb7, 0x1d, 0x60, 0xa7, 0x00, 0xea, 0x30, 0x98, 0xf7, 0xcc, - 0x22, 0x2c, 0xad, 0xa7, 0x77, 0x41, 0x8b, 0x46, 0x96, 0x67, 0x85, 0x19, 0xf5, 0x99, 0x59, 0xfd, - 0x3a, 0xc3, 0x53, 0xc5, 0xe1, 0x75, 0x80, 0xf1, 0x34, 0x8a, 0x4d, 0xf2, 0x73, 0x51, 0x61, 0xa4, - 0x11, 0x42, 0x27, 0x21, 0xfa, 0x6d, 0x58, 0xe9, 0x24, 0x4e, 0x71, 0x49, 0x4c, 0x86, 0xa2, 0x7c, - 0x88, 0x28, 0x80, 0x0a, 0x7b, 0x4b, 0xec, 0x5b, 0x13, 0xf1, 0x00, 0x8a, 0x63, 0x6b, 0x22, 0x6f, - 0xeb, 0x34, 0x92, 0x2b, 0x4d, 0x8c, 0x7d, 0xb8, 0x6f, 0x4d, 0xd8, 0xce, 0x8b, 0x44, 0xb7, 0x3e, - 0x83, 0xb2, 0x02, 0xfc, 0xb4, 0x48, 0x56, 0x4b, 0x50, 0xd9, 0xc9, 0x3a, 0xb5, 0xa2, 0x2e, 0x1c, - 0x87, 0x53, 0x9f, 0x9a, 0x28, 0x9f, 0x5c, 0x19, 0x59, 0xfe, 0x50, 0x82, 0x14, 0x43, 0x5d, 0xfa, - 0x1e, 0x86, 0x7a, 0x1b, 0x40, 0x2e, 0x4f, 0xd7, 0x56, 0x72, 0x78, 0x39, 0xc4, 0x85, 0xd9, 0xb1, - 0x2f, 0x16, 0xdf, 0x31, 0x2e, 0xfd, 0xf8, 0x3b, 0xc6, 0xcb, 0x0b, 0xef, 0x18, 0xbf, 0x9d, 0x8a, - 0xde, 0xb4, 0xb3, 0xd9, 0x17, 0xf2, 0x51, 0x08, 0x25, 0x68, 0xe3, 0x8e, 0x66, 0x5f, 0x88, 0x9f, - 0x41, 0x5d, 0xb5, 0x4e, 0x96, 0x07, 0xb9, 0xb8, 0x82, 0x12, 0xc7, 0x5e, 0xb0, 0x6b, 0x71, 0x36, - 0x99, 0xdf, 0x28, 0xaa, 0x3f, 0x70, 0x8f, 0xf9, 0x6f, 0x15, 0x40, 0x48, 0x1f, 0xa6, 0xdd, 0xa9, - 0xe7, 0x0d, 0x9d, 0x0b, 0xda, 0x8f, 0x1e, 0xc0, 0x46, 0xee, 0x82, 0x4e, 0x46, 0xd3, 0x59, 0xcf, - 0xdc, 0xc8, 0x51, 0xc1, 0x9a, 0xe7, 0x42, 0xf3, 0x2e, 0x2d, 0x0c, 0xcd, 0xbb, 0x38, 0xe4, 0xef, - 0x5d, 0xa8, 0x66, 0x03, 0xdb, 0xb2, 0xea, 0x0b, 0x56, 0x12, 0xd3, 0x56, 0xff, 0x9f, 0x97, 0x00, - 0x52, 0x3f, 0xab, 0xbf, 0xec, 0x0b, 0xe2, 0x0b, 0x86, 0xa4, 0xb8, 0x68, 0x48, 0xee, 0x83, 0x96, - 0xa5, 0xcb, 0x44, 0x58, 0xae, 0xa7, 0x84, 0x4a, 0x05, 0x74, 0xa3, 0x6c, 0x10, 0x5b, 0x0a, 0x9d, - 0x26, 0xef, 0xd4, 0x32, 0x92, 0x45, 0x50, 0xc9, 0xb0, 0xca, 0x6e, 0xc4, 0x92, 0x00, 0x49, 0xaf, - 0x2a, 0x27, 0x79, 0x58, 0x04, 0xd3, 0x38, 0xb9, 0x7f, 0xb3, 0x2a, 0xa5, 0x57, 0x59, 0xd2, 0x0b, - 0x46, 0xab, 0xfb, 0x37, 0x9f, 0x42, 0xe5, 0x78, 0xea, 0x79, 0x66, 0xec, 0x5c, 0xa8, 0x3b, 0x41, - 0x8d, 0x9c, 0x8b, 0x5a, 0x66, 0x78, 0x8d, 0xf2, 0xb1, 0x4c, 0xe8, 0xff, 0xfa, 0x0a, 0x2c, 0xb3, - 0x61, 0xfc, 0x33, 0xa8, 0x44, 0xf1, 0x38, 0xce, 0xde, 0x16, 0x91, 0xae, 0x47, 0x84, 0xa7, 0xcb, - 0x1e, 0xb4, 0x6d, 0xb0, 0xcc, 0x83, 0xb4, 0xc4, 0xeb, 0x36, 0x61, 0x39, 0x8a, 0x9d, 0x49, 0x24, - 0xe3, 0xae, 0x70, 0x42, 0x6c, 0xc1, 0xb2, 0x1f, 0xd8, 0x4e, 0x94, 0x8f, 0xae, 0xd2, 0x43, 0x6d, - 0x8c, 0x11, 0x42, 0x87, 0x95, 0x64, 0xc4, 0xe7, 0x6e, 0x6c, 0x30, 0x86, 0x62, 0xb6, 0x39, 0x16, - 0x72, 0x5f, 0x15, 0xb1, 0x3a, 0x49, 0xa3, 0xda, 0x41, 0xe7, 0x69, 0xd6, 0x89, 0x8a, 0xe1, 0x2f, - 0x93, 0x62, 0x0b, 0xaa, 0xf8, 0xf3, 0x45, 0xe8, 0xc6, 0xce, 0xe0, 0xb1, 0x92, 0x29, 0x32, 0x20, - 0x71, 0x07, 0xc0, 0x76, 0x62, 0x67, 0x14, 0x0f, 0xbe, 0xf5, 0x94, 0x81, 0x30, 0x03, 0x11, 0x3f, - 0x03, 0x71, 0x64, 0x8d, 0xce, 0x4e, 0xf8, 0xc2, 0xd1, 0xb7, 0x53, 0x27, 0x74, 0x13, 0xc6, 0x5d, - 0xcd, 0x74, 0x8a, 0xb1, 0x91, 0x92, 0xfd, 0x8a, 0xa9, 0xc4, 0x75, 0x58, 0x19, 0x5b, 0x17, 0x3b, - 0xc1, 0x44, 0x5a, 0xd0, 0x65, 0x4a, 0x3c, 0x86, 0xeb, 0x28, 0xa3, 0x64, 0xa3, 0x8f, 0x48, 0xaf, - 0x40, 0xe6, 0xd0, 0x28, 0xc1, 0xa4, 0x61, 0x47, 0xe4, 0xd9, 0xf5, 0x36, 0x6c, 0x2a, 0x03, 0xb9, - 0xed, 0x4c, 0x1c, 0xdf, 0x76, 0xfc, 0x91, 0x9b, 0xc4, 0xfc, 0x9c, 0x9b, 0xfc, 0x57, 0x25, 0xf1, - 0x4e, 0x86, 0x56, 0xbc, 0x09, 0x6b, 0xf8, 0xe1, 0xd0, 0x89, 0xa7, 0xa1, 0x8f, 0x7b, 0x1f, 0x4b, - 0x14, 0x28, 0x20, 0x1a, 0x0a, 0xc6, 0x6e, 0xce, 0x32, 0x91, 0xde, 0x93, 0x5a, 0x36, 0xd6, 0x12, - 0x28, 0xf9, 0xe6, 0x3f, 0x86, 0xeb, 0xec, 0x40, 0x19, 0x7d, 0xeb, 0x49, 0x39, 0xcb, 0x4c, 0x6f, - 0x8c, 0x94, 0x8d, 0xab, 0x84, 0x1d, 0x7c, 0xeb, 0xb1, 0xa8, 0xc5, 0x7b, 0x7d, 0x1f, 0xae, 0x4f, - 0xfd, 0xd0, 0x89, 0x02, 0xef, 0x65, 0x12, 0x5c, 0xf9, 0xd4, 0x45, 0xe1, 0x58, 0xcb, 0x5e, 0xcb, - 0x3b, 0x4c, 0x68, 0x48, 0xa6, 0xdf, 0x73, 0xfd, 0xd8, 0xd8, 0x9c, 0xce, 0x03, 0x23, 0xfd, 0xf7, - 0x61, 0x2d, 0x37, 0x1b, 0xe7, 0x9c, 0x82, 0x06, 0xed, 0x6e, 0xbb, 0x35, 0xe4, 0x53, 0x7e, 0xe9, - 0xa6, 0xb2, 0x94, 0xf1, 0x67, 0x29, 0x65, 0x4e, 0xff, 0x97, 0xc9, 0x1b, 0xa6, 0x6d, 0x3c, 0x6d, - 0x93, 0x83, 0x46, 0x51, 0x2b, 0xea, 0x7f, 0x7b, 0x09, 0x36, 0x86, 0xa1, 0xe5, 0x47, 0x16, 0x6b, - 0xbd, 0x7e, 0x1c, 0x06, 0x9e, 0xf8, 0x19, 0x94, 0xe3, 0x91, 0x97, 0x5d, 0x1e, 0x77, 0x15, 0x33, - 0x9e, 0x21, 0x7d, 0x38, 0x1c, 0xb1, 0x83, 0xf3, 0x6a, 0xcc, 0x3f, 0xc4, 0x07, 0xb0, 0x7c, 0xe4, - 0x9c, 0xb8, 0xbe, 0xdc, 0x8f, 0xae, 0xcd, 0x66, 0xdc, 0x46, 0xe4, 0xde, 0x15, 0x83, 0xa9, 0xc4, - 0x47, 0xb0, 0x22, 0xcf, 0x89, 0x8a, 0xd9, 0x7b, 0x06, 0xd9, 0x0f, 0x21, 0x76, 0xef, 0x8a, 0x21, - 0xe9, 0xc4, 0x67, 0x50, 0x0e, 0x03, 0xf9, 0x00, 0x54, 0x29, 0xbb, 0xf8, 0xd3, 0x3c, 0x86, 0xc4, - 0xef, 0x5d, 0x31, 0x12, 0x5a, 0xfd, 0x21, 0xac, 0xca, 0xca, 0x62, 0x37, 0x6c, 0xb7, 0x9f, 0x76, - 0x64, 0x0f, 0xb6, 0xfa, 0xfb, 0xfb, 0x9d, 0x21, 0xc7, 0x87, 0x36, 0xfa, 0xdd, 0xee, 0x76, 0xb3, - 0xf5, 0x4c, 0x5b, 0xda, 0x2e, 0xc3, 0x0a, 0x4f, 0x5a, 0xfd, 0x5f, 0x2e, 0xc0, 0xfa, 0x4c, 0x03, - 0xc4, 0x13, 0x28, 0x91, 0xf5, 0x92, 0xbb, 0xe7, 0xde, 0xc2, 0x56, 0x66, 0xd2, 0x6c, 0x9b, 0xc1, - 0x1c, 0xfa, 0x17, 0x50, 0xcf, 0xc3, 0x33, 0x3e, 0x24, 0x6b, 0x50, 0x31, 0xda, 0xcd, 0x1d, 0xb3, - 0xdf, 0xeb, 0x7e, 0xcd, 0x7e, 0x5d, 0x94, 0x7c, 0x61, 0x74, 0xc8, 0x79, 0xe3, 0xf7, 0x40, 0x9b, - 0xed, 0x18, 0xf1, 0x14, 0xd6, 0x51, 0xf6, 0xf2, 0x1c, 0x76, 0x58, 0x4b, 0x87, 0xec, 0xce, 0x82, - 0x9e, 0x94, 0x64, 0x7c, 0xfb, 0x79, 0x94, 0x4b, 0xeb, 0xbf, 0x0f, 0x62, 0xbe, 0x07, 0xff, 0xf2, - 0x8a, 0xff, 0xbf, 0x0a, 0x50, 0x3a, 0xf0, 0x2c, 0x5f, 0xbc, 0x09, 0xcb, 0x7c, 0x64, 0x59, 0xc8, - 0xde, 0xaf, 0x23, 0x1e, 0x83, 0xd3, 0x82, 0x70, 0xe2, 0x3d, 0x28, 0xc6, 0x23, 0x15, 0x09, 0xfa, - 0xc6, 0x2b, 0x26, 0xdf, 0xde, 0x15, 0x03, 0xa9, 0xc4, 0x7d, 0x28, 0xda, 0xb6, 0x8a, 0x23, 0x96, - 0x39, 0xd0, 0xde, 0x71, 0x8e, 0xe9, 0x86, 0x25, 0xbd, 0x7d, 0x84, 0x24, 0xe2, 0x2d, 0x28, 0xda, - 0x23, 0x2f, 0x1f, 0x14, 0x8e, 0xcf, 0x9a, 0x93, 0x02, 0xed, 0x91, 0x87, 0x7a, 0x58, 0x1c, 0x5e, - 0x9a, 0xe1, 0xd4, 0xa7, 0x30, 0x1a, 0xea, 0x01, 0xaf, 0x2a, 0xca, 0x76, 0x53, 0x8a, 0xc5, 0x11, - 0xc9, 0x90, 0xb2, 0xf2, 0x85, 0x1e, 0x65, 0xbb, 0x73, 0x23, 0xf9, 0x96, 0xcf, 0xf6, 0x0a, 0xd0, - 0x33, 0xce, 0xfa, 0xfb, 0xf4, 0x18, 0x0c, 0xaa, 0xdd, 0xba, 0xfa, 0xb5, 0xe0, 0xcd, 0x4b, 0x89, - 0xd1, 0xff, 0x59, 0x11, 0xaa, 0x99, 0xfa, 0x88, 0x4f, 0xa0, 0x6c, 0xe7, 0x17, 0xe2, 0xcd, 0xb9, - 0x4a, 0x3f, 0xdc, 0x51, 0x4b, 0xd0, 0x96, 0xd3, 0x9b, 0xbc, 0xe7, 0x63, 0xf3, 0xa5, 0x15, 0xba, - 0x7c, 0x25, 0x78, 0x29, 0xeb, 0xc6, 0x3e, 0x70, 0xe2, 0xe7, 0x0a, 0xb3, 0x77, 0xc5, 0xa8, 0x45, - 0x99, 0x34, 0x59, 0xaa, 0x64, 0x93, 0x8a, 0xb9, 0xc7, 0x14, 0x19, 0xb8, 0x77, 0xc5, 0x50, 0x78, - 0x24, 0x75, 0x2e, 0x9c, 0xd1, 0x34, 0x56, 0x96, 0xaa, 0x35, 0xd5, 0x20, 0x02, 0xd2, 0xc3, 0xb4, - 0xfc, 0x53, 0x3c, 0xc2, 0x3d, 0xc8, 0xf2, 0xbc, 0x80, 0x44, 0xd8, 0xe5, 0xec, 0x31, 0xd1, 0x4e, - 0x02, 0xe7, 0x87, 0x70, 0x55, 0x4a, 0xbc, 0x0d, 0xcb, 0x41, 0x7c, 0xea, 0x28, 0xcd, 0x5a, 0x3d, - 0x2b, 0x83, 0xa0, 0x9d, 0x56, 0x17, 0x67, 0x0a, 0xa1, 0xf5, 0x3f, 0x2e, 0xc0, 0xaa, 0xec, 0x01, - 0xb1, 0x01, 0x6b, 0x83, 0xf6, 0xd0, 0x7c, 0xde, 0x34, 0x3a, 0xcd, 0xed, 0x6e, 0x5b, 0xc6, 0xb2, - 0x7b, 0x6a, 0x34, 0x7b, 0x92, 0x41, 0x1a, 0xed, 0xe7, 0xfd, 0x67, 0x6d, 0x76, 0xcc, 0xda, 0x69, - 0xf7, 0xbe, 0xd6, 0x8a, 0xec, 0xc4, 0xd8, 0x3e, 0x68, 0x1a, 0xc8, 0x2b, 0xab, 0xb0, 0xda, 0xfe, - 0xaa, 0xdd, 0x3a, 0x24, 0x66, 0x59, 0x07, 0xd8, 0x69, 0x37, 0xbb, 0xdd, 0x7e, 0x0b, 0x99, 0xe7, - 0x8a, 0x10, 0x50, 0x6f, 0x19, 0xed, 0xe6, 0xb0, 0x6d, 0x36, 0x5b, 0xad, 0xfe, 0x61, 0x6f, 0xa8, - 0xad, 0xe2, 0x17, 0x9b, 0xdd, 0x61, 0xdb, 0x48, 0x40, 0xf4, 0x58, 0xde, 0x8e, 0xd1, 0x3f, 0x48, - 0x20, 0x95, 0xed, 0x0a, 0xac, 0x8e, 0x78, 0xac, 0xf4, 0xff, 0x6c, 0x83, 0xfd, 0x13, 0xd2, 0xa9, - 0x29, 0x3e, 0x87, 0xb2, 0x6d, 0xe7, 0xc6, 0xf8, 0xf6, 0xa2, 0x29, 0xfc, 0x70, 0xc7, 0x56, 0xc3, - 0xcc, 0x3f, 0xc4, 0x1b, 0x6a, 0x21, 0x2d, 0xcd, 0x2d, 0x24, 0xb5, 0x8c, 0x7e, 0x01, 0xeb, 0xf2, - 0xad, 0x92, 0xe4, 0x68, 0x33, 0xb7, 0x4a, 0x5a, 0x84, 0xdc, 0x91, 0xb8, 0xbd, 0x2b, 0x46, 0x7d, - 0x94, 0x83, 0x88, 0x9f, 0x43, 0xdd, 0xe2, 0x03, 0xc3, 0xec, 0xd1, 0x68, 0x22, 0x9c, 0x37, 0xe9, - 0xbc, 0x30, 0xcd, 0xbe, 0x66, 0x65, 0x01, 0x38, 0x11, 0xed, 0x30, 0x98, 0xa4, 0x99, 0x97, 0x73, - 0xf7, 0x29, 0xc2, 0x60, 0x92, 0xc9, 0x5b, 0xb3, 0x33, 0x69, 0xf1, 0x19, 0xd4, 0x64, 0xcd, 0x53, - 0xe3, 0x78, 0xb2, 0x64, 0xb9, 0xda, 0x24, 0x6c, 0xef, 0x5d, 0x31, 0xaa, 0xa3, 0x34, 0x29, 0x1e, - 0xa3, 0x84, 0x9d, 0xaa, 0x26, 0xab, 0xd9, 0xb9, 0x46, 0xb5, 0x55, 0xb9, 0xc0, 0x4a, 0x52, 0xe2, - 0x23, 0x00, 0xaa, 0x27, 0xe7, 0x29, 0xe7, 0x6e, 0x1a, 0x86, 0xc1, 0x44, 0x65, 0xa9, 0xd8, 0x2a, - 0x91, 0xa9, 0x1e, 0x5b, 0xec, 0x2a, 0xf3, 0xd5, 0xe3, 0x4d, 0x3c, 0xa9, 0x1e, 0x1b, 0xef, 0x92, - 0xea, 0x71, 0x36, 0x98, 0xab, 0x9e, 0xca, 0xc5, 0xd5, 0xe3, 0x4c, 0xaa, 0x7a, 0x9c, 0xa7, 0x3a, - 0x5b, 0x3d, 0x95, 0x85, 0xaa, 0xc7, 0x39, 0x7e, 0x3e, 0xa7, 0x53, 0xd5, 0x5e, 0xa9, 0x53, 0xe1, - 0xb0, 0xe5, 0xb5, 0xaa, 0x9f, 0x43, 0x3d, 0x3a, 0x0d, 0xce, 0x33, 0x0c, 0x64, 0x2d, 0x9b, 0x7b, - 0x70, 0x1a, 0x9c, 0x67, 0x39, 0xc8, 0x5a, 0x94, 0x05, 0x60, 0x6d, 0xb9, 0x89, 0x74, 0xf7, 0xa1, - 0x9e, 0xad, 0x2d, 0xb5, 0xf0, 0xb9, 0xeb, 0x9c, 0x63, 0x6d, 0x2d, 0x95, 0xc0, 0x4e, 0x49, 0x0f, - 0x0a, 0x22, 0x69, 0xfa, 0xcf, 0xdd, 0xcf, 0x93, 0x5f, 0x82, 0xe4, 0xc8, 0x20, 0xc2, 0xb9, 0x35, - 0xf5, 0xb3, 0xd9, 0xb4, 0xec, 0xdc, 0x3a, 0xf4, 0x73, 0x19, 0x6b, 0x4c, 0x2a, 0xb3, 0xa6, 0xab, - 0x22, 0x72, 0xbe, 0x9d, 0x3a, 0xfe, 0xc8, 0x91, 0xf7, 0x70, 0x73, 0xab, 0x62, 0x20, 0x71, 0xe9, - 0xaa, 0x50, 0x90, 0x64, 0x5e, 0x27, 0xd9, 0xc5, 0xec, 0xbc, 0xce, 0x64, 0xa6, 0x79, 0x9d, 0x64, - 0x4d, 0x16, 0x54, 0x92, 0xf7, 0xea, 0xdc, 0x82, 0xca, 0x64, 0xe6, 0x05, 0x95, 0xe4, 0x7e, 0x0c, - 0x72, 0x36, 0x71, 0xe7, 0xe6, 0x6e, 0xeb, 0x72, 0xad, 0x65, 0xef, 0xc2, 0x28, 0x49, 0xe1, 0x5c, - 0x0d, 0x1d, 0xd4, 0xe1, 0xe4, 0x54, 0xb8, 0x96, 0x9d, 0xab, 0x06, 0x61, 0x92, 0xa5, 0x14, 0xa6, - 0xc9, 0xcc, 0xc7, 0x26, 0x6e, 0x1c, 0x36, 0xec, 0xf9, 0x8f, 0x1d, 0xb8, 0x71, 0x98, 0x7e, 0x0c, - 0x53, 0xe2, 0x03, 0xa0, 0x69, 0xc8, 0x59, 0x9c, 0x2c, 0xeb, 0xc6, 0x6e, 0x91, 0x19, 0xca, 0xb6, - 0xfc, 0x8d, 0x93, 0x45, 0x7e, 0x63, 0x64, 0x8f, 0x1a, 0xc7, 0xd9, 0xc9, 0xc2, 0x9f, 0x68, 0xed, - 0xb4, 0x70, 0xb2, 0x30, 0x51, 0xcb, 0x1e, 0x89, 0x07, 0x40, 0xb9, 0x89, 0xfe, 0x24, 0xf7, 0x6c, - 0x59, 0x18, 0x4c, 0x98, 0x7a, 0x15, 0x09, 0x90, 0x16, 0x5b, 0xe0, 0x05, 0xbe, 0x6a, 0xf8, 0x69, - 0xae, 0x05, 0x88, 0x48, 0x98, 0xc1, 0x28, 0x49, 0xe9, 0xff, 0xea, 0x0a, 0xac, 0x4a, 0x5e, 0x2b, - 0xae, 0xc2, 0xba, 0x64, 0xf9, 0x3b, 0xcd, 0x61, 0x73, 0xbb, 0x39, 0x40, 0x21, 0x4d, 0x40, 0x9d, - 0x79, 0x7e, 0x02, 0x2b, 0xe0, 0x3e, 0x40, 0x4c, 0x3f, 0x01, 0x2d, 0xe1, 0x3e, 0x20, 0xf3, 0xb2, - 0xfb, 0x6b, 0x51, 0xac, 0x43, 0x95, 0x33, 0x32, 0x80, 0x42, 0xeb, 0x52, 0x2e, 0x4e, 0x2f, 0x67, - 0xb2, 0xb0, 0x03, 0xf3, 0x4a, 0x9a, 0x85, 0x01, 0xab, 0x49, 0x16, 0xe5, 0xe1, 0x2c, 0xa0, 0x3e, - 0x34, 0x0e, 0x7b, 0xad, 0xf4, 0x3b, 0x15, 0x0a, 0x87, 0xca, 0xc5, 0x3c, 0xef, 0xb4, 0x5f, 0x68, - 0x80, 0x99, 0xb8, 0x14, 0x4a, 0x93, 0xe7, 0x33, 0x15, 0x42, 0xc9, 0x9a, 0xb8, 0x01, 0x57, 0x07, - 0x7b, 0xfd, 0x17, 0x26, 0x67, 0x4a, 0x9a, 0xb0, 0x26, 0x36, 0x41, 0xcb, 0x20, 0xb8, 0xf8, 0x3a, - 0x7e, 0x92, 0xa0, 0x8a, 0x70, 0xa0, 0xad, 0xd3, 0x63, 0x2a, 0x08, 0x1b, 0xf2, 0xbe, 0xab, 0x61, - 0x53, 0x38, 0x6b, 0xbf, 0x7b, 0xb8, 0xdf, 0x1b, 0x68, 0x1b, 0x58, 0x09, 0x82, 0x70, 0xcd, 0x45, - 0x52, 0x4c, 0xba, 0x5b, 0x5f, 0xa5, 0x0d, 0x1c, 0x61, 0x2f, 0x9a, 0x46, 0xaf, 0xd3, 0x7b, 0x3a, - 0xd0, 0x36, 0x93, 0x92, 0xdb, 0x86, 0xd1, 0x37, 0x06, 0xda, 0xb5, 0x04, 0x30, 0x18, 0x36, 0x87, - 0x87, 0x03, 0xed, 0x7a, 0x52, 0xcb, 0x03, 0xa3, 0xdf, 0x6a, 0x0f, 0x06, 0xdd, 0xce, 0x60, 0xa8, - 0xdd, 0x10, 0xd7, 0x60, 0x23, 0xad, 0x91, 0x22, 0x6e, 0x64, 0x2a, 0x6a, 0x3c, 0x6d, 0x0f, 0xb5, - 0x9b, 0x49, 0x35, 0x5a, 0xfd, 0x6e, 0xb7, 0x49, 0xbe, 0xd5, 0xb7, 0x90, 0x88, 0xae, 0x00, 0xc8, - 0xd6, 0xbc, 0x86, 0xf5, 0x3a, 0xec, 0x65, 0x41, 0xb7, 0x33, 0x53, 0x63, 0xd0, 0xfe, 0xd5, 0x61, - 0xbb, 0xd7, 0x6a, 0x6b, 0xaf, 0xa7, 0x53, 0x23, 0x81, 0xdd, 0x49, 0xa6, 0x46, 0x02, 0xba, 0x9b, - 0x7c, 0x53, 0x81, 0x06, 0xda, 0x56, 0xd2, 0x61, 0x87, 0x07, 0x4f, 0x8d, 0xe6, 0x4e, 0x5b, 0xd3, - 0x11, 0x62, 0xb4, 0x7b, 0xcd, 0x7d, 0x35, 0xb0, 0x6f, 0x66, 0x06, 0xf6, 0xa0, 0x33, 0x34, 0xb4, - 0x7b, 0xc9, 0x40, 0x52, 0xf2, 0x2d, 0xf1, 0x1a, 0xdc, 0xc8, 0x4e, 0x39, 0xf3, 0x45, 0x67, 0xb8, - 0x27, 0x3d, 0xf5, 0xdf, 0x66, 0x67, 0x6f, 0x42, 0xb6, 0x76, 0x5a, 0x7c, 0x25, 0x81, 0xf2, 0x62, - 0xea, 0xbe, 0x5e, 0x2a, 0xbf, 0xa1, 0xbd, 0xf1, 0x60, 0x5d, 0x76, 0x45, 0xaf, 0x47, 0xd7, 0x3d, - 0x06, 0xdb, 0x35, 0x94, 0xdc, 0x94, 0x08, 0xa2, 0x7f, 0x09, 0x22, 0xfb, 0x90, 0xb5, 0x0c, 0x68, - 0x20, 0xa0, 0x74, 0x1c, 0x06, 0x63, 0xe5, 0x26, 0x82, 0xbf, 0xc5, 0x16, 0x54, 0x27, 0xd3, 0x23, - 0xf2, 0x4d, 0x4f, 0x03, 0x59, 0x67, 0x41, 0xfa, 0xbf, 0x5f, 0x80, 0x7a, 0x5e, 0xfc, 0xa0, 0xe3, - 0x8f, 0x63, 0xd3, 0x0f, 0x62, 0x7e, 0xcf, 0x2a, 0x4a, 0xde, 0x97, 0x3e, 0xee, 0x05, 0x31, 0x3d, - 0x68, 0x15, 0xe5, 0xbc, 0xb4, 0x96, 0x66, 0xbc, 0xb4, 0x3a, 0x70, 0x35, 0xf7, 0x6e, 0x78, 0xee, - 0x35, 0xb1, 0x46, 0xf2, 0x92, 0xe9, 0x4c, 0xfd, 0x0d, 0x11, 0xcd, 0xb7, 0x49, 0x86, 0x23, 0x2f, - 0xa5, 0xe1, 0xc8, 0xf7, 0x60, 0x2d, 0x27, 0xed, 0x90, 0x75, 0xeb, 0x38, 0x5f, 0xd3, 0xb2, 0x7b, - 0xfc, 0xc3, 0xd5, 0xd4, 0xff, 0x6e, 0x01, 0x6a, 0x59, 0xd9, 0xe7, 0xb7, 0x2e, 0x89, 0xee, 0x19, - 0xca, 0xdf, 0xa6, 0x6b, 0xab, 0x67, 0xa8, 0x14, 0x88, 0x5c, 0x20, 0xab, 0x7c, 0x92, 0xb4, 0x7b, - 0x36, 0x48, 0x9a, 0x93, 0x05, 0x91, 0x67, 0xdb, 0xa9, 0x33, 0x3a, 0xdb, 0x7d, 0x86, 0x04, 0xca, - 0xb3, 0x2d, 0x81, 0xe8, 0x77, 0xa1, 0xb2, 0x7b, 0xa6, 0xae, 0x5d, 0x66, 0x5f, 0x75, 0xab, 0x70, - 0xf4, 0x73, 0xfd, 0xef, 0x17, 0xa0, 0x9e, 0xda, 0x72, 0xc8, 0xb1, 0x9e, 0xdf, 0x9b, 0xe7, 0xe9, - 0xb0, 0x64, 0x1f, 0xa5, 0xde, 0x8b, 0x4b, 0x59, 0xef, 0xc5, 0x37, 0x65, 0x61, 0xc5, 0x2c, 0xd3, - 0x4f, 0xbe, 0x25, 0x63, 0xab, 0x3f, 0x86, 0x1a, 0xfe, 0x37, 0x9c, 0x63, 0x27, 0x0c, 0x1d, 0x3b, - 0x1f, 0xaf, 0x2a, 0x25, 0xce, 0x11, 0x91, 0x96, 0x97, 0x3c, 0xb1, 0xb0, 0xf0, 0x11, 0x18, 0x7a, - 0x9c, 0xe8, 0xff, 0x28, 0x42, 0x35, 0x23, 0x49, 0xfe, 0xa8, 0xe9, 0x77, 0x1b, 0x2a, 0xe9, 0x93, - 0x24, 0x32, 0xa0, 0x75, 0x02, 0xc8, 0x8d, 0x55, 0x71, 0x66, 0xac, 0xc8, 0x89, 0x98, 0xa2, 0x68, - 0xa6, 0x4e, 0xc4, 0x94, 0xcc, 0x1b, 0xb1, 0x97, 0x7f, 0xe0, 0xb4, 0xf3, 0x63, 0xa8, 0x65, 0x2c, - 0xd0, 0xca, 0xdd, 0x70, 0x96, 0xbe, 0x9a, 0x5a, 0xa3, 0x23, 0x71, 0x0d, 0x56, 0x8e, 0xcf, 0x4c, - 0xfb, 0x88, 0x4f, 0xf0, 0x2b, 0xc6, 0xf2, 0xf1, 0xd9, 0xce, 0x11, 0x79, 0x2c, 0x1c, 0x27, 0xc2, - 0x13, 0xdb, 0x05, 0xcb, 0xc7, 0x4a, 0x44, 0xba, 0x0f, 0xab, 0xc7, 0x67, 0xd9, 0xb0, 0xb8, 0x73, - 0x5d, 0xbe, 0x72, 0x7c, 0x46, 0x91, 0x59, 0x3f, 0x84, 0x4d, 0xb9, 0x83, 0x5b, 0x91, 0x32, 0x93, - 0xe1, 0xd2, 0xe1, 0x37, 0xde, 0x36, 0x18, 0xd7, 0x8c, 0xd8, 0x48, 0x86, 0x33, 0x4e, 0x87, 0x5a, - 0x66, 0x02, 0xb2, 0x7d, 0xaf, 0x62, 0xe4, 0x60, 0xe2, 0x09, 0xd4, 0x8e, 0xcf, 0x78, 0x40, 0x87, - 0xc1, 0xbe, 0x23, 0x23, 0xbf, 0x6c, 0xce, 0x0e, 0x25, 0xdd, 0x7c, 0xc8, 0x51, 0x8a, 0xeb, 0xb0, - 0x62, 0x58, 0xe7, 0x83, 0x5f, 0x75, 0x49, 0x8c, 0xac, 0x18, 0x32, 0xc5, 0x2f, 0xc0, 0xe9, 0xff, - 0xa8, 0x00, 0xf5, 0x54, 0x0b, 0xc0, 0x45, 0x28, 0x1e, 0xa4, 0x8f, 0x3f, 0xd7, 0x15, 0x93, 0xc8, - 0x93, 0x3c, 0x1c, 0x5e, 0x4e, 0xf8, 0x31, 0xd5, 0x45, 0xef, 0x30, 0x2d, 0x3a, 0x12, 0x28, 0x2e, - 0x7c, 0x76, 0xfe, 0x29, 0x14, 0x87, 0x97, 0x13, 0xb6, 0x38, 0xe1, 0xa6, 0xc8, 0xda, 0x29, 0x6f, - 0x87, 0x74, 0xbb, 0xe8, 0x59, 0xfb, 0x6b, 0x0e, 0xc0, 0x7f, 0x60, 0x74, 0xf6, 0x9b, 0xc6, 0xd7, - 0x26, 0x02, 0x48, 0x6c, 0xd8, 0xed, 0x1b, 0xed, 0xce, 0xd3, 0x1e, 0x01, 0x4a, 0x64, 0x8f, 0x4a, - 0xab, 0xd8, 0xb4, 0xed, 0xdd, 0xb3, 0xec, 0x13, 0x36, 0x85, 0xdc, 0x13, 0x36, 0xc9, 0x6b, 0x4f, - 0xd9, 0xa7, 0x09, 0xe3, 0xe4, 0x9c, 0x42, 0x24, 0xab, 0x30, 0x59, 0xd2, 0xe2, 0x1d, 0x28, 0x1d, - 0x9f, 0x39, 0x97, 0x79, 0x55, 0x2f, 0xbf, 0x80, 0x88, 0x40, 0xff, 0xb3, 0x02, 0x88, 0x5c, 0x45, - 0x58, 0xfb, 0xf8, 0x6d, 0xeb, 0xf2, 0x39, 0x34, 0xd4, 0x3b, 0xa6, 0x44, 0x95, 0x39, 0x83, 0x90, - 0x5d, 0x7a, 0x2d, 0x48, 0x23, 0x0e, 0xa4, 0x4f, 0x45, 0x89, 0x0f, 0x81, 0x5f, 0x1d, 0xa4, 0x8b, - 0x32, 0xa5, 0x57, 0x68, 0x8a, 0x46, 0x4a, 0x93, 0x3e, 0x33, 0x98, 0x7d, 0x3e, 0x91, 0x8f, 0x2f, - 0xd6, 0xd3, 0x51, 0xa3, 0x35, 0xaf, 0xff, 0xcd, 0x02, 0x5c, 0xcd, 0x4f, 0x88, 0xbf, 0x58, 0x2b, - 0xf3, 0x6f, 0x45, 0x16, 0x67, 0xdf, 0x8a, 0x5c, 0x34, 0x9f, 0x4a, 0x0b, 0xe7, 0xd3, 0x1f, 0x14, - 0x60, 0x33, 0xd3, 0xfb, 0xa9, 0xbe, 0xf8, 0x57, 0x54, 0xb3, 0xcc, 0x93, 0x91, 0xa5, 0xdc, 0x93, - 0x91, 0xfa, 0x9f, 0x16, 0xe0, 0xfa, 0x4c, 0x4d, 0x0c, 0xe7, 0xaf, 0xb4, 0x2e, 0xf9, 0xa7, 0x25, - 0xf9, 0xd1, 0x7f, 0x19, 0xa4, 0xbe, 0x70, 0xbf, 0x98, 0x79, 0x5a, 0x92, 0xce, 0xd5, 0xe8, 0x70, - 0xf7, 0x75, 0xf9, 0x96, 0x89, 0x19, 0x5d, 0xfa, 0x23, 0x39, 0xd8, 0x15, 0x82, 0x0c, 0x2e, 0xfd, - 0x11, 0x6e, 0x52, 0x63, 0x27, 0x3c, 0x51, 0xa6, 0x3c, 0x4e, 0xe8, 0xff, 0x49, 0x01, 0x6e, 0xce, - 0xb4, 0xac, 0x39, 0x8d, 0x03, 0xe9, 0x8b, 0xf1, 0x57, 0xd4, 0xb8, 0xbb, 0x40, 0xaf, 0x2c, 0x29, - 0x27, 0x90, 0xcc, 0x05, 0x0a, 0xf9, 0x5d, 0x0d, 0x8a, 0xb6, 0x75, 0x29, 0x63, 0x1c, 0xe3, 0x4f, - 0x5c, 0xc6, 0xa7, 0xc1, 0x34, 0x94, 0x1e, 0xff, 0xf4, 0x5b, 0xff, 0x04, 0x36, 0xd2, 0xaa, 0xb7, - 0xe4, 0xbb, 0x9f, 0x77, 0xa1, 0xea, 0x3b, 0xe7, 0xa6, 0x7a, 0x15, 0x54, 0xde, 0x05, 0xf3, 0x9d, - 0x73, 0x49, 0xa0, 0xef, 0x66, 0x39, 0x24, 0x55, 0xe7, 0x26, 0x94, 0x03, 0xcf, 0xce, 0x79, 0x80, - 0x06, 0x9e, 0xad, 0x50, 0x58, 0x5a, 0xa6, 0x95, 0xab, 0xbe, 0x73, 0x4e, 0xb3, 0xf3, 0x5c, 0x96, - 0xd3, 0xb4, 0x95, 0xc7, 0xd3, 0x22, 0x77, 0xe2, 0x9b, 0x50, 0x9e, 0x84, 0xb9, 0x6e, 0x5a, 0x9d, - 0x84, 0xfc, 0xd9, 0x7b, 0xf2, 0xa6, 0xd9, 0xab, 0x3c, 0xe6, 0xf8, 0xee, 0x99, 0x06, 0xc5, 0x49, - 0x10, 0x49, 0xa7, 0x1e, 0xfc, 0xa9, 0x7f, 0x2a, 0x99, 0x23, 0xe9, 0x83, 0xfc, 0x65, 0x0d, 0x8a, - 0xae, 0x7d, 0x41, 0x1f, 0x5e, 0x33, 0xf0, 0x27, 0xc9, 0x77, 0xce, 0xb7, 0xf2, 0xb2, 0x1b, 0xfe, - 0xd4, 0xb7, 0xa1, 0x6a, 0xe4, 0x94, 0xdf, 0x5a, 0xc6, 0x8e, 0x14, 0xe5, 0xdf, 0x8c, 0x49, 0x3b, - 0xc8, 0xa8, 0xa6, 0x66, 0xa4, 0x48, 0x8f, 0x24, 0x3b, 0x7c, 0x6e, 0x85, 0xa3, 0x53, 0x2b, 0xec, - 0x3a, 0xfe, 0x49, 0x7c, 0x8a, 0x5d, 0xce, 0xe6, 0xdd, 0x6c, 0x17, 0x02, 0x83, 0xd4, 0x74, 0xc0, - 0x5e, 0xf4, 0x88, 0x5c, 0x3a, 0x04, 0x54, 0x7c, 0xe7, 0x5c, 0xe6, 0x7f, 0x1d, 0x00, 0xfb, 0x5f, - 0xa2, 0xe5, 0x6d, 0x9b, 0xc0, 0xb3, 0x19, 0xad, 0x6f, 0xc8, 0xf6, 0xca, 0x18, 0xdd, 0x3b, 0xce, - 0xb1, 0xee, 0xc9, 0x91, 0xe7, 0x06, 0xc9, 0x4e, 0xf8, 0xad, 0x86, 0x51, 0xbc, 0x01, 0x35, 0x65, - 0xa9, 0xa0, 0x67, 0x8a, 0xf8, 0xf3, 0x55, 0x05, 0xeb, 0x4d, 0xc7, 0xfa, 0x7f, 0x5a, 0x82, 0x5a, - 0x93, 0x7d, 0x44, 0x27, 0x97, 0xfd, 0x49, 0x2c, 0x7e, 0x1f, 0xae, 0x51, 0x7c, 0x7c, 0x0e, 0x55, - 0x40, 0xae, 0x99, 0xec, 0x94, 0xc8, 0x9d, 0xf8, 0x20, 0xd3, 0x89, 0x32, 0xcb, 0xc3, 0xc1, 0x99, - 0x3b, 0xe1, 0xe8, 0x05, 0x1d, 0xfb, 0x82, 0x7c, 0x14, 0xd9, 0x93, 0x82, 0x42, 0xe9, 0xe7, 0x11, - 0x14, 0xaa, 0x19, 0x8b, 0x9f, 0x9c, 0xc9, 0x62, 0xa5, 0x53, 0x0e, 0x02, 0x0f, 0xce, 0x98, 0x26, - 0x75, 0x61, 0x9a, 0xdb, 0x96, 0xa5, 0x0b, 0x53, 0x3a, 0xbf, 0x07, 0xb0, 0x21, 0xc3, 0xf9, 0xd3, - 0x2b, 0x82, 0xe6, 0x28, 0x98, 0x5c, 0xca, 0x83, 0xda, 0x77, 0x5e, 0x51, 0xd5, 0x0e, 0x93, 0x22, - 0x88, 0xeb, 0xb9, 0x1e, 0xe5, 0xa1, 0xe2, 0x39, 0x08, 0xec, 0xd2, 0x89, 0x37, 0xc5, 0xfd, 0x4c, - 0xbd, 0x5f, 0xc8, 0xae, 0xe3, 0xf7, 0x17, 0x94, 0xda, 0x73, 0xce, 0x0f, 0x88, 0x56, 0x16, 0xc2, - 0xc5, 0x6a, 0xfe, 0x0c, 0xf8, 0x56, 0x1b, 0x6e, 0xbc, 0xa2, 0xaf, 0x7e, 0xc8, 0xc9, 0xa4, 0x9c, - 0x71, 0x32, 0xb9, 0xb5, 0x0d, 0x9b, 0x8b, 0xda, 0xf1, 0x93, 0xca, 0x68, 0xc1, 0xb5, 0x85, 0xb5, - 0xfe, 0x29, 0x85, 0xe8, 0x7f, 0x50, 0x07, 0x48, 0x97, 0x53, 0x4e, 0x82, 0x2e, 0xcc, 0x48, 0xd0, - 0x3f, 0xc9, 0x2b, 0xf0, 0x13, 0xa8, 0xe3, 0x38, 0x66, 0x82, 0xae, 0x2e, 0x8e, 0xf6, 0x5a, 0x43, - 0xaa, 0x61, 0x1a, 0x6e, 0x6f, 0xde, 0xbb, 0xa5, 0xb4, 0xd0, 0xbb, 0xe5, 0x63, 0x58, 0xe5, 0xd3, - 0x41, 0x35, 0xa8, 0x37, 0x66, 0x59, 0xc3, 0x43, 0x19, 0xe4, 0x46, 0xd1, 0x89, 0x36, 0xd4, 0x93, - 0xf8, 0x14, 0xd9, 0x78, 0x8f, 0x77, 0xe6, 0x73, 0x2a, 0x32, 0x7e, 0x18, 0xd1, 0xca, 0x26, 0x33, - 0x02, 0x77, 0x3c, 0x96, 0x26, 0x6b, 0x12, 0xb8, 0x57, 0xb3, 0x02, 0xf7, 0x70, 0xcc, 0x86, 0x6a, - 0x14, 0xb8, 0x3f, 0x80, 0xab, 0xd2, 0x4f, 0x18, 0x33, 0x60, 0x77, 0x12, 0x3d, 0xdf, 0xea, 0xd2, - 0x64, 0xfc, 0xf8, 0x31, 0xa9, 0xa3, 0x48, 0xfe, 0x15, 0x6c, 0xf2, 0x13, 0x07, 0xf4, 0x9a, 0xfc, - 0x28, 0xf0, 0x3a, 0xb6, 0x39, 0xb6, 0x26, 0x52, 0x0f, 0x78, 0x67, 0xae, 0xb2, 0xfc, 0xc2, 0xc1, - 0xf0, 0xc8, 0x23, 0x3f, 0xeb, 0xc4, 0x07, 0x6a, 0x63, 0x34, 0x0b, 0x9f, 0x71, 0x45, 0x80, 0x39, - 0x57, 0x84, 0x59, 0xcd, 0xa0, 0xba, 0x40, 0x33, 0x48, 0xe5, 0xfb, 0x5a, 0x56, 0xbe, 0x17, 0xef, - 0xc3, 0xaa, 0x8c, 0x1b, 0x28, 0x8d, 0xd5, 0x62, 0x7e, 0x91, 0x19, 0x8a, 0x04, 0xbf, 0xa4, 0x1c, - 0x63, 0x28, 0x46, 0x75, 0x9d, 0xbf, 0x94, 0x85, 0x89, 0x6d, 0x69, 0xa9, 0x4d, 0x7c, 0xc2, 0xa5, - 0x61, 0xfa, 0x56, 0xa6, 0xe0, 0x04, 0x27, 0x4d, 0x09, 0x33, 0x39, 0x6e, 0xfd, 0xd1, 0x2a, 0xac, - 0x48, 0xf7, 0x86, 0x07, 0x50, 0xb2, 0x43, 0x79, 0x7f, 0x25, 0x51, 0x65, 0xf2, 0x72, 0xe5, 0xde, - 0x15, 0x83, 0x68, 0xc4, 0x43, 0x58, 0xb1, 0x6c, 0xdb, 0x3c, 0x3e, 0xcb, 0x1f, 0xa2, 0xcf, 0xc8, - 0xfc, 0x7b, 0x57, 0x8c, 0x65, 0x8b, 0x84, 0xff, 0xcf, 0xa1, 0x82, 0xf4, 0xd9, 0x68, 0xc1, 0x8d, - 0x05, 0x59, 0xd4, 0x41, 0x41, 0xd9, 0x52, 0x92, 0xfa, 0xef, 0xe6, 0x8f, 0x23, 0x4a, 0x73, 0x0d, - 0x9c, 0x11, 0x2d, 0x67, 0x0e, 0x26, 0xfe, 0x1a, 0xb0, 0x7d, 0x3a, 0x11, 0x27, 0x96, 0xb3, 0xe7, - 0xb5, 0x73, 0xc2, 0xc7, 0xde, 0x15, 0x83, 0x37, 0x55, 0x25, 0x8c, 0x7c, 0xaa, 0x8e, 0x0a, 0x88, - 0x3d, 0xaf, 0x2c, 0xee, 0x19, 0xe4, 0xd1, 0xc9, 0x79, 0x01, 0x31, 0x6c, 0xcc, 0x66, 0x27, 0xee, - 0x9e, 0xab, 0x73, 0xd9, 0x12, 0x91, 0x83, 0xb2, 0x25, 0xf2, 0xc7, 0x13, 0xa8, 0xb2, 0xe5, 0x98, - 0xf3, 0x95, 0xe7, 0xba, 0x36, 0x95, 0x18, 0xe8, 0x2c, 0x32, 0x95, 0x1f, 0x5a, 0xaa, 0x9d, 0xa1, - 0x93, 0x3d, 0xee, 0xb9, 0xbd, 0xb0, 0xa3, 0x8c, 0xe4, 0xe4, 0x87, 0x1b, 0x6b, 0x70, 0x1e, 0xd1, - 0x85, 0x4d, 0x79, 0x2e, 0xc2, 0xd2, 0x81, 0xda, 0xd0, 0x61, 0x6e, 0xbc, 0x72, 0xe2, 0xc3, 0xde, - 0x15, 0x43, 0x58, 0xf3, 0x42, 0x45, 0x0b, 0x36, 0x54, 0x95, 0x68, 0xdb, 0xcf, 0x78, 0xc0, 0x65, - 0x9b, 0x94, 0x0a, 0x05, 0x7b, 0x57, 0x8c, 0x75, 0x2b, 0x0f, 0x12, 0x1d, 0xb8, 0xaa, 0x0a, 0xa1, - 0xf3, 0x81, 0x8c, 0xf3, 0x7b, 0x7e, 0x14, 0xb3, 0x82, 0xc4, 0xde, 0x15, 0x63, 0xc3, 0x9a, 0x93, - 0x2e, 0xf6, 0x55, 0x7d, 0xb2, 0x92, 0x2b, 0xaf, 0xc4, 0xbb, 0x0b, 0xbb, 0x29, 0x15, 0xa3, 0x93, - 0x9a, 0x65, 0x24, 0xeb, 0x5f, 0xa9, 0xce, 0xca, 0x3b, 0xfb, 0xca, 0xe3, 0xa4, 0xd7, 0xe7, 0x4a, - 0xcc, 0xfa, 0xfa, 0x26, 0x3d, 0x96, 0x83, 0xa6, 0xfe, 0x1c, 0xb7, 0x0c, 0xb8, 0xbe, 0x98, 0x69, - 0x65, 0x77, 0xae, 0x12, 0xef, 0x5c, 0x7a, 0x76, 0xe7, 0x9a, 0x0d, 0x63, 0x9f, 0xd9, 0xc7, 0x7e, - 0x09, 0x6b, 0x39, 0xae, 0x2d, 0xaa, 0xb0, 0xaa, 0x5e, 0x00, 0xa7, 0xd8, 0x20, 0xad, 0xfe, 0xc1, - 0xd7, 0x5a, 0x01, 0xc1, 0x9d, 0xde, 0x60, 0xd8, 0xec, 0x0d, 0xb5, 0x25, 0x4e, 0x1c, 0x74, 0x9b, - 0xad, 0xb6, 0x56, 0xd4, 0xff, 0x61, 0x11, 0x2a, 0xc9, 0x69, 0xe3, 0x6f, 0x6f, 0x13, 0x5c, 0x7c, - 0x85, 0x7d, 0x46, 0xe1, 0x65, 0xdf, 0xff, 0x92, 0x8a, 0x59, 0x9d, 0x55, 0x2b, 0xa3, 0xf9, 0xa0, - 0xa4, 0xcb, 0x3f, 0x32, 0x28, 0x69, 0xf6, 0xee, 0xd6, 0x4a, 0xfe, 0xee, 0xd6, 0xcc, 0x83, 0xf9, - 0xab, 0xf4, 0xd6, 0x72, 0xf6, 0xc1, 0xfc, 0xeb, 0xb0, 0xe2, 0x46, 0xcf, 0x5d, 0xe7, 0x5c, 0x7a, - 0xb2, 0xcb, 0x54, 0x7e, 0xd3, 0x87, 0x1f, 0xd8, 0xf4, 0x7f, 0xcc, 0x06, 0xf2, 0x08, 0x36, 0x8f, - 0xcf, 0x92, 0x17, 0x9e, 0x53, 0x13, 0x53, 0x8d, 0xaa, 0xb4, 0x10, 0x27, 0xde, 0x81, 0x95, 0x58, - 0x1d, 0x84, 0x16, 0x17, 0x9c, 0x0d, 0x1b, 0x12, 0xad, 0xff, 0x51, 0x01, 0x20, 0x3d, 0x87, 0xfb, - 0x0b, 0x1b, 0xb4, 0x33, 0x36, 0xc3, 0xe2, 0xf7, 0xd8, 0x0c, 0x7f, 0xe8, 0x01, 0x9f, 0x6f, 0xa1, - 0x92, 0x9c, 0xbc, 0xfe, 0xf6, 0x13, 0xeb, 0x27, 0x7d, 0xf2, 0x5f, 0x50, 0xc6, 0xfd, 0xe4, 0xe8, - 0xf2, 0x2f, 0xda, 0x17, 0xb9, 0xcf, 0x17, 0x7f, 0xe0, 0xf3, 0x17, 0x6c, 0x61, 0x4f, 0x3e, 0xfe, - 0x97, 0xbc, 0x9a, 0xb2, 0x13, 0xbd, 0x94, 0x9b, 0xe8, 0xfa, 0x54, 0x1e, 0x13, 0xfc, 0xc5, 0x3f, - 0xfd, 0x93, 0x1a, 0xfc, 0xbf, 0x17, 0x94, 0x2d, 0x3b, 0x79, 0x94, 0xfb, 0x95, 0x72, 0xf4, 0x62, - 0x73, 0xfc, 0x4f, 0xf9, 0xdc, 0xf7, 0x5a, 0xea, 0x4a, 0xdf, 0x67, 0xa9, 0x7b, 0x47, 0xbd, 0x69, - 0xb0, 0xfc, 0x2a, 0x2b, 0x9d, 0x7c, 0xd6, 0xe0, 0x2e, 0x54, 0xb3, 0xb6, 0x39, 0x36, 0xca, 0xb0, - 0x51, 0x85, 0xcd, 0x72, 0xba, 0xd4, 0x1b, 0xb8, 0xbd, 0x9b, 0xaa, 0x5c, 0x19, 0xcb, 0x87, 0x12, - 0xfa, 0x5f, 0x67, 0x8e, 0xfa, 0xdb, 0x76, 0xc9, 0xf7, 0x9b, 0x69, 0xf4, 0xff, 0xb7, 0x00, 0x6b, - 0x39, 0x4f, 0x8a, 0xdf, 0xe2, 0x13, 0x0b, 0xf9, 0x72, 0xf1, 0xff, 0x47, 0x7c, 0x39, 0xe7, 0xe0, - 0x5d, 0xce, 0x3b, 0x78, 0x23, 0xbb, 0xab, 0xe5, 0xb4, 0xa2, 0x45, 0xfa, 0x53, 0x61, 0xa1, 0xfe, - 0x74, 0x07, 0xc0, 0x1a, 0xd1, 0xbd, 0xb1, 0xce, 0x0e, 0xfb, 0x53, 0xaf, 0x19, 0x19, 0x88, 0xf8, - 0x02, 0x6e, 0x4a, 0xa3, 0x09, 0xf7, 0x4f, 0x70, 0x6c, 0x2a, 0xac, 0x2d, 0x8d, 0x10, 0xd7, 0x99, - 0x80, 0x46, 0xb7, 0x7f, 0xdc, 0x54, 0x58, 0xbd, 0x03, 0x6b, 0x39, 0x17, 0x15, 0xdc, 0x5b, 0x4e, - 0xbc, 0xe0, 0xc8, 0xf2, 0x64, 0x5d, 0x64, 0x4a, 0x6c, 0xc1, 0xf2, 0xf9, 0xa9, 0x13, 0x3a, 0x0b, - 0x9e, 0x9e, 0x65, 0x84, 0xfe, 0x73, 0xa8, 0x65, 0xdd, 0xe5, 0xc4, 0xfb, 0xb0, 0xec, 0xc6, 0xce, - 0x58, 0x99, 0x83, 0xae, 0xcf, 0x7b, 0xd4, 0x75, 0x62, 0x67, 0x6c, 0x30, 0x91, 0xfe, 0xc7, 0x05, - 0xd0, 0x66, 0x71, 0x14, 0x8e, 0xe6, 0x32, 0x8a, 0x9d, 0xb1, 0xaa, 0x0c, 0xa7, 0x32, 0x95, 0x5c, - 0xca, 0x55, 0x52, 0x59, 0xcd, 0x8a, 0x19, 0xab, 0xd9, 0x96, 0x12, 0x4a, 0xe6, 0xaf, 0x14, 0x31, - 0x42, 0xbc, 0x0d, 0xe5, 0xd0, 0xa1, 0x40, 0x37, 0xf6, 0x82, 0xdb, 0x6c, 0x09, 0x4e, 0xff, 0xc3, - 0x02, 0xac, 0x4a, 0xdf, 0xbe, 0x85, 0xf6, 0xb9, 0x77, 0x61, 0x35, 0x1a, 0x9d, 0x3a, 0x63, 0x4b, - 0xbd, 0xe3, 0x33, 0xe7, 0x87, 0xad, 0xf0, 0xe2, 0x0e, 0x7b, 0x3c, 0xe6, 0xed, 0x75, 0x07, 0x9e, - 0xe5, 0x1b, 0x04, 0xc7, 0xa9, 0xc6, 0x76, 0x5a, 0xbe, 0x1a, 0xc4, 0xef, 0x26, 0x00, 0x81, 0xe8, - 0xf2, 0x8f, 0xfe, 0xbb, 0xb0, 0x2a, 0x7d, 0x07, 0x17, 0x56, 0xe5, 0x0e, 0x94, 0xac, 0xf0, 0x24, - 0x5a, 0x30, 0x58, 0x04, 0xd7, 0xb7, 0x00, 0x52, 0x67, 0xc2, 0x45, 0x25, 0xe8, 0x0f, 0xa0, 0xac, - 0xfc, 0x07, 0x71, 0xfe, 0xa5, 0x9f, 0x96, 0x97, 0x79, 0xb3, 0x95, 0xf1, 0xe4, 0x73, 0xf2, 0xdd, - 0x60, 0x74, 0x46, 0x47, 0x06, 0x1f, 0x02, 0xdd, 0x6c, 0x1e, 0xce, 0x3d, 0x30, 0x91, 0x90, 0xf1, - 0x65, 0x01, 0x45, 0x24, 0x1e, 0x40, 0xc2, 0x2f, 0x7f, 0xc8, 0x5a, 0xa1, 0x37, 0xd5, 0x1d, 0x78, - 0x9a, 0x65, 0x8f, 0xa5, 0xf5, 0xb8, 0x4b, 0x2f, 0xa5, 0x15, 0xb2, 0xcf, 0xae, 0xe6, 0xea, 0x64, - 0x64, 0xc8, 0xf4, 0x3a, 0xd4, 0xb2, 0x4e, 0x4f, 0x7a, 0x13, 0x36, 0xf6, 0x9d, 0xd8, 0x42, 0xfe, - 0xa3, 0xc2, 0xee, 0xf3, 0xfc, 0xc5, 0x1f, 0xf9, 0xf9, 0x3b, 0x4b, 0x67, 0x30, 0x91, 0xfe, 0x0f, - 0x4b, 0xa0, 0xcd, 0xe2, 0xbe, 0x2f, 0x1e, 0xc0, 0x5d, 0xa8, 0xf2, 0x13, 0x3b, 0x59, 0x4b, 0x22, - 0x30, 0x28, 0x73, 0x5b, 0x84, 0x9f, 0x9f, 0x49, 0x1f, 0xda, 0xdf, 0xa3, 0xb4, 0xb8, 0xc1, 0x97, - 0xbf, 0xbd, 0x60, 0x44, 0xd3, 0xba, 0x46, 0x77, 0xbd, 0xbb, 0xc1, 0x88, 0xc2, 0x0c, 0x48, 0x83, - 0x07, 0x7b, 0xe2, 0xd6, 0x8c, 0xb2, 0xb4, 0x72, 0xd0, 0x29, 0xa6, 0xbc, 0x43, 0x12, 0x47, 0x32, - 0x16, 0x58, 0x99, 0x01, 0xc3, 0x48, 0x3d, 0x1a, 0x3e, 0xf2, 0x63, 0x19, 0xe5, 0x66, 0x25, 0x0c, - 0xce, 0x5b, 0x3e, 0x45, 0x19, 0xa0, 0x27, 0x3b, 0x11, 0x53, 0x4e, 0x9f, 0x6d, 0x47, 0x14, 0x85, - 0x96, 0xe1, 0xb8, 0xa8, 0xfc, 0x60, 0x56, 0x45, 0xbe, 0x94, 0x26, 0x81, 0xc9, 0x7b, 0x84, 0xbc, - 0xff, 0x65, 0xe2, 0x07, 0x01, 0x83, 0x88, 0xe0, 0x26, 0x94, 0xbf, 0x0b, 0x7c, 0x87, 0x0c, 0x27, - 0x55, 0xaa, 0xd5, 0x2a, 0xa6, 0xf7, 0xad, 0x09, 0x6e, 0x04, 0x1e, 0x85, 0x9d, 0xe3, 0x5b, 0x92, - 0x9c, 0xd0, 0xff, 0x87, 0x02, 0x6c, 0xce, 0xf6, 0x35, 0x4d, 0xa3, 0x1a, 0x94, 0x5b, 0xfd, 0xae, - 0xd9, 0x6b, 0xee, 0xb7, 0xb5, 0x2b, 0x62, 0x1d, 0xaa, 0xfd, 0xed, 0x2f, 0xdb, 0xad, 0x21, 0x03, - 0x0a, 0x14, 0x01, 0x73, 0x60, 0xee, 0x75, 0x76, 0x76, 0xda, 0x3d, 0xd6, 0x28, 0xfa, 0xdb, 0x5f, - 0x9a, 0xdd, 0x7e, 0x4b, 0x2b, 0x22, 0x4e, 0xb9, 0x83, 0x0c, 0xb4, 0x12, 0x39, 0x8b, 0xd0, 0xa5, - 0x00, 0x4c, 0x2e, 0xb3, 0xb7, 0xfb, 0x8b, 0x81, 0xd9, 0xea, 0x0d, 0xb5, 0x15, 0x4c, 0xf5, 0x0e, - 0xbb, 0x5d, 0x4a, 0x91, 0x5b, 0x6b, 0xab, 0xbf, 0x7f, 0x60, 0xb4, 0x07, 0x03, 0x73, 0xd0, 0xf9, - 0x75, 0x5b, 0x2b, 0xd3, 0x97, 0x8d, 0xce, 0xd3, 0x4e, 0x8f, 0x01, 0x15, 0xb1, 0x0a, 0xc5, 0xfd, - 0x4e, 0x8f, 0x23, 0x7f, 0xee, 0x37, 0xbf, 0xd2, 0xaa, 0xf8, 0x63, 0x70, 0xb8, 0xaf, 0xd5, 0x44, - 0x05, 0x96, 0xbb, 0xed, 0xe7, 0xed, 0xae, 0xb6, 0xa6, 0xff, 0xf3, 0xa2, 0x92, 0x88, 0xc9, 0xdf, - 0xeb, 0xc7, 0x48, 0x81, 0x8b, 0x4e, 0x59, 0x93, 0x4e, 0x2b, 0x66, 0x3a, 0x4d, 0xbc, 0x01, 0x35, - 0xb9, 0x29, 0x64, 0xcf, 0xc9, 0xaa, 0x12, 0x46, 0x53, 0xee, 0x4d, 0x58, 0x4b, 0x5c, 0x24, 0x32, - 0x0f, 0x7d, 0xd7, 0x14, 0x70, 0xc1, 0x71, 0xcd, 0xca, 0x82, 0xe3, 0x9a, 0x89, 0x1b, 0xa3, 0xe2, - 0x8e, 0x3c, 0x97, 0x67, 0x52, 0x05, 0x21, 0xcf, 0x89, 0xd7, 0xbe, 0x06, 0x94, 0x30, 0xa7, 0xbe, - 0x7c, 0xa2, 0xa8, 0x62, 0x94, 0x11, 0x70, 0xe8, 0xbb, 0xf1, 0xac, 0x8b, 0x46, 0x65, 0xce, 0x45, - 0x23, 0xbb, 0x39, 0x43, 0x7e, 0x73, 0x7e, 0x3d, 0xd9, 0x23, 0x11, 0x59, 0xa5, 0xb3, 0x8a, 0x4a, - 0xb2, 0x0b, 0x8a, 0xf7, 0x41, 0x8c, 0xa6, 0x21, 0x3d, 0xf9, 0x91, 0x21, 0xe3, 0xa7, 0x85, 0x34, - 0x89, 0x49, 0x76, 0x45, 0x8a, 0xbc, 0x92, 0xa7, 0x26, 0xf5, 0xbc, 0x62, 0xd4, 0xf3, 0xa4, 0xe2, - 0x21, 0x5c, 0x95, 0x73, 0x3b, 0xd7, 0xb7, 0x32, 0x68, 0x03, 0xa3, 0x9a, 0x69, 0x0f, 0xeb, 0xbf, - 0x03, 0x65, 0xe5, 0xda, 0xf7, 0xfd, 0xc2, 0xee, 0x82, 0x71, 0xd5, 0xff, 0xc3, 0x25, 0xa8, 0x24, - 0x8e, 0x7e, 0x3f, 0x6a, 0x76, 0xbc, 0x86, 0x72, 0x6a, 0x74, 0x96, 0x65, 0x31, 0x65, 0x04, 0xa8, - 0x91, 0x92, 0x77, 0xf9, 0xa6, 0xa1, 0xab, 0x24, 0x36, 0x86, 0x1c, 0x86, 0x2e, 0xc5, 0xf5, 0x76, - 0xfd, 0x4c, 0x78, 0x85, 0x8a, 0x51, 0x46, 0x00, 0x2d, 0xb4, 0x9b, 0x40, 0xbf, 0x29, 0x27, 0x4f, - 0x92, 0x55, 0x4c, 0x63, 0xbe, 0xeb, 0x89, 0xfe, 0x27, 0x43, 0x93, 0xc5, 0x89, 0x60, 0x21, 0x7d, - 0x8c, 0xd8, 0xb3, 0x42, 0xa6, 0xf0, 0x3b, 0x14, 0xd0, 0x87, 0xea, 0x28, 0x67, 0x04, 0x02, 0x54, - 0x1d, 0x33, 0xc3, 0x55, 0x99, 0x1d, 0xd5, 0xd9, 0x39, 0x0d, 0x73, 0x73, 0x5a, 0x8f, 0x61, 0x55, - 0x3a, 0x3b, 0x7e, 0x7f, 0x87, 0x7f, 0x6f, 0x57, 0x69, 0x50, 0xb4, 0x3c, 0x75, 0x5b, 0x1e, 0x7f, - 0xce, 0x54, 0xac, 0x34, 0x53, 0x31, 0xfd, 0xdf, 0x59, 0x02, 0x48, 0x9d, 0x26, 0xc5, 0x07, 0x33, - 0x0e, 0xda, 0x85, 0xb9, 0x6d, 0x7f, 0xc6, 0x2f, 0x7b, 0x26, 0xd0, 0xfd, 0xd2, 0x8f, 0x08, 0x74, - 0xff, 0x08, 0xd6, 0xa2, 0x70, 0xf4, 0x83, 0x36, 0xfc, 0x6a, 0x14, 0x8e, 0x12, 0x13, 0xfe, 0x87, - 0x80, 0x49, 0x7a, 0x04, 0x27, 0x55, 0x54, 0xe7, 0xa4, 0x96, 0x4a, 0x14, 0x8e, 0xfa, 0x47, 0xdf, - 0xec, 0xf0, 0x05, 0x4a, 0x3b, 0x8a, 0xcd, 0x45, 0x5c, 0x62, 0xdd, 0x8e, 0xe2, 0x9d, 0x2c, 0xa3, - 0xb8, 0x07, 0x75, 0xa4, 0x9d, 0x63, 0x16, 0x35, 0x3b, 0x4a, 0x0f, 0x94, 0xf4, 0x7f, 0x45, 0x1d, - 0xcc, 0xcf, 0x98, 0x87, 0xc5, 0x67, 0x52, 0x11, 0xcf, 0x08, 0x11, 0x8d, 0x45, 0xd6, 0x64, 0xbe, - 0x63, 0x9d, 0x90, 0x8a, 0x27, 0xb0, 0x96, 0xe0, 0x76, 0x9c, 0x63, 0x25, 0x03, 0xa9, 0x17, 0x55, - 0x32, 0x28, 0x23, 0x4f, 0x88, 0x42, 0x51, 0xfa, 0x0c, 0x11, 0xae, 0xc0, 0xe4, 0xd2, 0x52, 0x45, - 0x5e, 0x47, 0x7a, 0x02, 0x37, 0x5e, 0x61, 0x47, 0x53, 0xe7, 0x92, 0x32, 0x6e, 0x82, 0x0c, 0xc2, - 0xe6, 0x3b, 0xe7, 0x1c, 0x37, 0x41, 0xf7, 0xe1, 0xea, 0x82, 0xf7, 0xc3, 0xc5, 0x16, 0xb9, 0x6c, - 0xa5, 0xef, 0xa5, 0x4b, 0xd9, 0x6a, 0x94, 0x3e, 0x92, 0xfe, 0x29, 0xac, 0x3b, 0x9e, 0x7b, 0xe2, - 0x1e, 0xb9, 0x14, 0x1b, 0x7c, 0x14, 0x78, 0x8b, 0x5e, 0xd3, 0x37, 0xea, 0x19, 0xa2, 0x56, 0xe0, - 0xe9, 0xff, 0x5a, 0x21, 0xf7, 0x18, 0xa0, 0x7a, 0x0e, 0x8c, 0x1f, 0x03, 0x94, 0xaf, 0x0e, 0x17, - 0x0c, 0xfa, 0x8d, 0x2b, 0x53, 0x3e, 0x34, 0x2b, 0x1f, 0xf7, 0xe2, 0x94, 0xf8, 0x10, 0x36, 0x65, - 0x7c, 0x73, 0x8a, 0x2e, 0x66, 0x4e, 0x9c, 0xd0, 0x0c, 0x83, 0x73, 0x9a, 0x58, 0x05, 0x43, 0xc6, - 0x3e, 0xa7, 0x20, 0x63, 0x07, 0x4e, 0x68, 0x04, 0xe7, 0xa2, 0x41, 0x52, 0x89, 0x33, 0x8a, 0xd5, - 0x19, 0xb3, 0x4a, 0xea, 0xbf, 0x07, 0x57, 0x17, 0x5c, 0xe3, 0x13, 0x6f, 0x29, 0x3d, 0xef, 0x15, - 0x97, 0x76, 0x17, 0xea, 0x96, 0x4b, 0x33, 0xba, 0xe5, 0x83, 0x7f, 0xab, 0x00, 0x1b, 0x83, 0x38, - 0x74, 0xfd, 0x93, 0xae, 0x1b, 0x3b, 0xa1, 0xe5, 0xed, 0x06, 0xe1, 0x98, 0x1c, 0x75, 0x87, 0x46, - 0xa7, 0xf7, 0xd4, 0xec, 0x76, 0x86, 0x6d, 0xa3, 0x99, 0x04, 0x09, 0x9e, 0x47, 0x0c, 0xdb, 0x5f, - 0x0d, 0xb5, 0x82, 0xb8, 0x07, 0x5b, 0x33, 0x88, 0xed, 0x4e, 0xaf, 0x69, 0x7c, 0x6d, 0x76, 0x7a, - 0x43, 0xa3, 0xbf, 0x73, 0xd8, 0x6a, 0x1b, 0xda, 0x92, 0xb8, 0x0e, 0x62, 0x86, 0x6a, 0xaf, 0xfd, - 0x95, 0x56, 0x5c, 0x00, 0xdf, 0xee, 0x0c, 0xb5, 0xd2, 0x83, 0x7d, 0xb8, 0xda, 0x3c, 0x39, 0x09, - 0x9d, 0x13, 0xe4, 0xdb, 0x14, 0x90, 0x52, 0x79, 0x4b, 0x37, 0x9f, 0x3e, 0x35, 0x5b, 0xfd, 0xde, - 0x6e, 0xe7, 0xa9, 0xaa, 0xda, 0x1b, 0xf0, 0x7a, 0x06, 0xf8, 0xd4, 0xe8, 0x1f, 0x1e, 0x60, 0xa2, - 0xd5, 0x1c, 0x9a, 0x7d, 0x63, 0xa7, 0x6d, 0x68, 0x85, 0x07, 0x6f, 0x40, 0x4d, 0x85, 0xa2, 0x4f, - 0x62, 0x2a, 0x07, 0xbe, 0xa3, 0x5d, 0x41, 0x89, 0xa2, 0xfb, 0xdd, 0x27, 0x5a, 0xe1, 0x81, 0x0e, - 0xd5, 0xc1, 0xe9, 0xf4, 0xf8, 0xd8, 0x73, 0x14, 0xc5, 0x9e, 0x15, 0x9d, 0xb2, 0x07, 0x15, 0xbd, - 0xe0, 0xa7, 0x15, 0x1e, 0xbc, 0x8d, 0x7a, 0x1f, 0xd1, 0xec, 0x3b, 0xf1, 0x69, 0x60, 0x0b, 0x80, - 0x95, 0x5e, 0x10, 0x8e, 0x2d, 0x4f, 0xd2, 0x39, 0xd3, 0x08, 0xe9, 0x3e, 0x84, 0x6b, 0x99, 0xb2, - 0x76, 0x83, 0x90, 0x02, 0xe3, 0xb4, 0x7a, 0x74, 0x9b, 0xd2, 0x1d, 0x4f, 0x3c, 0x87, 0xef, 0x05, - 0xee, 0x5d, 0x1e, 0x85, 0xae, 0xad, 0x15, 0x1e, 0x3c, 0x81, 0x4a, 0xfa, 0x48, 0x28, 0x45, 0x23, - 0xdf, 0xee, 0x1f, 0xf6, 0x76, 0x28, 0xdc, 0x31, 0x45, 0x20, 0x6f, 0x75, 0x0f, 0x07, 0x9d, 0xe7, - 0x52, 0x1c, 0x6b, 0x7f, 0xa5, 0x92, 0x4b, 0x0f, 0xfe, 0xb0, 0xa0, 0x62, 0x69, 0xa9, 0x6a, 0x77, - 0xfb, 0xcd, 0x1d, 0x96, 0xe3, 0x92, 0x40, 0xeb, 0xc3, 0x6d, 0xad, 0x80, 0x00, 0xa3, 0x3d, 0x38, - 0xec, 0x0e, 0x55, 0x0c, 0xf7, 0x3a, 0x40, 0xa7, 0xd5, 0xde, 0x6e, 0x1b, 0x4f, 0x91, 0xa0, 0x88, - 0xe9, 0xfd, 0x7e, 0xef, 0x69, 0x7f, 0x67, 0x1b, 0xd3, 0x14, 0xbd, 0x7d, 0xa7, 0x39, 0x6c, 0x0e, - 0x86, 0x46, 0xbb, 0xb9, 0x8f, 0x20, 0xba, 0xb0, 0xa4, 0x1c, 0xc5, 0x86, 0xdb, 0x2c, 0xd3, 0x3d, - 0x6b, 0xee, 0x3e, 0x6b, 0x62, 0x6a, 0xf5, 0xc1, 0x7f, 0xbf, 0x04, 0xda, 0x6c, 0xbc, 0x34, 0xf1, - 0x1a, 0xdc, 0xa0, 0x52, 0xcd, 0x03, 0xa3, 0xbd, 0xd3, 0x69, 0xb1, 0xeb, 0xf9, 0xf3, 0x66, 0xb7, - 0xb3, 0xc3, 0xb3, 0x6a, 0x16, 0xd9, 0xec, 0xed, 0x70, 0x1c, 0xe7, 0x59, 0x44, 0xfb, 0x57, 0x87, - 0xcd, 0xae, 0xb6, 0x24, 0x5e, 0x87, 0x9b, 0xb3, 0xa8, 0x5e, 0x7f, 0x28, 0xd1, 0x45, 0xd1, 0x80, - 0xcd, 0x59, 0x74, 0xb7, 0x3d, 0x40, 0xe9, 0xf4, 0x0e, 0xdc, 0x5a, 0x84, 0x91, 0x39, 0x97, 0x17, - 0xd5, 0xf4, 0x29, 0x09, 0xb7, 0x86, 0xb6, 0x82, 0x93, 0xec, 0x15, 0x48, 0x99, 0x7f, 0x15, 0xe7, - 0xf2, 0x7c, 0x4b, 0xb5, 0xf2, 0xc2, 0x1e, 0x18, 0x98, 0x14, 0xb5, 0xbb, 0x22, 0xee, 0xc2, 0x6b, - 0x8b, 0x90, 0xfd, 0x21, 0x13, 0xc0, 0x83, 0x7f, 0x52, 0x80, 0xc6, 0xab, 0x42, 0x6a, 0x08, 0x1d, - 0xee, 0x18, 0x87, 0x3d, 0x8a, 0xc1, 0xce, 0xe1, 0xe2, 0xcd, 0x67, 0xed, 0xaf, 0x67, 0xc2, 0x65, - 0xbf, 0x0e, 0x37, 0x17, 0xd0, 0x18, 0xcd, 0x17, 0xe6, 0xf3, 0x8f, 0xb5, 0x82, 0x78, 0x0f, 0xde, - 0x59, 0x80, 0xde, 0xed, 0xf6, 0x9b, 0x43, 0xf3, 0xd7, 0x6d, 0xa3, 0x6f, 0xb6, 0xba, 0xfd, 0x41, - 0x7b, 0x07, 0x89, 0x97, 0xc4, 0x16, 0xdc, 0x5e, 0x40, 0x3c, 0xe0, 0x08, 0xff, 0xcf, 0x3f, 0xd6, - 0x8a, 0xe2, 0x2d, 0x78, 0xe3, 0xd5, 0x14, 0xbb, 0x28, 0xff, 0x3f, 0xff, 0x58, 0x2b, 0x3d, 0xf8, - 0x25, 0x34, 0x5e, 0x75, 0xaf, 0x13, 0x17, 0x52, 0x6b, 0xaf, 0x49, 0x77, 0x67, 0x51, 0x67, 0xe8, - 0x9b, 0x9c, 0xa2, 0x93, 0x0d, 0xa3, 0xdd, 0x6d, 0xd3, 0xe5, 0x87, 0x07, 0xbf, 0x29, 0x64, 0xf4, - 0x67, 0x75, 0x37, 0x2f, 0x01, 0xc8, 0xd5, 0x9d, 0x05, 0x19, 0x8e, 0x65, 0x6b, 0x05, 0x1c, 0xa5, - 0x1c, 0xa8, 0x1b, 0x8c, 0x2c, 0x4f, 0x5b, 0xa2, 0x6b, 0x0e, 0x0a, 0x4e, 0x37, 0xdb, 0xb5, 0x22, - 0x76, 0x5d, 0x02, 0xeb, 0x06, 0xe7, 0x07, 0xa1, 0x1b, 0x84, 0x6e, 0x7c, 0xc9, 0xe8, 0xd2, 0x83, - 0x7f, 0x51, 0x3a, 0xe3, 0xe4, 0x76, 0x55, 0xfc, 0x40, 0xd3, 0xb6, 0x53, 0x18, 0x09, 0x72, 0x3c, - 0xd7, 0x49, 0x8a, 0x9d, 0x41, 0x14, 0x70, 0x7e, 0x28, 0x23, 0xdf, 0x2c, 0x72, 0x09, 0x91, 0x86, - 0x43, 0x0e, 0xf2, 0x73, 0xc8, 0xe2, 0xf6, 0xb3, 0x7f, 0xfc, 0x67, 0x77, 0x0a, 0x7f, 0xf2, 0x67, - 0x77, 0x0a, 0xff, 0xeb, 0x9f, 0xdd, 0xb9, 0xf2, 0x37, 0xfe, 0xfc, 0x4e, 0xe1, 0x8f, 0xff, 0xfc, - 0x4e, 0xe1, 0x4f, 0xfe, 0xfc, 0x4e, 0xe1, 0x7f, 0xfa, 0xf3, 0x3b, 0x85, 0x5f, 0x7f, 0x70, 0xe2, - 0xc6, 0xa7, 0xd3, 0xa3, 0x87, 0xa3, 0x60, 0xfc, 0xe1, 0xd8, 0x8a, 0x43, 0xf7, 0x82, 0x45, 0x6b, - 0x95, 0xf0, 0x9d, 0x0f, 0x27, 0x67, 0x27, 0x1f, 0x4e, 0x8e, 0x3e, 0xc4, 0x0d, 0xe4, 0x68, 0x65, - 0x12, 0x06, 0x71, 0xf0, 0xf8, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x4b, 0xcf, 0xdb, 0xf6, 0x29, - 0xb4, 0x00, 0x00, + // 18165 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xcc, 0xbd, 0x5d, 0x8c, 0x1b, 0x57, + 0x97, 0x20, 0x26, 0x36, 0xd9, 0x4d, 0xf2, 0x90, 0xcd, 0xae, 0xbe, 0x6a, 0x49, 0x2d, 0x59, 0x96, + 0xe4, 0xb2, 0x6c, 0xcb, 0xb2, 0x2d, 0xdb, 0x92, 0x7f, 0x64, 0xcf, 0x37, 0xf3, 0x7d, 0x6c, 0x36, + 0x5b, 0x4d, 0x8b, 0x4d, 0xf6, 0x57, 0x64, 0x4b, 0xf6, 0x37, 0x3b, 0x28, 0x54, 0xb3, 0xaa, 0xbb, + 0xcb, 0x5d, 0xac, 0xa2, 0xab, 0x8a, 0xea, 0x6e, 0x03, 0x41, 0x3e, 0xe4, 0x21, 0x93, 0x09, 0xf2, + 0xb0, 0xc0, 0x20, 0x9b, 0x87, 0x00, 0xc1, 0xec, 0x02, 0x8b, 0x00, 0x9b, 0xe4, 0x21, 0xc1, 0x22, + 0x93, 0x1f, 0x6c, 0x92, 0xcd, 0x06, 0xc8, 0x02, 0x09, 0x82, 0x41, 0x36, 0xc9, 0x24, 0x59, 0x60, + 0x37, 0x99, 0xc9, 0x73, 0x12, 0x20, 0x79, 0xd9, 0xbc, 0x24, 0x38, 0xe7, 0xdc, 0x5b, 0x3f, 0x24, + 0x65, 0xd9, 0xdf, 0xcc, 0x00, 0x79, 0xe9, 0xe6, 0x3d, 0xe7, 0xdc, 0x5b, 0xf7, 0xf7, 0xdc, 0x73, + 0xce, 0x3d, 0xf7, 0x5c, 0x80, 0x89, 0x67, 0xf9, 0x0f, 0x26, 0x61, 0x10, 0x07, 0xa2, 0x84, 0xbf, + 0x6f, 0x7c, 0x70, 0xec, 0xc6, 0x27, 0xd3, 0xc3, 0x07, 0xa3, 0x60, 0xfc, 0xe1, 0x71, 0x70, 0x1c, + 0x7c, 0x48, 0xc8, 0xc3, 0xe9, 0x11, 0xa5, 0x28, 0x41, 0xbf, 0x38, 0xd3, 0x0d, 0xf0, 0x82, 0xd1, + 0xa9, 0xfc, 0xbd, 0x16, 0xbb, 0x63, 0x27, 0x8a, 0xad, 0xf1, 0x84, 0x01, 0xfa, 0xff, 0x5e, 0x80, + 0xd2, 0xf0, 0x62, 0xe2, 0x88, 0x06, 0x2c, 0xb9, 0xf6, 0x66, 0xe1, 0x4e, 0xe1, 0xde, 0xb2, 0xb1, + 0xe4, 0xda, 0xe2, 0x0e, 0xd4, 0xfc, 0x20, 0xee, 0x4d, 0x3d, 0xcf, 0x3a, 0xf4, 0x9c, 0xcd, 0xa5, + 0x3b, 0x85, 0x7b, 0x15, 0x23, 0x0b, 0x12, 0xaf, 0x41, 0xd5, 0x9a, 0xc6, 0x81, 0xe9, 0xfa, 0xa3, + 0x70, 0xb3, 0x48, 0xf8, 0x0a, 0x02, 0x3a, 0xfe, 0x28, 0x14, 0x1b, 0xb0, 0x7c, 0xe6, 0xda, 0xf1, + 0xc9, 0x66, 0x89, 0x4a, 0xe4, 0x04, 0x42, 0xa3, 0x91, 0xe5, 0x39, 0x9b, 0xcb, 0x0c, 0xa5, 0x04, + 0x42, 0x63, 0xfa, 0xc8, 0xca, 0x9d, 0xc2, 0xbd, 0xaa, 0xc1, 0x09, 0x71, 0x0b, 0xc0, 0xf1, 0xa7, + 0xe3, 0x17, 0x96, 0x37, 0x75, 0xa2, 0xcd, 0x32, 0xa1, 0x32, 0x10, 0xb1, 0x09, 0xe5, 0xd1, 0x89, + 0x15, 0x46, 0x4e, 0xbc, 0x59, 0xb9, 0x53, 0xb8, 0xb7, 0x6a, 0xa8, 0x24, 0x56, 0x6c, 0x62, 0xd9, + 0x66, 0x34, 0xb1, 0x46, 0xce, 0x66, 0x95, 0x2b, 0x36, 0xb1, 0xec, 0x01, 0xa6, 0xf5, 0x9f, 0x43, + 0x75, 0x1c, 0x1d, 0xef, 0x3a, 0x96, 0xed, 0x84, 0xe2, 0x1a, 0x94, 0xc7, 0xd1, 0xb1, 0x19, 0x5b, + 0xc7, 0xb2, 0xe5, 0x2b, 0xe3, 0xe8, 0x78, 0x68, 0x1d, 0x8b, 0xeb, 0x50, 0x21, 0xc4, 0xc5, 0x84, + 0x9b, 0xbe, 0x6c, 0x20, 0x21, 0x76, 0x94, 0xfe, 0x27, 0x65, 0x28, 0x77, 0xdd, 0xd8, 0x09, 0x2d, + 0x4f, 0x5c, 0x85, 0x15, 0x37, 0xf2, 0xa7, 0x9e, 0x47, 0xd9, 0x2b, 0x86, 0x4c, 0x89, 0xab, 0xb0, + 0xec, 0x3e, 0x7e, 0x61, 0x79, 0x9c, 0x77, 0xf7, 0x92, 0xc1, 0x49, 0xb1, 0x09, 0x2b, 0xee, 0xc7, + 0x9f, 0x21, 0xa2, 0x28, 0x11, 0x32, 0x4d, 0x98, 0x47, 0x0f, 0x11, 0x53, 0x4a, 0x30, 0x94, 0x26, + 0xcc, 0x67, 0x9f, 0x20, 0x06, 0x3b, 0xad, 0x48, 0x18, 0x4a, 0xe3, 0x57, 0xa6, 0xf4, 0x15, 0xec, + 0xb7, 0x55, 0xfc, 0xca, 0x54, 0x7d, 0x65, 0xca, 0x5f, 0x29, 0x4b, 0x84, 0x4c, 0x13, 0x86, 0xbf, + 0x52, 0x49, 0x30, 0xc9, 0x57, 0xa6, 0xfc, 0x15, 0xec, 0xb0, 0x12, 0x61, 0xf8, 0x2b, 0x1b, 0x50, + 0xb2, 0x11, 0x0e, 0x77, 0x0a, 0xf7, 0x0a, 0xbb, 0x97, 0x0c, 0x4a, 0x21, 0x34, 0x42, 0x68, 0x0d, + 0xc7, 0x05, 0xa1, 0x91, 0x84, 0x1e, 0x22, 0xb4, 0x8e, 0xbd, 0x81, 0xd0, 0x43, 0x09, 0x3d, 0x42, + 0xe8, 0xea, 0x9d, 0xc2, 0xbd, 0x25, 0x84, 0x62, 0x4a, 0xdc, 0x80, 0xb2, 0x6d, 0xc5, 0x0e, 0x22, + 0x1a, 0xb2, 0xc9, 0x0a, 0x80, 0x38, 0x9c, 0xa8, 0x88, 0x5b, 0x93, 0x8d, 0x56, 0x00, 0xa1, 0x43, + 0x0d, 0xc9, 0x14, 0x5e, 0x93, 0xf8, 0x2c, 0x50, 0x7c, 0x0a, 0x75, 0xdb, 0x19, 0xb9, 0x63, 0xcb, + 0xe3, 0x36, 0xad, 0xdf, 0x29, 0xdc, 0xab, 0x3d, 0x5c, 0x7b, 0x40, 0x4b, 0x29, 0xc1, 0xec, 0x5e, + 0x32, 0x72, 0x64, 0xe2, 0x31, 0xac, 0xca, 0xf4, 0xc7, 0x0f, 0xa9, 0x63, 0x05, 0xe5, 0xd3, 0x72, + 0xf9, 0x3e, 0x7e, 0xf8, 0x78, 0xf7, 0x92, 0x91, 0x27, 0x14, 0x77, 0xa1, 0x9e, 0xac, 0x2c, 0xcc, + 0x78, 0x59, 0xd6, 0x2a, 0x07, 0xc5, 0x66, 0x7d, 0x1b, 0x05, 0x3e, 0x12, 0x6c, 0xc8, 0x7e, 0x53, + 0x00, 0x71, 0x07, 0xc0, 0x76, 0x8e, 0xac, 0xa9, 0x17, 0x23, 0xfa, 0x8a, 0xec, 0xc0, 0x0c, 0x4c, + 0xdc, 0x82, 0xea, 0x74, 0x82, 0xad, 0x7c, 0x66, 0x79, 0x9b, 0x57, 0x25, 0x41, 0x0a, 0xc2, 0xd2, + 0x71, 0x79, 0x20, 0xf6, 0x9a, 0x1c, 0x5d, 0x05, 0xc0, 0xe1, 0x7d, 0xe1, 0x8c, 0x10, 0xb5, 0x29, + 0x3f, 0x2c, 0xd3, 0xb8, 0xf8, 0xdc, 0x68, 0xcb, 0xf5, 0x37, 0xaf, 0xd3, 0x0c, 0xe6, 0x84, 0xb8, + 0x09, 0xc5, 0x28, 0x1c, 0x6d, 0xde, 0xa0, 0xf6, 0x03, 0xb7, 0xbf, 0x7d, 0x3e, 0x09, 0x0d, 0x04, + 0x8b, 0x37, 0x61, 0xd5, 0x8d, 0xcc, 0xc8, 0x09, 0x5d, 0xcb, 0x73, 0xbf, 0x77, 0xec, 0xcd, 0xd7, + 0x28, 0x6f, 0xdd, 0x8d, 0x06, 0x09, 0x4c, 0x7c, 0x09, 0x75, 0x8f, 0x97, 0x89, 0x79, 0x14, 0x84, + 0xe3, 0xcd, 0x9b, 0x77, 0x0a, 0xf7, 0x1a, 0x0f, 0xaf, 0x71, 0x59, 0x83, 0x38, 0x74, 0xfd, 0x63, + 0xb9, 0x8c, 0x76, 0x82, 0x70, 0x6c, 0xd4, 0xbc, 0x34, 0x81, 0x1f, 0x88, 0x88, 0xc2, 0x8c, 0x82, + 0x69, 0x38, 0x72, 0x36, 0x5f, 0xa7, 0x15, 0x5e, 0x67, 0xe0, 0x80, 0x60, 0xe2, 0xe7, 0x70, 0x53, + 0x0e, 0x82, 0xa9, 0x3e, 0x14, 0x3a, 0xdf, 0x4d, 0xdd, 0xd0, 0x89, 0xcc, 0x17, 0x8f, 0x1f, 0x6e, + 0xde, 0xa2, 0x4a, 0x5d, 0x97, 0x34, 0xf2, 0x5b, 0x86, 0xa4, 0x78, 0xf6, 0xf8, 0xe1, 0x56, 0x19, + 0x96, 0x89, 0x97, 0xe8, 0x37, 0xa1, 0xb2, 0x6f, 0x85, 0xd6, 0xd8, 0x70, 0x8e, 0x84, 0x06, 0xc5, + 0x49, 0x10, 0x49, 0x76, 0x80, 0x3f, 0xf5, 0x2e, 0xac, 0x3c, 0xb3, 0x42, 0xc4, 0x09, 0x28, 0xf9, + 0xd6, 0xd8, 0x21, 0x64, 0xd5, 0xa0, 0xdf, 0xc8, 0x02, 0xa2, 0x8b, 0x28, 0x76, 0xc6, 0x92, 0x45, + 0xca, 0x14, 0xc2, 0x8f, 0xbd, 0xe0, 0x50, 0x2e, 0xf5, 0x8a, 0x21, 0x53, 0xfa, 0xbf, 0x50, 0x80, + 0x95, 0x56, 0xe0, 0x61, 0x71, 0xd7, 0xa0, 0x1c, 0x3a, 0x9e, 0x99, 0x7e, 0x6e, 0x25, 0x74, 0xbc, + 0xfd, 0x20, 0x42, 0xc4, 0x28, 0x60, 0x04, 0x33, 0x9f, 0x95, 0x51, 0x40, 0x08, 0x55, 0x81, 0x62, + 0xa6, 0x02, 0xd7, 0xa1, 0x12, 0x1f, 0x7a, 0x26, 0xc1, 0x4b, 0x04, 0x2f, 0xc7, 0x87, 0x5e, 0x0f, + 0x51, 0xd7, 0xa0, 0x6c, 0x1f, 0x32, 0x66, 0x99, 0x30, 0x2b, 0xf6, 0x21, 0x22, 0xf4, 0x2f, 0xa0, + 0x6a, 0x58, 0x67, 0xb2, 0x1a, 0x57, 0x60, 0x05, 0x0b, 0x90, 0xdc, 0xbf, 0x64, 0x2c, 0xc7, 0x87, + 0x5e, 0xc7, 0x46, 0x30, 0x56, 0xc2, 0xb5, 0xa9, 0x0e, 0x25, 0x63, 0x79, 0x14, 0x78, 0x1d, 0x5b, + 0x1f, 0x02, 0xb4, 0x82, 0x30, 0xfc, 0x8d, 0x9b, 0xb0, 0x01, 0xcb, 0xb6, 0x33, 0x89, 0x4f, 0x98, + 0x03, 0x1a, 0x9c, 0xd0, 0xef, 0x43, 0x05, 0xa7, 0x57, 0xd7, 0x8d, 0x62, 0x71, 0x0b, 0x4a, 0x9e, + 0x1b, 0xc5, 0x9b, 0x85, 0x3b, 0xc5, 0x99, 0xc9, 0x47, 0x70, 0xfd, 0x0e, 0x54, 0xf6, 0xac, 0xf3, + 0x67, 0x38, 0x72, 0x58, 0x1a, 0x0d, 0xa1, 0x1c, 0x12, 0x39, 0x9e, 0x75, 0x80, 0xa1, 0x15, 0x1e, + 0x3b, 0x31, 0x31, 0xec, 0xff, 0xab, 0x00, 0xb5, 0xc1, 0xf4, 0xf0, 0xbb, 0xa9, 0x13, 0x5e, 0x60, + 0x9d, 0xef, 0x41, 0x31, 0xbe, 0x98, 0x50, 0x8e, 0xc6, 0xc3, 0xab, 0x72, 0x3e, 0xa6, 0xf8, 0x07, + 0x98, 0xc9, 0x40, 0x12, 0x6c, 0x84, 0x1f, 0xd8, 0x8e, 0xea, 0x83, 0x65, 0x63, 0x05, 0x93, 0x1d, + 0x1b, 0x37, 0xcb, 0x60, 0x22, 0x47, 0x61, 0x29, 0x98, 0x88, 0x3b, 0xb0, 0x3c, 0x3a, 0x71, 0x3d, + 0x9b, 0x06, 0x20, 0x5f, 0x67, 0x46, 0xe0, 0x28, 0x85, 0xc1, 0x99, 0x19, 0xb9, 0xdf, 0xab, 0xcd, + 0xaf, 0x1c, 0x06, 0x67, 0x03, 0xf7, 0x7b, 0x47, 0x1f, 0xca, 0x1d, 0x18, 0x60, 0x65, 0xd0, 0x6a, + 0x76, 0x9b, 0x86, 0x76, 0x09, 0x7f, 0xb7, 0xbf, 0xee, 0x0c, 0x86, 0x03, 0xad, 0x20, 0x1a, 0x00, + 0xbd, 0xfe, 0xd0, 0x94, 0xe9, 0x25, 0xb1, 0x02, 0x4b, 0x9d, 0x9e, 0x56, 0x44, 0x1a, 0x84, 0x77, + 0x7a, 0x5a, 0x49, 0x94, 0xa1, 0xd8, 0xec, 0x7d, 0xa3, 0x2d, 0xd3, 0x8f, 0x6e, 0x57, 0x5b, 0xd1, + 0xff, 0x9f, 0x25, 0xa8, 0xf6, 0x0f, 0xbf, 0x75, 0x46, 0x31, 0xb6, 0x19, 0x67, 0xa9, 0x13, 0xbe, + 0x70, 0x42, 0x6a, 0x76, 0xd1, 0x90, 0x29, 0x6c, 0x88, 0x7d, 0x48, 0x8d, 0x2b, 0x1a, 0x4b, 0xf6, + 0x21, 0xd1, 0x8d, 0x4e, 0x9c, 0xb1, 0x45, 0x8d, 0x43, 0x3a, 0x4a, 0xe1, 0xaa, 0x08, 0x0e, 0xbf, + 0xa5, 0xe6, 0x15, 0x0d, 0xfc, 0x29, 0x6e, 0x43, 0x8d, 0xcb, 0xc8, 0xce, 0x2f, 0x60, 0xd0, 0xec, + 0xe4, 0x5b, 0xc9, 0x4e, 0x3e, 0xca, 0x49, 0xa5, 0x32, 0x52, 0xee, 0xec, 0x0c, 0xea, 0xc9, 0x19, + 0x1d, 0x1c, 0x7e, 0xcb, 0xd8, 0x0a, 0xcf, 0xe8, 0xe0, 0xf0, 0x5b, 0x42, 0xbd, 0x07, 0xeb, 0xd1, + 0xf4, 0x30, 0x1a, 0x85, 0xee, 0x24, 0x76, 0x03, 0x9f, 0x69, 0xaa, 0x44, 0xa3, 0x65, 0x11, 0x44, + 0x7c, 0x0f, 0x2a, 0x93, 0xe9, 0xa1, 0xe9, 0xfa, 0x47, 0x01, 0xed, 0x5e, 0xb5, 0x87, 0xab, 0x3c, + 0x30, 0xfb, 0xd3, 0xc3, 0x8e, 0x7f, 0x14, 0x18, 0xe5, 0x09, 0xff, 0x10, 0x3a, 0xac, 0xfa, 0x41, + 0x6c, 0xa2, 0xa0, 0x64, 0x8e, 0x9d, 0xd8, 0xa2, 0x6d, 0x8d, 0xc5, 0x9d, 0x6e, 0x30, 0x3a, 0xdd, + 0x73, 0x62, 0x4b, 0xdc, 0x87, 0x4a, 0xe4, 0x5b, 0x93, 0xe8, 0x24, 0x88, 0x69, 0x7f, 0xab, 0x3d, + 0x6c, 0xc8, 0xb9, 0x23, 0xa1, 0x46, 0x82, 0xd7, 0xdf, 0x86, 0xb2, 0xfc, 0x06, 0x0a, 0x23, 0xb1, + 0xe3, 0x5b, 0x7e, 0x6c, 0x26, 0xe2, 0x55, 0x85, 0x01, 0x1d, 0x5b, 0xff, 0xbb, 0x05, 0xd0, 0x06, + 0x99, 0x6a, 0xd3, 0x87, 0x16, 0x71, 0x99, 0xd7, 0x01, 0xac, 0xd1, 0x28, 0x98, 0x72, 0x31, 0x3c, + 0x19, 0xab, 0x12, 0xd2, 0xb1, 0xb3, 0x7d, 0x5d, 0xcc, 0xf5, 0xf5, 0x1b, 0x50, 0x57, 0xf9, 0x32, + 0x0c, 0xa2, 0x26, 0x61, 0xaa, 0xb7, 0xa3, 0x69, 0x8e, 0x4b, 0x94, 0xa3, 0x29, 0xe7, 0xbe, 0x0a, + 0x2b, 0x24, 0x8b, 0x45, 0x6a, 0x04, 0x39, 0xa5, 0xff, 0x69, 0x01, 0x56, 0x3b, 0xbe, 0xed, 0x9c, + 0x0f, 0x46, 0x96, 0xaf, 0x3a, 0xd0, 0x8d, 0x4c, 0x17, 0x61, 0x66, 0x34, 0xb2, 0x7c, 0x29, 0x0f, + 0xd5, 0xdc, 0x28, 0xa1, 0xc3, 0x36, 0x30, 0x01, 0x7d, 0x6a, 0x89, 0x4a, 0xac, 0x12, 0x84, 0x3e, + 0xf6, 0x36, 0xac, 0x1d, 0x3a, 0x5e, 0xe0, 0x1f, 0x9b, 0x71, 0x60, 0xb2, 0x3c, 0xc8, 0x6d, 0x59, + 0x65, 0xf0, 0x30, 0x18, 0x92, 0x5c, 0xb8, 0x01, 0xcb, 0x13, 0x2b, 0x8c, 0xa3, 0xcd, 0xd2, 0x9d, + 0x22, 0x2e, 0x79, 0x4a, 0x60, 0x37, 0xbb, 0x91, 0x39, 0xf5, 0xdd, 0xef, 0xa6, 0xdc, 0x8c, 0x8a, + 0x51, 0x71, 0xa3, 0x03, 0x4a, 0x8b, 0x7b, 0xa0, 0xf1, 0x97, 0xa9, 0xd8, 0xec, 0x9c, 0x6c, 0x10, + 0x9c, 0x0a, 0x26, 0xc6, 0xf8, 0xdf, 0x15, 0xa1, 0xb2, 0x33, 0xf5, 0x47, 0x38, 0x18, 0xe2, 0x4d, + 0x28, 0x1d, 0x4d, 0xfd, 0x11, 0xb5, 0x25, 0x91, 0x1e, 0x92, 0x35, 0x65, 0x10, 0x12, 0xb9, 0x95, + 0x15, 0x1e, 0x23, 0x97, 0x9b, 0xe3, 0x56, 0x08, 0xa7, 0x91, 0x3b, 0x3e, 0x36, 0x47, 0x81, 0x7f, + 0xe4, 0x1e, 0x53, 0x8b, 0xea, 0x46, 0xd5, 0x3a, 0x3e, 0x6e, 0x11, 0x40, 0x34, 0x61, 0x2d, 0x45, + 0xb3, 0xbc, 0x59, 0x22, 0xc6, 0x74, 0x9d, 0x4b, 0x6a, 0x1e, 0x1f, 0x87, 0xce, 0xb1, 0x15, 0x3b, + 0x4c, 0x4f, 0xbc, 0x69, 0x35, 0xc9, 0x4e, 0x7c, 0xe3, 0x23, 0xd8, 0x88, 0x2e, 0xfc, 0xd8, 0x3a, + 0x37, 0x9d, 0xf3, 0x89, 0xe7, 0x8e, 0xdc, 0xd8, 0x1c, 0x59, 0x51, 0x2c, 0x7b, 0x41, 0x30, 0xae, + 0x2d, 0x51, 0x2d, 0x2b, 0x8a, 0xc5, 0x27, 0x50, 0x0f, 0x83, 0x69, 0xec, 0xfa, 0x8e, 0x39, 0xb2, + 0x3c, 0x96, 0x1f, 0x6b, 0x0f, 0xd7, 0xf9, 0x8b, 0x06, 0x63, 0x5a, 0x96, 0xe7, 0x19, 0xb5, 0x30, + 0x4d, 0xe8, 0xff, 0x41, 0x81, 0xfb, 0x66, 0xc7, 0xb3, 0x8e, 0x45, 0x05, 0x4a, 0xbd, 0x7e, 0xaf, + 0xad, 0x5d, 0x12, 0x75, 0xa8, 0x74, 0x7a, 0xc3, 0xb6, 0xd1, 0x6b, 0x76, 0xb5, 0x02, 0x31, 0xb1, + 0x61, 0x73, 0xab, 0xdb, 0xd6, 0x96, 0x10, 0xf3, 0xac, 0xdf, 0x6d, 0x0e, 0x3b, 0xdd, 0xb6, 0x56, + 0x62, 0x8c, 0xd1, 0x69, 0x0d, 0xb5, 0x8a, 0xd0, 0xa0, 0xbe, 0x6f, 0xf4, 0xb7, 0x0f, 0x5a, 0x6d, + 0xb3, 0x77, 0xd0, 0xed, 0x6a, 0x9a, 0xb8, 0x0c, 0x6b, 0x09, 0xa4, 0xcf, 0xc0, 0x3b, 0x98, 0xe5, + 0x59, 0xd3, 0x68, 0x1a, 0x4f, 0xb4, 0x5f, 0x88, 0x0a, 0x14, 0x9b, 0x4f, 0x9e, 0x68, 0xbf, 0x46, + 0x7e, 0x58, 0x7d, 0xde, 0xe9, 0x99, 0xcf, 0x9a, 0xdd, 0x83, 0xb6, 0xf6, 0xeb, 0x25, 0x95, 0xee, + 0x1b, 0xdb, 0x6d, 0x43, 0xfb, 0x75, 0x49, 0xac, 0x43, 0xfd, 0x57, 0xfd, 0x5e, 0x7b, 0xaf, 0xb9, + 0xbf, 0x4f, 0x15, 0xf9, 0x75, 0x45, 0xff, 0xf3, 0x12, 0x5c, 0xdb, 0x0f, 0x9d, 0x89, 0x15, 0x3a, + 0x76, 0x6f, 0x3a, 0x76, 0x42, 0x77, 0x84, 0x4b, 0xcd, 0xb6, 0x62, 0x4b, 0xdc, 0x80, 0xca, 0x91, + 0xe5, 0x79, 0x87, 0xd6, 0xe8, 0x54, 0xce, 0xda, 0x24, 0xcd, 0x9a, 0x44, 0x68, 0x8d, 0x33, 0xfb, + 0x58, 0x85, 0x00, 0xb8, 0x93, 0xbd, 0x03, 0x6b, 0x8a, 0x50, 0x89, 0x29, 0xbc, 0xd5, 0x37, 0x14, + 0x58, 0x0a, 0x2a, 0x9f, 0xc2, 0xb5, 0x19, 0x42, 0x53, 0x6d, 0x2b, 0xac, 0x1d, 0x6d, 0xe4, 0x33, + 0xf4, 0x78, 0x93, 0x59, 0x90, 0x4d, 0x6d, 0xa9, 0xcb, 0x8b, 0xb2, 0xb5, 0x78, 0x83, 0xfd, 0x0c, + 0xae, 0x4d, 0xc2, 0xe0, 0x85, 0x1b, 0xb9, 0x81, 0x4f, 0x22, 0x51, 0x34, 0xf5, 0xe4, 0x8c, 0x58, + 0xa1, 0xea, 0x5d, 0xc9, 0xa0, 0x0d, 0xc2, 0xd2, 0xa4, 0x58, 0x9c, 0x6f, 0xe2, 0x38, 0x21, 0xb1, + 0xe8, 0x45, 0xf9, 0xf6, 0x1d, 0x27, 0x14, 0xdb, 0x70, 0xfb, 0x25, 0xf9, 0x68, 0x3a, 0x63, 0x2b, + 0x2b, 0x54, 0xdd, 0xd7, 0x16, 0xe6, 0xc7, 0x29, 0xdc, 0xb1, 0x45, 0x13, 0x5e, 0x7f, 0x59, 0x29, + 0xac, 0x47, 0x56, 0xa9, 0x8c, 0x1b, 0x0b, 0xcb, 0x78, 0x4e, 0xca, 0xe5, 0x0f, 0x14, 0xc1, 0x4a, + 0x27, 0xfc, 0x40, 0x11, 0x03, 0xd2, 0x44, 0x7f, 0x06, 0x1b, 0x52, 0xee, 0xb4, 0x83, 0xb1, 0xe5, + 0xfa, 0x6a, 0x5c, 0x6b, 0x73, 0xdb, 0xba, 0x60, 0xba, 0x6d, 0x22, 0xe3, 0xfe, 0xd7, 0xff, 0xde, + 0x32, 0x94, 0x10, 0x29, 0xf4, 0x54, 0xc2, 0x48, 0x72, 0x61, 0x3b, 0xb7, 0x4a, 0xff, 0xf0, 0x9f, + 0xdc, 0xbe, 0xc4, 0xb2, 0xc5, 0x1b, 0x50, 0xf4, 0xdc, 0x98, 0x26, 0x55, 0xb2, 0x2f, 0x49, 0x19, + 0x75, 0xf7, 0x92, 0x81, 0x38, 0x71, 0x0b, 0x0a, 0x2c, 0x64, 0x24, 0x5b, 0x8d, 0x92, 0x52, 0x77, + 0x2f, 0x19, 0x85, 0x89, 0xb8, 0x09, 0x85, 0x17, 0x52, 0xe2, 0xa8, 0x33, 0x9e, 0xe5, 0x54, 0xc4, + 0xbe, 0x10, 0x77, 0xa0, 0x38, 0x0a, 0x58, 0x69, 0x4c, 0xf0, 0x2c, 0xb5, 0x61, 0xf9, 0xa3, 0xc0, + 0x13, 0x6f, 0x42, 0x31, 0xb4, 0xce, 0xe4, 0xea, 0x97, 0xec, 0x2d, 0x11, 0x0b, 0x91, 0x28, 0xb4, + 0xce, 0xb0, 0x12, 0x47, 0x34, 0x01, 0x92, 0x4a, 0x28, 0xfe, 0x88, 0x9f, 0x39, 0x12, 0x77, 0xa0, + 0x70, 0x46, 0x03, 0x9c, 0xe8, 0x49, 0xcf, 0x5d, 0xdf, 0x0e, 0xce, 0x06, 0x13, 0x67, 0x84, 0x14, + 0x67, 0xe2, 0x2d, 0x28, 0x46, 0xd3, 0x43, 0x1a, 0xc0, 0x84, 0xc9, 0x64, 0xe4, 0x2d, 0xfc, 0x50, + 0x34, 0x3d, 0x14, 0x6f, 0x43, 0x69, 0x14, 0x84, 0xa1, 0xdc, 0xa9, 0x35, 0x55, 0x61, 0x25, 0x6a, + 0xa2, 0xde, 0x88, 0x78, 0xfc, 0x60, 0x2c, 0x07, 0x44, 0x12, 0xa5, 0xb2, 0x1e, 0x7e, 0x30, 0x16, + 0x77, 0xa5, 0x00, 0x99, 0xdb, 0xa5, 0x95, 0x78, 0x89, 0xe5, 0x20, 0x16, 0x07, 0x69, 0x6c, 0x9d, + 0x93, 0x52, 0x9a, 0x10, 0x29, 0xb9, 0x12, 0xeb, 0x34, 0xb6, 0xce, 0xc5, 0x5d, 0x28, 0xbe, 0x70, + 0x46, 0xa4, 0x9f, 0x26, 0x5f, 0x93, 0x83, 0xf4, 0x8c, 0x9a, 0x87, 0x68, 0xda, 0x27, 0x02, 0xcf, + 0x26, 0x55, 0x35, 0x19, 0xcb, 0x9d, 0xc0, 0xb3, 0x9f, 0xd1, 0x58, 0x12, 0x12, 0xc5, 0x69, 0x6b, + 0x7a, 0x8e, 0xab, 0x41, 0x63, 0xc1, 0xd7, 0x9a, 0x9e, 0x77, 0x6c, 0x14, 0xac, 0x7c, 0xfb, 0x05, + 0x29, 0xa8, 0x05, 0x03, 0x7f, 0x8a, 0x3b, 0x28, 0x58, 0x79, 0xce, 0x28, 0x76, 0x5f, 0xb8, 0xf1, + 0x05, 0xa9, 0xa0, 0x05, 0x23, 0x0b, 0x12, 0xbb, 0xa0, 0x4d, 0x24, 0x33, 0x33, 0x7d, 0xe6, 0x66, + 0xa4, 0x70, 0xd6, 0x1e, 0xbe, 0x2e, 0xa7, 0xc9, 0x62, 0x56, 0x67, 0xac, 0x4d, 0xf2, 0x88, 0xad, + 0x15, 0x28, 0x39, 0xe7, 0x93, 0xf0, 0xab, 0x52, 0x65, 0x43, 0xdb, 0xd4, 0x77, 0xa1, 0x2c, 0x6b, + 0x3d, 0x67, 0x0d, 0xba, 0x0e, 0x15, 0x37, 0xc2, 0x5d, 0x2a, 0x8a, 0xa5, 0x9e, 0x53, 0x76, 0xa3, + 0x16, 0x26, 0x51, 0x5c, 0xc1, 0xc2, 0xe5, 0xd6, 0x46, 0xbf, 0xf5, 0xbf, 0x57, 0x00, 0x48, 0xfb, + 0x09, 0x1b, 0xe9, 0x39, 0xbe, 0xd2, 0xa9, 0x3c, 0xc7, 0x4f, 0x32, 0x2d, 0xa5, 0x99, 0xe6, 0xb5, + 0xca, 0xe2, 0x02, 0xad, 0x72, 0x4e, 0x33, 0x2c, 0xfd, 0x06, 0x9a, 0xe1, 0xf2, 0x2b, 0x34, 0x43, + 0xfd, 0x3a, 0x54, 0x13, 0xc3, 0x80, 0xa8, 0x43, 0xc1, 0x92, 0x62, 0x73, 0xc1, 0xd2, 0xef, 0xa1, + 0x9e, 0xae, 0x54, 0xff, 0x3c, 0x0e, 0x53, 0x4a, 0x98, 0x2e, 0x1c, 0xea, 0x3f, 0x83, 0xba, 0x64, + 0xaf, 0x81, 0xb7, 0xed, 0x1c, 0x89, 0xf7, 0x01, 0x92, 0x74, 0x24, 0xb5, 0x9b, 0x74, 0x5d, 0x6e, + 0x3b, 0x47, 0x46, 0x06, 0xaf, 0xff, 0xcd, 0x65, 0xd2, 0x13, 0xb7, 0x59, 0x41, 0x93, 0x9a, 0x58, + 0x21, 0xa3, 0x89, 0x25, 0x72, 0xe2, 0x52, 0x5e, 0x1b, 0x3d, 0x71, 0x6d, 0xdb, 0xf1, 0x95, 0xd6, + 0xc9, 0x29, 0x9c, 0xc8, 0x96, 0x77, 0x2c, 0x45, 0x0b, 0xa1, 0x3e, 0x3a, 0x9e, 0x84, 0x4e, 0x14, + 0xb1, 0xbe, 0x63, 0x79, 0xc7, 0x8a, 0x6f, 0x2d, 0xff, 0x10, 0xdf, 0xba, 0x0e, 0x15, 0x14, 0x95, + 0xc9, 0xe8, 0xc5, 0xfb, 0x49, 0x59, 0x1a, 0x05, 0xc5, 0x3b, 0x50, 0x96, 0xe6, 0x0a, 0xc9, 0x30, + 0xe4, 0x52, 0xd8, 0x66, 0xa0, 0xa1, 0xb0, 0x64, 0xba, 0x0b, 0xc6, 0x63, 0xc7, 0x8f, 0x95, 0x7c, + 0x2f, 0x93, 0xe2, 0x3d, 0xa8, 0x06, 0xbe, 0xc9, 0x36, 0x0d, 0xc9, 0x31, 0xe4, 0xd2, 0xec, 0xfb, + 0x07, 0x04, 0x35, 0x2a, 0x81, 0xfc, 0x85, 0x55, 0xf1, 0x82, 0x33, 0x73, 0x64, 0x85, 0x36, 0x71, + 0x8d, 0x8a, 0x51, 0xf6, 0x82, 0xb3, 0x96, 0x15, 0xda, 0xac, 0xef, 0x7c, 0xe7, 0x4f, 0xc7, 0xc4, + 0x29, 0x56, 0x0d, 0x99, 0x12, 0x37, 0xa1, 0x3a, 0xf2, 0xa6, 0x51, 0xec, 0x84, 0x5b, 0x17, 0x6c, + 0xa5, 0x32, 0x52, 0x00, 0xd6, 0x6b, 0x12, 0xba, 0x63, 0x2b, 0xbc, 0x20, 0xb6, 0x50, 0x31, 0x54, + 0x92, 0x84, 0xce, 0x53, 0xd7, 0x3e, 0x67, 0x53, 0x95, 0xc1, 0x09, 0xa4, 0x3f, 0x21, 0x43, 0x62, + 0x44, 0x6b, 0xbf, 0x62, 0xa8, 0x24, 0x8d, 0x03, 0xfd, 0xa4, 0xd5, 0x5e, 0x35, 0x64, 0x2a, 0xa7, + 0xac, 0xaf, 0xbf, 0x54, 0x59, 0x17, 0xb3, 0xfa, 0x52, 0x10, 0xba, 0xc7, 0xae, 0xd4, 0x76, 0x2e, + 0xb3, 0xbe, 0xc4, 0x20, 0x22, 0xf8, 0x1c, 0x56, 0x8f, 0x1d, 0xdf, 0x09, 0xad, 0xd8, 0xb1, 0x51, + 0x44, 0x20, 0xe3, 0x52, 0x4d, 0x0d, 0xf3, 0x13, 0x85, 0x42, 0x3e, 0x5a, 0x3f, 0xce, 0xa4, 0xb0, + 0x96, 0x52, 0x62, 0xbe, 0xc2, 0xb3, 0x85, 0x53, 0x28, 0x8a, 0xcb, 0x2f, 0x26, 0x95, 0xbd, 0xca, + 0xa2, 0x38, 0x83, 0x87, 0x5c, 0x65, 0xfd, 0x3b, 0x28, 0xcb, 0xb1, 0x45, 0x31, 0x18, 0x39, 0x49, + 0x7e, 0xcf, 0x63, 0x31, 0x18, 0xe1, 0xb8, 0x6e, 0x65, 0x91, 0xbc, 0x52, 0xe5, 0xac, 0xad, 0x33, + 0x90, 0xcd, 0x41, 0xa8, 0xad, 0xe0, 0xbc, 0x32, 0xad, 0x43, 0xd7, 0x43, 0xde, 0x57, 0x94, 0x5a, + 0xd8, 0xd4, 0xf3, 0x9a, 0x0c, 0xd2, 0xfb, 0x50, 0x51, 0x33, 0xe1, 0x2f, 0xe5, 0x9b, 0xfa, 0x04, + 0xea, 0xd9, 0x1e, 0xfa, 0xcb, 0x69, 0x08, 0x6b, 0x23, 0x51, 0x1c, 0x84, 0x09, 0x1b, 0xab, 0xb8, + 0xd1, 0x80, 0xd2, 0xfa, 0x1f, 0x2d, 0x41, 0x8d, 0xb4, 0xa2, 0x3e, 0xe9, 0x7c, 0xe2, 0x7d, 0x10, + 0xa3, 0xd0, 0xb1, 0x62, 0xc7, 0x74, 0xce, 0xe3, 0xd0, 0x92, 0xba, 0x0f, 0x8b, 0xa2, 0x1a, 0x63, + 0xda, 0x88, 0x60, 0xf5, 0xe7, 0x36, 0xd4, 0x26, 0x56, 0x18, 0x29, 0xbd, 0x9b, 0xbf, 0x0e, 0x0c, + 0x92, 0x5a, 0xaf, 0xe6, 0x1f, 0xa3, 0xcc, 0x1a, 0x07, 0xa7, 0x8e, 0xcf, 0x16, 0x07, 0xb6, 0xb5, + 0x34, 0x08, 0x3e, 0x44, 0xf0, 0xc0, 0xfd, 0x1e, 0xa5, 0x1d, 0x40, 0x41, 0x48, 0x76, 0x36, 0xf3, + 0x86, 0x9b, 0xdc, 0xe0, 0x4c, 0xfd, 0x1e, 0x3c, 0x4b, 0x68, 0x8c, 0x0c, 0xbd, 0xfe, 0x2b, 0x80, + 0x14, 0x23, 0x6e, 0xc0, 0xd5, 0x67, 0x9d, 0x41, 0x67, 0xab, 0xd3, 0xed, 0x0c, 0xbf, 0x31, 0x0f, + 0x7a, 0x83, 0xfd, 0x76, 0xab, 0xb3, 0xd3, 0x69, 0x6f, 0x6b, 0x97, 0xc4, 0x55, 0x10, 0x19, 0x1c, + 0xfd, 0xec, 0xb6, 0xb5, 0x82, 0xd8, 0x84, 0x8d, 0x0c, 0xbc, 0xd3, 0x53, 0x98, 0x25, 0xfd, 0x7f, + 0x2e, 0xc0, 0xea, 0x3e, 0x2f, 0xbd, 0xa7, 0xce, 0xc5, 0x36, 0x9b, 0xde, 0x46, 0x8a, 0x6d, 0x96, + 0x0c, 0xfa, 0x2d, 0x6e, 0x41, 0x6d, 0x72, 0xea, 0x5c, 0x98, 0x39, 0x33, 0x55, 0x15, 0x41, 0x2d, + 0x62, 0x90, 0xef, 0xc2, 0x4a, 0x40, 0x4d, 0x90, 0x42, 0xd4, 0xfa, 0x5c, 0xdb, 0x0c, 0x49, 0x80, + 0xfa, 0x6b, 0x52, 0x54, 0x56, 0x51, 0x96, 0x85, 0x51, 0xc7, 0x6e, 0xc0, 0x32, 0xa2, 0x50, 0xfa, + 0x26, 0xc5, 0x93, 0x12, 0xe2, 0x23, 0x58, 0x1d, 0x05, 0xe3, 0x89, 0xa9, 0xb2, 0x4b, 0x71, 0x2a, + 0xcf, 0xd8, 0x6b, 0x48, 0xb2, 0xcf, 0x65, 0xe9, 0x7f, 0x5a, 0x84, 0x0a, 0xd5, 0x41, 0xf2, 0x76, + 0xd7, 0x3e, 0x57, 0xbc, 0xbd, 0x6a, 0x2c, 0xbb, 0x36, 0x8a, 0x05, 0xaf, 0xd0, 0x95, 0x13, 0x1d, + 0xb8, 0x98, 0xd5, 0x81, 0xd3, 0xe5, 0x5c, 0xca, 0x2d, 0xe7, 0x45, 0xea, 0xef, 0xf2, 0x22, 0xf5, + 0x17, 0x27, 0x17, 0xd3, 0x38, 0xe7, 0x6e, 0xa2, 0x2f, 0x00, 0x81, 0xda, 0x08, 0xc9, 0x72, 0xee, + 0x72, 0x9e, 0x73, 0x6f, 0x42, 0x99, 0x26, 0x87, 0xc7, 0x36, 0x9b, 0x8a, 0xa1, 0x92, 0x99, 0x61, + 0xa8, 0xbe, 0x6a, 0x18, 0x92, 0x66, 0x5b, 0xde, 0x31, 0xdb, 0x6c, 0x54, 0xb3, 0x9b, 0xde, 0x71, + 0x20, 0x3e, 0x86, 0x2b, 0x29, 0x5a, 0xb6, 0x86, 0x54, 0x66, 0x3a, 0x85, 0x30, 0x44, 0x42, 0x49, + 0x2d, 0x22, 0xe5, 0xf8, 0x3e, 0xac, 0x67, 0xb2, 0x90, 0xee, 0x16, 0x11, 0xe3, 0xaf, 0x1a, 0x6b, + 0x09, 0x39, 0x89, 0xd5, 0x91, 0x78, 0x17, 0xfb, 0x69, 0xe4, 0x4d, 0x6d, 0x66, 0xa3, 0xd3, 0xb1, + 0x1f, 0x6d, 0xae, 0x52, 0x07, 0xaf, 0x29, 0x78, 0x8b, 0xc1, 0x5f, 0x95, 0x2a, 0x0d, 0x6d, 0xcd, + 0x68, 0xa4, 0xcb, 0xc1, 0x8c, 0x9c, 0x58, 0xff, 0x83, 0x65, 0x58, 0xdd, 0x09, 0x42, 0xc7, 0x3d, + 0xf6, 0xd3, 0x69, 0x3b, 0x67, 0xcb, 0x51, 0x53, 0x79, 0x29, 0x33, 0x95, 0x6f, 0x43, 0xed, 0x88, + 0x33, 0x22, 0xcb, 0xa5, 0xf9, 0x5a, 0x32, 0x40, 0x82, 0x86, 0x87, 0x1e, 0xb2, 0x46, 0x45, 0x40, + 0x99, 0x4b, 0x94, 0x59, 0x65, 0x42, 0x89, 0x41, 0x7c, 0x49, 0x7b, 0xa7, 0xed, 0x78, 0x4e, 0xcc, + 0xe3, 0xdb, 0x50, 0xf2, 0x60, 0xae, 0x4e, 0x0f, 0x0c, 0xe7, 0xa8, 0x49, 0x02, 0x3c, 0x6e, 0xa5, + 0xdb, 0x44, 0x2e, 0xf3, 0xca, 0x7d, 0x77, 0xe5, 0x47, 0xe6, 0x95, 0x6c, 0xf8, 0x21, 0x5c, 0x09, + 0x9d, 0x23, 0x27, 0x74, 0xfc, 0x91, 0x63, 0x9b, 0x99, 0x69, 0xcb, 0x33, 0xe4, 0x72, 0x8a, 0xec, + 0x24, 0x13, 0x78, 0x0f, 0xb4, 0xa4, 0xae, 0x26, 0xb3, 0x4e, 0x9a, 0x36, 0x8d, 0x87, 0x6f, 0xfe, + 0xe0, 0x67, 0xfb, 0x44, 0x6a, 0x34, 0x54, 0xc5, 0x39, 0x2d, 0x8b, 0xe3, 0xea, 0xab, 0xe2, 0xaa, + 0x3f, 0xa9, 0x38, 0x6e, 0x0b, 0xa7, 0xf5, 0x21, 0x54, 0x13, 0x12, 0x51, 0x87, 0x8a, 0xd1, 0x96, + 0x96, 0x8b, 0x4b, 0xa2, 0x06, 0xe5, 0x56, 0x73, 0xd0, 0x6a, 0x6e, 0x23, 0x03, 0xab, 0x43, 0x65, + 0xd0, 0x1e, 0xb2, 0xb5, 0x62, 0x49, 0xac, 0x41, 0x0d, 0x53, 0xdb, 0xed, 0x9d, 0xe6, 0x41, 0x77, + 0xa8, 0x15, 0xc5, 0x2a, 0x54, 0x7b, 0x7d, 0xb3, 0xd9, 0x1a, 0x76, 0xfa, 0x3d, 0xad, 0xa4, 0x7b, + 0xb0, 0x36, 0xf3, 0x61, 0xe4, 0x9a, 0x8c, 0x36, 0xfb, 0x46, 0xe7, 0x49, 0xa7, 0x67, 0xb6, 0xbf, + 0xde, 0xef, 0x76, 0x5a, 0x1d, 0xfc, 0xd2, 0x75, 0xb8, 0x92, 0xc7, 0xa9, 0x82, 0x0b, 0x42, 0x87, + 0x5b, 0x79, 0x54, 0xb7, 0xfd, 0xa4, 0xd9, 0xfa, 0xc6, 0x6c, 0xee, 0x6d, 0x75, 0x9e, 0x1c, 0xf4, + 0x0f, 0x06, 0xda, 0x92, 0x6e, 0x42, 0xa5, 0x75, 0xe2, 0x8c, 0x4e, 0x5f, 0x36, 0x0b, 0xc9, 0x64, + 0xed, 0x8c, 0x4e, 0xa5, 0x06, 0x3a, 0x63, 0xb2, 0x76, 0x46, 0xa7, 0xb8, 0x18, 0xd5, 0x4e, 0xf7, + 0x9d, 0x27, 0x6d, 0x71, 0x55, 0xb9, 0xcd, 0x7d, 0xe7, 0xe9, 0x6d, 0xa8, 0xee, 0x5b, 0x61, 0xec, + 0x52, 0x27, 0x3d, 0x86, 0xd5, 0x24, 0xb1, 0xed, 0x1c, 0x29, 0xf1, 0x56, 0x24, 0x6a, 0x6b, 0x82, + 0x32, 0xf2, 0x84, 0xfa, 0xfb, 0x50, 0xcf, 0x02, 0xc4, 0x4d, 0x28, 0xda, 0xce, 0xd1, 0x82, 0xed, + 0x17, 0xc1, 0xfa, 0x33, 0xa8, 0xb7, 0x94, 0xb8, 0xf6, 0xb2, 0x96, 0x3d, 0x84, 0x06, 0x71, 0xe4, + 0xd1, 0xa1, 0x62, 0xc9, 0x4b, 0x0b, 0x58, 0x72, 0x1d, 0x69, 0x5a, 0x87, 0x92, 0x27, 0x7f, 0x0a, + 0xb5, 0xfd, 0x30, 0x98, 0x38, 0x61, 0x4c, 0xc5, 0x6a, 0x50, 0x3c, 0x75, 0x2e, 0x64, 0xa9, 0xf8, + 0x33, 0x3d, 0x68, 0x58, 0xca, 0x1e, 0x34, 0x3c, 0x84, 0x8a, 0xca, 0xf6, 0xa3, 0xf3, 0xfc, 0x1c, + 0xb7, 0x36, 0xca, 0xe3, 0x3a, 0x11, 0x7e, 0xec, 0x01, 0xc0, 0x24, 0x01, 0xc8, 0x8e, 0x53, 0xfa, + 0xbe, 0x2c, 0xdc, 0xc8, 0x50, 0xe8, 0xaf, 0x43, 0xf9, 0x99, 0xeb, 0x9c, 0xc9, 0xe6, 0xbf, 0x70, + 0x9d, 0x33, 0xd5, 0x7c, 0xfc, 0xad, 0xff, 0x17, 0x00, 0x15, 0xe2, 0x7f, 0xdb, 0x2f, 0x3f, 0xdb, + 0xf9, 0x29, 0xaa, 0xc3, 0x1d, 0xc9, 0xae, 0x4a, 0x0b, 0x14, 0x16, 0x66, 0x5e, 0xaf, 0x03, 0x64, + 0x78, 0x31, 0xef, 0x2c, 0xd5, 0x38, 0x61, 0xc1, 0x28, 0x73, 0x93, 0x14, 0x83, 0xd3, 0x88, 0xcd, + 0xae, 0x29, 0x40, 0x3c, 0x60, 0x89, 0x98, 0x0c, 0xad, 0xac, 0x35, 0x5c, 0x56, 0x5a, 0xfd, 0xa1, + 0xe7, 0x28, 0x5b, 0x03, 0x89, 0xc9, 0x98, 0xa0, 0x7d, 0xc6, 0x09, 0x23, 0xdc, 0x4e, 0xe4, 0xb1, + 0xbf, 0x4c, 0x8a, 0x77, 0xa0, 0x84, 0x9b, 0xb0, 0xb4, 0x0d, 0x5c, 0x56, 0x3d, 0x98, 0x91, 0x22, + 0x0c, 0x22, 0x10, 0xf7, 0xa0, 0x4c, 0x5c, 0xca, 0xc1, 0x9d, 0x20, 0xd3, 0xdb, 0x6a, 0x53, 0x36, + 0x14, 0x5a, 0xbc, 0x0b, 0xcb, 0x47, 0xa7, 0xce, 0x05, 0x6f, 0x03, 0x49, 0x99, 0x39, 0x66, 0x62, + 0x30, 0x85, 0xb8, 0x0b, 0x8d, 0xd0, 0x39, 0x32, 0xe9, 0xb4, 0x07, 0x79, 0x78, 0xb4, 0xd9, 0x20, + 0x16, 0x5d, 0x0f, 0x9d, 0xa3, 0x16, 0x02, 0x87, 0x87, 0x5e, 0x24, 0xde, 0x86, 0x15, 0x5a, 0x5c, + 0xa8, 0x30, 0x64, 0xbe, 0xac, 0x56, 0xaa, 0x21, 0xb1, 0xe2, 0x63, 0x00, 0xa9, 0x96, 0x98, 0x87, + 0x17, 0x24, 0x7c, 0x27, 0x8b, 0x29, 0x3b, 0xff, 0xb3, 0xca, 0xcb, 0x3b, 0xb0, 0x8c, 0x93, 0x24, + 0xda, 0xbc, 0x46, 0x25, 0xaf, 0xe7, 0x67, 0x10, 0xd5, 0x94, 0xf0, 0xe2, 0x1e, 0x54, 0x70, 0xa2, + 0xd0, 0xaa, 0xde, 0xcc, 0xea, 0x69, 0x72, 0x56, 0xe1, 0xce, 0xed, 0x9c, 0x0d, 0xbe, 0xf3, 0xc4, + 0x7d, 0x28, 0xd9, 0xb8, 0x98, 0xaf, 0x53, 0x89, 0x57, 0x33, 0xe3, 0x82, 0x5c, 0x74, 0xdb, 0x39, + 0x22, 0xd5, 0x91, 0x68, 0xc4, 0x2e, 0x34, 0x70, 0x1a, 0x3d, 0x24, 0x61, 0x0c, 0xbb, 0x6f, 0xf3, + 0x06, 0xe5, 0x7a, 0x63, 0x26, 0x57, 0x4f, 0x12, 0x51, 0x67, 0xb7, 0xfd, 0x38, 0xbc, 0x30, 0x56, + 0xfd, 0x2c, 0x4c, 0xdc, 0x80, 0x8a, 0x1b, 0x75, 0x83, 0xd1, 0x69, 0x72, 0xb0, 0x9c, 0xa4, 0xc5, + 0x17, 0xb0, 0x4a, 0x13, 0x0b, 0x93, 0xf8, 0x71, 0x79, 0xaa, 0x9c, 0x9d, 0x32, 0x0a, 0x65, 0xe4, + 0x29, 0x71, 0x07, 0x75, 0x23, 0x33, 0x76, 0xc6, 0x93, 0x20, 0x44, 0x0d, 0xef, 0x75, 0x75, 0x42, + 0x31, 0x54, 0x20, 0x14, 0x94, 0x12, 0x8f, 0x16, 0x33, 0x38, 0x3a, 0x8a, 0x9c, 0x98, 0x4e, 0x91, + 0x4b, 0x46, 0x43, 0x39, 0xb6, 0xf4, 0x09, 0x4a, 0x82, 0x4a, 0x64, 0xda, 0x17, 0xbe, 0x35, 0x76, + 0x47, 0x9b, 0xb7, 0x59, 0x91, 0x74, 0xa3, 0x6d, 0x06, 0x64, 0x75, 0xb9, 0x3b, 0x39, 0x5d, 0xee, + 0x32, 0x2c, 0xdb, 0x87, 0xb8, 0x1c, 0xdf, 0xa0, 0x62, 0x4b, 0xf6, 0x61, 0xc7, 0x16, 0x1f, 0x90, + 0x95, 0x99, 0x59, 0xe0, 0xa6, 0x9e, 0xb5, 0xc6, 0x25, 0x9c, 0xd1, 0x48, 0x29, 0xc4, 0x1d, 0xa8, + 0xed, 0x38, 0x56, 0x3c, 0x0d, 0x9d, 0x1d, 0xcf, 0x3a, 0xde, 0x7c, 0x93, 0x4a, 0xca, 0x82, 0xb0, + 0x76, 0x5e, 0x70, 0xec, 0x8e, 0x2c, 0x5a, 0xf9, 0x77, 0x59, 0x2e, 0x96, 0x90, 0x8e, 0x9d, 0xaa, + 0x30, 0x96, 0x14, 0x76, 0xdf, 0xca, 0xaa, 0x30, 0x96, 0xa7, 0x8e, 0x63, 0xd2, 0xbe, 0x70, 0x26, + 0xc1, 0xe8, 0x64, 0xf3, 0x6d, 0x5a, 0x6f, 0xab, 0xaa, 0x2b, 0xda, 0x08, 0x14, 0xef, 0xc0, 0x9a, + 0x54, 0xeb, 0x4d, 0xe5, 0x8e, 0xf3, 0x0e, 0xd1, 0x35, 0x24, 0xb8, 0x25, 0xbd, 0x72, 0x74, 0x58, + 0xe5, 0x02, 0x6d, 0x73, 0x64, 0x8d, 0x4e, 0x9c, 0xcd, 0x7b, 0x5c, 0x71, 0x2a, 0xce, 0x6e, 0x21, + 0xe8, 0xc6, 0x13, 0x52, 0x28, 0x69, 0xb8, 0x3e, 0x9d, 0xe1, 0x8a, 0xb9, 0x35, 0x9d, 0x61, 0x9f, + 0xbb, 0x97, 0xb2, 0xcc, 0x71, 0x6b, 0x99, 0xb6, 0x8f, 0x1b, 0xbf, 0x00, 0x31, 0x3f, 0xd1, 0x5e, + 0xc5, 0xa2, 0x97, 0x25, 0x8b, 0xfe, 0x72, 0xe9, 0x71, 0x41, 0xff, 0x1f, 0x0a, 0xb0, 0x9a, 0x63, + 0x41, 0x0b, 0xf7, 0x1a, 0x16, 0xc4, 0xad, 0xb1, 0x34, 0x64, 0x71, 0x42, 0xa9, 0x7f, 0xae, 0x7f, + 0xec, 0x39, 0x19, 0xf5, 0x8f, 0xd2, 0xe2, 0xe7, 0x70, 0xf9, 0x68, 0xea, 0x79, 0xb1, 0x73, 0x1e, + 0x2b, 0xb3, 0x7e, 0xe8, 0x1c, 0x49, 0x3b, 0xee, 0xdc, 0x21, 0xd3, 0xba, 0xa2, 0x65, 0xd3, 0x96, + 0xe1, 0x1c, 0x89, 0xdf, 0x06, 0x91, 0x14, 0xc0, 0xd2, 0x16, 0xe6, 0x5f, 0x5e, 0x9c, 0x5f, 0x53, + 0xa4, 0xd4, 0x0d, 0x86, 0x73, 0xa4, 0xff, 0x37, 0x45, 0xa8, 0xef, 0x5a, 0xd1, 0xc9, 0x9e, 0x35, + 0x19, 0xc4, 0x56, 0x1c, 0xe1, 0xc2, 0x38, 0xb1, 0xa2, 0x93, 0xb1, 0x35, 0x61, 0x65, 0xb1, 0xc0, + 0x16, 0x47, 0x09, 0x23, 0x4d, 0xf1, 0x06, 0x54, 0x30, 0xd9, 0xf7, 0xf7, 0x9f, 0x4a, 0xf3, 0x5f, + 0x92, 0x46, 0x86, 0x1c, 0x9d, 0x4c, 0x8f, 0x8e, 0x92, 0xa6, 0xaa, 0xa4, 0xb8, 0x0b, 0xab, 0xf2, + 0x27, 0xe9, 0x63, 0xe7, 0xf2, 0xb4, 0x23, 0x0f, 0x14, 0x8f, 0xa0, 0x26, 0x01, 0x43, 0xb5, 0x7d, + 0x34, 0x12, 0x33, 0x71, 0x8a, 0x30, 0xb2, 0x54, 0xe2, 0x97, 0x70, 0x25, 0x93, 0xdc, 0x09, 0xc2, + 0xbd, 0xa9, 0x17, 0xbb, 0xad, 0x9e, 0x94, 0x5d, 0x5f, 0x9b, 0xcb, 0x9e, 0x92, 0x18, 0x8b, 0x73, + 0xe6, 0x6b, 0xbb, 0xe7, 0xfa, 0xb4, 0x1b, 0x15, 0x8d, 0x3c, 0x70, 0x86, 0xca, 0x3a, 0xa7, 0x4d, + 0x28, 0x4f, 0x65, 0x9d, 0x23, 0x9b, 0x92, 0x80, 0x3d, 0x27, 0x3e, 0x09, 0x6c, 0x29, 0x8c, 0x5e, + 0xce, 0x55, 0x8b, 0x51, 0x46, 0x9e, 0x12, 0xbb, 0xd3, 0x9f, 0x7a, 0xde, 0xc8, 0x8f, 0x49, 0xff, + 0x29, 0x1a, 0x2a, 0x89, 0x1b, 0x74, 0x68, 0xf9, 0xc7, 0x4e, 0xb4, 0x59, 0xbb, 0x53, 0xbc, 0x57, + 0x30, 0x64, 0x4a, 0xff, 0xdb, 0x4b, 0xb0, 0xcc, 0x23, 0xf9, 0x1a, 0x54, 0x0f, 0xe9, 0x0c, 0xdb, + 0x9f, 0x8e, 0xd5, 0x59, 0x33, 0x01, 0x7a, 0xd3, 0x31, 0xab, 0x1d, 0xd2, 0x7c, 0x5b, 0x30, 0xe8, + 0x37, 0x16, 0x19, 0x4c, 0x63, 0xfc, 0x56, 0x91, 0xa0, 0x32, 0x85, 0x95, 0x08, 0x83, 0x33, 0x9a, + 0x0d, 0x25, 0x42, 0xa8, 0x24, 0x1d, 0x67, 0xd3, 0x5e, 0x8f, 0x99, 0x96, 0x09, 0x57, 0x21, 0x40, + 0xcb, 0x8f, 0x67, 0x4d, 0xd7, 0x2b, 0xf3, 0xa6, 0xeb, 0x5b, 0x80, 0x4a, 0xcd, 0xc8, 0xe9, 0xfb, + 0x4e, 0xab, 0x27, 0xcf, 0x95, 0x32, 0x10, 0x5c, 0xa1, 0x76, 0x30, 0x91, 0x07, 0x46, 0xf8, 0x53, + 0x7c, 0x96, 0xcc, 0x4e, 0x6a, 0xa3, 0xd4, 0x21, 0xe5, 0x5e, 0x98, 0x9d, 0xc7, 0x46, 0x8e, 0x0e, + 0x4b, 0xc2, 0x0d, 0x8e, 0x75, 0x48, 0xfc, 0xa9, 0xb7, 0x01, 0x8c, 0xe0, 0x2c, 0x72, 0x62, 0x3a, + 0xa3, 0xb9, 0x46, 0x4d, 0xcc, 0x79, 0xae, 0x04, 0x67, 0xfb, 0x41, 0x94, 0x18, 0x80, 0xe6, 0xe5, + 0x62, 0x82, 0xeb, 0x1f, 0x42, 0x19, 0xa5, 0x1f, 0x2b, 0xb6, 0xc4, 0x5d, 0x69, 0xc5, 0x66, 0x99, + 0x4d, 0x53, 0xe7, 0xa7, 0xea, 0x1b, 0xd2, 0x18, 0xde, 0x55, 0xdf, 0xa5, 0x3c, 0x6f, 0x64, 0x0c, + 0x19, 0xc9, 0xce, 0x2b, 0x0b, 0x94, 0xf2, 0xd4, 0x6b, 0x50, 0xc5, 0xaa, 0xd1, 0x11, 0xbd, 0x3a, + 0x75, 0x0c, 0x83, 0xb3, 0x16, 0xa6, 0xf5, 0x7f, 0x5c, 0x80, 0x5a, 0x3f, 0xb4, 0x71, 0xcb, 0x1f, + 0x4c, 0x9c, 0xd1, 0x2b, 0xed, 0x55, 0x28, 0x7d, 0x05, 0x9e, 0x67, 0xd1, 0xe6, 0x22, 0x0d, 0x09, + 0x09, 0x40, 0x7c, 0x0c, 0xa5, 0x23, 0xdc, 0x44, 0x8a, 0x59, 0x95, 0x2f, 0x53, 0xbc, 0xfa, 0x8d, + 0xdb, 0x8a, 0x41, 0xa4, 0xfa, 0xef, 0x26, 0xdf, 0xa7, 0xbd, 0x26, 0x7b, 0xfc, 0x7b, 0x89, 0xdc, + 0x4f, 0x06, 0x2d, 0xad, 0x20, 0x2a, 0x50, 0xda, 0x6e, 0x0f, 0x5a, 0xac, 0x16, 0xa1, 0x82, 0x34, + 0x30, 0x77, 0x3a, 0xc6, 0x60, 0xa8, 0x95, 0xc8, 0x9f, 0x85, 0x00, 0xdd, 0xe6, 0x60, 0xa8, 0x55, + 0x04, 0xc0, 0xca, 0x41, 0xaf, 0xf3, 0xcb, 0x83, 0xb6, 0xa6, 0xe9, 0xff, 0xa8, 0x00, 0x90, 0x9e, + 0x1f, 0x89, 0xf7, 0xa0, 0x76, 0x46, 0x29, 0x33, 0x73, 0x10, 0x9f, 0x6d, 0x23, 0x30, 0x9a, 0x24, + 0xc3, 0x0f, 0xa0, 0x9e, 0x6c, 0x92, 0x28, 0x35, 0xcd, 0x9f, 0xc8, 0xd7, 0x12, 0xfc, 0xd6, 0x85, + 0x78, 0x1f, 0x2a, 0x01, 0xb6, 0x03, 0x49, 0x8b, 0x59, 0x91, 0x29, 0xd3, 0x7c, 0xa3, 0x1c, 0x70, + 0x02, 0xa5, 0xab, 0xa3, 0x50, 0x19, 0x86, 0x12, 0xd2, 0x1d, 0x04, 0xb5, 0x3c, 0x6b, 0x1a, 0x39, + 0x06, 0xe3, 0x93, 0x5d, 0x62, 0x39, 0xdd, 0x25, 0xf4, 0x5f, 0x41, 0x63, 0x60, 0x8d, 0x27, 0xbc, + 0x97, 0x50, 0xc3, 0x04, 0x94, 0x70, 0x4e, 0xc8, 0xa9, 0x47, 0xbf, 0x71, 0xd1, 0xed, 0x3b, 0xe1, + 0xc8, 0xf1, 0xd5, 0x1a, 0x55, 0x49, 0x64, 0xbf, 0x07, 0xb8, 0x9b, 0x18, 0xc1, 0x99, 0xda, 0x4e, + 0x54, 0x5a, 0xff, 0xb7, 0x0b, 0x50, 0xcb, 0x54, 0x43, 0x7c, 0x08, 0x25, 0x12, 0xc3, 0x0b, 0x59, + 0x46, 0x98, 0x21, 0xe0, 0xdf, 0x2c, 0xb8, 0x21, 0xa1, 0x78, 0x1b, 0x96, 0xa3, 0xd8, 0x0a, 0xd5, + 0x51, 0xa4, 0x96, 0xc9, 0xb1, 0x15, 0x4c, 0x7d, 0xdb, 0x60, 0xb4, 0xd0, 0xa1, 0xe8, 0xf8, 0xb6, + 0x34, 0xa5, 0xcd, 0x53, 0x21, 0x52, 0xbf, 0x03, 0xd5, 0xa4, 0x78, 0x9c, 0x02, 0x46, 0xff, 0xf9, + 0x40, 0xbb, 0x24, 0xaa, 0xb0, 0x6c, 0x34, 0x7b, 0x4f, 0xda, 0x5a, 0x41, 0xff, 0xbb, 0x05, 0x80, + 0x34, 0x97, 0x78, 0x90, 0xab, 0xed, 0x8d, 0xd9, 0x52, 0x1f, 0xd0, 0xdf, 0x4c, 0x65, 0x6f, 0x42, + 0x75, 0xea, 0x13, 0xd0, 0xb1, 0xe5, 0x4e, 0x94, 0x02, 0x50, 0x77, 0x54, 0xbe, 0xb5, 0x33, 0xba, + 0xe3, 0x0b, 0xcb, 0xd3, 0xbf, 0x84, 0x6a, 0x52, 0x1c, 0xea, 0xe6, 0x3b, 0xfd, 0x6e, 0xb7, 0xff, + 0xbc, 0xd3, 0x7b, 0xa2, 0x5d, 0xc2, 0xe4, 0xbe, 0xd1, 0x6e, 0xb5, 0xb7, 0x31, 0x59, 0xc0, 0x39, + 0xdb, 0x3a, 0x30, 0x8c, 0x76, 0x6f, 0x68, 0x1a, 0xfd, 0xe7, 0xda, 0x92, 0xfe, 0xfb, 0x05, 0x58, + 0xed, 0x7b, 0x76, 0x2b, 0xf0, 0x5a, 0xd6, 0x04, 0xe5, 0x2c, 0xf1, 0x73, 0x58, 0x3f, 0x9c, 0xa2, + 0xac, 0x3f, 0xf1, 0xac, 0x91, 0x73, 0x12, 0x78, 0xb6, 0xa3, 0x16, 0x61, 0xee, 0xb0, 0x55, 0x9e, + 0x9d, 0x68, 0x44, 0xbc, 0x9f, 0xd2, 0x8a, 0x4f, 0xa1, 0x3e, 0x09, 0x83, 0x43, 0x47, 0x1d, 0x64, + 0xcd, 0x2a, 0xa9, 0x69, 0xde, 0x1a, 0xd1, 0xc9, 0x43, 0xe6, 0xff, 0x72, 0x19, 0xea, 0xdb, 0x8e, + 0x3d, 0x9d, 0x7c, 0x15, 0xb8, 0x7e, 0x2b, 0x3e, 0x17, 0x9f, 0x40, 0x3d, 0xf0, 0xc8, 0x60, 0x65, + 0x66, 0xdc, 0xe6, 0x16, 0x95, 0x03, 0x01, 0xb5, 0x80, 0x9c, 0xec, 0x3e, 0x80, 0xcb, 0xd2, 0x5c, + 0xc2, 0xd6, 0xd3, 0x73, 0xce, 0x8c, 0x6b, 0x66, 0xd9, 0xd0, 0x18, 0xc5, 0x1b, 0x34, 0x91, 0xff, + 0x16, 0x6c, 0x64, 0xc8, 0x91, 0xb1, 0x30, 0x7d, 0x71, 0x6e, 0x8d, 0xad, 0x27, 0x79, 0x13, 0x87, + 0xbe, 0xaf, 0x60, 0x43, 0xd5, 0x70, 0xc4, 0xbd, 0xc7, 0x99, 0x4b, 0x59, 0xa5, 0x2a, 0xd7, 0xbb, + 0xb2, 0xc2, 0xeb, 0x41, 0x16, 0x48, 0x65, 0x7d, 0x0c, 0x57, 0x6c, 0x6c, 0xbd, 0xc9, 0x9d, 0x7f, + 0xea, 0x38, 0x13, 0xd3, 0xcb, 0x78, 0xbb, 0x10, 0x72, 0x0b, 0x71, 0x4f, 0x1d, 0x67, 0xd2, 0xb5, + 0xa2, 0x58, 0x3c, 0x86, 0x75, 0xeb, 0xe8, 0xc8, 0x19, 0xc5, 0x8e, 0x6d, 0xe2, 0x36, 0xb6, 0xd0, + 0x4a, 0x8b, 0xb2, 0xd2, 0x9a, 0x22, 0xc3, 0xe5, 0xd8, 0x0a, 0x3c, 0xf1, 0x04, 0xae, 0x4f, 0x4e, + 0x2e, 0x22, 0x12, 0xa4, 0x47, 0x27, 0xb8, 0xdb, 0x66, 0x4a, 0x28, 0x2f, 0x28, 0xe1, 0xaa, 0x22, + 0x6f, 0x31, 0xb5, 0x2a, 0xe8, 0x31, 0x5c, 0x57, 0xdd, 0x87, 0xfa, 0x5d, 0xbe, 0xcf, 0x2b, 0xd4, + 0xe7, 0x57, 0x64, 0xbf, 0x21, 0x3e, 0xd3, 0xf1, 0xf7, 0x40, 0x63, 0xf7, 0xad, 0x23, 0x9c, 0xba, + 0xf4, 0x75, 0xe9, 0xd2, 0xde, 0x20, 0xf8, 0x0e, 0x2d, 0x3e, 0x64, 0x1f, 0xf7, 0x40, 0x73, 0xc6, + 0x6e, 0x6c, 0x5a, 0x24, 0xad, 0x32, 0x25, 0x9f, 0x8a, 0x35, 0x10, 0x2e, 0xcd, 0x76, 0x48, 0xf9, + 0x19, 0x68, 0x92, 0xe8, 0x88, 0x74, 0x00, 0x6c, 0x4d, 0x6d, 0x41, 0x6b, 0x1a, 0x4c, 0xb5, 0x83, + 0x44, 0xd8, 0x8a, 0x3d, 0x10, 0xca, 0x06, 0x49, 0x96, 0x15, 0x56, 0x64, 0x59, 0x85, 0x96, 0xee, + 0x4a, 0xfd, 0xed, 0xa7, 0x07, 0xa9, 0x7a, 0x4c, 0x8d, 0x51, 0x0b, 0xe0, 0x28, 0x0f, 0x8e, 0xf4, + 0xff, 0x7c, 0x05, 0xaa, 0x6c, 0x76, 0xc3, 0x69, 0x7c, 0x0f, 0xca, 0xc1, 0xe1, 0xb7, 0x24, 0xca, + 0xbe, 0xc4, 0xdf, 0x6a, 0x25, 0x38, 0xfc, 0x16, 0xe5, 0xdf, 0xf7, 0x94, 0x08, 0x62, 0x3b, 0x47, + 0x72, 0xd5, 0x34, 0xf2, 0x4a, 0xa6, 0x14, 0x49, 0xb6, 0x9d, 0x23, 0x94, 0x2e, 0x5d, 0x3f, 0x72, + 0xc2, 0x98, 0xcd, 0xa6, 0xe5, 0x97, 0x2f, 0x0e, 0x26, 0x23, 0x4b, 0xea, 0x23, 0xa8, 0x49, 0xd3, + 0x24, 0x65, 0xaa, 0xbc, 0x3c, 0x13, 0x93, 0x51, 0xa6, 0x2f, 0xa0, 0x91, 0x6e, 0x3f, 0x94, 0xaf, + 0xfa, 0xd2, 0x7c, 0xab, 0x09, 0x25, 0x65, 0x7d, 0x08, 0x57, 0xa3, 0x53, 0x77, 0x62, 0xca, 0x9a, + 0x06, 0x3e, 0x1d, 0xaf, 0x9a, 0x93, 0x53, 0x39, 0x80, 0x02, 0xb1, 0x1d, 0x42, 0xf6, 0xfd, 0xde, + 0xd4, 0xf3, 0xf6, 0x4f, 0xc5, 0xbb, 0xb0, 0x2e, 0xc9, 0x27, 0xc9, 0x7c, 0xa2, 0x51, 0x5c, 0x36, + 0x1a, 0x8c, 0xd8, 0x97, 0xf3, 0x48, 0x7c, 0x0e, 0x9b, 0x3c, 0x87, 0x64, 0xa3, 0x78, 0x9a, 0xf3, + 0x0c, 0xe1, 0x33, 0xd0, 0x2b, 0x84, 0x67, 0x93, 0x6a, 0x93, 0xb0, 0x34, 0x51, 0x3e, 0x82, 0x0d, + 0xf7, 0xd8, 0x0f, 0x42, 0x95, 0x45, 0x4e, 0x7f, 0x79, 0x38, 0x2a, 0x18, 0xd7, 0xcc, 0x2c, 0x1a, + 0x6c, 0x89, 0x5c, 0x9e, 0x17, 0x66, 0x4c, 0x6e, 0x19, 0x98, 0x03, 0xb5, 0xd0, 0x46, 0x76, 0x7d, + 0x5e, 0xb0, 0xcb, 0x86, 0x11, 0x9c, 0x75, 0x6c, 0x5c, 0xd2, 0x92, 0x54, 0xad, 0x91, 0xf8, 0x9c, + 0x5a, 0xb3, 0x46, 0xad, 0x11, 0x8c, 0x4c, 0x66, 0x0a, 0xb6, 0xe8, 0x17, 0x20, 0xe6, 0x96, 0x74, + 0xb4, 0xa9, 0xbd, 0xb4, 0xbf, 0xb5, 0x99, 0x95, 0x4d, 0x6b, 0x60, 0x6e, 0x45, 0xaf, 0x2f, 0x5a, + 0x03, 0xa3, 0xfc, 0x4a, 0x6e, 0xc3, 0x66, 0xfe, 0xcb, 0x67, 0x8e, 0x7b, 0x7c, 0x42, 0xb3, 0x4b, + 0xde, 0x16, 0xc8, 0xe7, 0xbf, 0x92, 0xfd, 0xf2, 0x73, 0xa2, 0x7d, 0x25, 0x67, 0xb9, 0xfc, 0xe3, + 0x39, 0x8b, 0xfe, 0xef, 0x16, 0xa0, 0xca, 0x33, 0x03, 0x17, 0xd1, 0x1b, 0x50, 0xfc, 0x81, 0x05, + 0x84, 0x38, 0x71, 0x1f, 0xd6, 0x2d, 0xdb, 0x9e, 0x19, 0x50, 0xde, 0x49, 0xd7, 0x2c, 0xdb, 0xce, + 0x8d, 0xe6, 0x3d, 0xd0, 0xdc, 0xc8, 0x54, 0x86, 0xa8, 0xd4, 0x27, 0xb3, 0x62, 0x34, 0xdc, 0x48, + 0xda, 0xa1, 0xf8, 0x54, 0x32, 0xb7, 0x26, 0x4b, 0x3f, 0xbc, 0x26, 0x75, 0x01, 0x60, 0x38, 0xb4, + 0x6d, 0xb6, 0xe2, 0xf3, 0xaf, 0x4a, 0x95, 0x82, 0x06, 0xfa, 0x7f, 0x55, 0x83, 0x5a, 0xd3, 0xb7, + 0xbc, 0x8b, 0xef, 0x1d, 0x72, 0x28, 0xa5, 0x93, 0xa0, 0xc9, 0x54, 0xce, 0x52, 0xf6, 0xb0, 0xa8, + 0x12, 0x84, 0x6a, 0x76, 0x1b, 0x6a, 0xc1, 0x34, 0x4e, 0xf0, 0xec, 0x73, 0x01, 0x0c, 0x22, 0x82, + 0x24, 0x7f, 0x72, 0xfe, 0xa9, 0xf2, 0x93, 0x42, 0x9b, 0xe6, 0x4f, 0x94, 0x9c, 0x24, 0x3f, 0x11, + 0xbc, 0x09, 0xab, 0xb1, 0x3b, 0x76, 0xc8, 0xe5, 0x65, 0x3a, 0x76, 0x6c, 0xbe, 0x7c, 0xc3, 0xf7, + 0x39, 0x5a, 0x12, 0x86, 0xa5, 0x8c, 0x9d, 0x71, 0x10, 0x5e, 0x70, 0x29, 0x2b, 0x5c, 0x0a, 0x83, + 0xa8, 0x94, 0xf7, 0x41, 0x9c, 0x59, 0x6e, 0x6c, 0xe6, 0x8b, 0x62, 0xc5, 0x52, 0x43, 0xcc, 0x30, + 0x5b, 0xdc, 0x55, 0x58, 0xb1, 0xdd, 0xe8, 0xb4, 0xd3, 0x97, 0x4a, 0xa5, 0x4c, 0x61, 0x5b, 0xa2, + 0x91, 0x85, 0x32, 0x6d, 0xec, 0x30, 0xf7, 0x2f, 0x1a, 0x55, 0x84, 0x6c, 0x21, 0x00, 0x65, 0x22, + 0xdf, 0x89, 0xcf, 0x82, 0x10, 0x73, 0xb2, 0xce, 0x98, 0x02, 0x50, 0x76, 0x44, 0x52, 0xfc, 0x10, + 0xb1, 0x87, 0xa2, 0x91, 0xa4, 0x51, 0x1b, 0x63, 0x56, 0x41, 0xd8, 0x3a, 0x57, 0x3f, 0x85, 0x88, + 0xbb, 0xd0, 0xa0, 0xea, 0x93, 0x4e, 0x89, 0x6d, 0xa0, 0x95, 0x5f, 0x34, 0xea, 0x08, 0x25, 0xc3, + 0x1a, 0x52, 0x7d, 0x01, 0xd7, 0x73, 0xed, 0x33, 0xad, 0x30, 0xb4, 0x2e, 0xcc, 0xb1, 0xf5, 0x6d, + 0x10, 0x92, 0x11, 0xb4, 0x68, 0x5c, 0xcd, 0x76, 0x5b, 0x13, 0xd1, 0x7b, 0x88, 0x7d, 0x69, 0x56, + 0xd7, 0x0f, 0x42, 0xb2, 0x90, 0x2e, 0xcc, 0x8a, 0x58, 0x32, 0xe7, 0xd1, 0x00, 0x93, 0x82, 0x1b, + 0xf1, 0x3d, 0x20, 0xa3, 0x46, 0xb0, 0x2d, 0x02, 0xa1, 0x8a, 0x17, 0x3d, 0xe2, 0x3d, 0x76, 0x5d, + 0x7a, 0xb3, 0x3f, 0xa2, 0x4d, 0x95, 0x11, 0x27, 0x8e, 0x65, 0xd3, 0x9a, 0x25, 0xc4, 0xae, 0x63, + 0x91, 0x93, 0x56, 0xf4, 0xc8, 0x9c, 0x4c, 0x63, 0xbe, 0xc0, 0x63, 0x2c, 0x47, 0x8f, 0xf6, 0xa7, + 0xb1, 0x04, 0x1f, 0x3b, 0x31, 0x79, 0x56, 0x10, 0xf8, 0x09, 0xdf, 0x33, 0x8b, 0x1e, 0xa9, 0x03, + 0xb7, 0x2b, 0xb2, 0x6f, 0x1f, 0xc9, 0x13, 0x35, 0x1d, 0x56, 0x13, 0xa4, 0x39, 0x9e, 0xf2, 0x8d, + 0x9d, 0xa2, 0x51, 0x53, 0x04, 0x7b, 0x53, 0x0f, 0x07, 0x96, 0x4c, 0x61, 0x66, 0x88, 0x55, 0xb9, + 0xc6, 0x43, 0x47, 0x10, 0x03, 0x6b, 0xf3, 0x1a, 0x70, 0xc2, 0x3c, 0x71, 0x63, 0xb2, 0xd4, 0x16, + 0x8d, 0x0a, 0x01, 0x76, 0xdd, 0x18, 0xd7, 0x31, 0x23, 0xe5, 0x0c, 0xa4, 0x22, 0xae, 0x13, 0xd1, + 0x1a, 0x21, 0xf6, 0x08, 0x4e, 0x05, 0xa1, 0x10, 0x91, 0xa5, 0xc5, 0xf2, 0x6e, 0x10, 0x69, 0x23, + 0x43, 0x8a, 0xa5, 0xbe, 0x0d, 0x9c, 0xd9, 0xc4, 0xa9, 0xc7, 0x65, 0xbe, 0xc6, 0x06, 0x0e, 0x02, + 0x6f, 0xbb, 0xd1, 0x29, 0x95, 0x78, 0x17, 0x1a, 0x19, 0x3a, 0x2c, 0xef, 0x26, 0xcf, 0x8c, 0x84, + 0x2c, 0x57, 0xc7, 0xd0, 0x19, 0x07, 0xb1, 0x6c, 0xe6, 0xeb, 0x99, 0x3a, 0x1a, 0x04, 0xcf, 0xd7, + 0x51, 0xd2, 0x62, 0x99, 0xb7, 0x32, 0x75, 0x64, 0x52, 0x2c, 0xf5, 0x0d, 0xa8, 0x9f, 0x85, 0x6e, + 0x1c, 0x3b, 0x52, 0xc8, 0xb9, 0xcd, 0x1d, 0x2b, 0x61, 0xb4, 0xfa, 0xdf, 0x80, 0x3a, 0xf7, 0xbc, + 0xe4, 0x6f, 0x77, 0x98, 0x44, 0xc2, 0x14, 0x83, 0x90, 0xbd, 0x31, 0x76, 0x7d, 0x32, 0xc7, 0x16, + 0x8d, 0x2a, 0x43, 0xf6, 0x5c, 0x3f, 0x8b, 0xb6, 0xce, 0xc9, 0x28, 0x9b, 0xa2, 0xad, 0x73, 0x5a, + 0x92, 0x13, 0xd7, 0xf3, 0x78, 0xe1, 0xbf, 0x29, 0x97, 0x24, 0x42, 0x68, 0xdd, 0x27, 0x68, 0xfa, + 0xfa, 0xdd, 0x0c, 0x9a, 0xbe, 0x8d, 0x13, 0x87, 0xd0, 0xf8, 0xe9, 0xb7, 0xe4, 0xc4, 0x41, 0x00, + 0x7e, 0x39, 0x45, 0x5a, 0xe7, 0x64, 0x72, 0x4d, 0x90, 0xd6, 0xb9, 0xe4, 0x5b, 0xb4, 0x53, 0x60, + 0xde, 0x77, 0x12, 0xbe, 0x85, 0x20, 0xcc, 0x9d, 0x25, 0xb0, 0xce, 0xc9, 0xc6, 0x9a, 0x21, 0xb0, + 0xce, 0xc9, 0xb8, 0xe0, 0x58, 0x36, 0x57, 0xfc, 0x5d, 0x2e, 0x1e, 0x01, 0x54, 0xef, 0x3b, 0x50, + 0x8f, 0x1e, 0x99, 0x29, 0xfe, 0x3e, 0x67, 0x8f, 0x1e, 0x19, 0x8a, 0xe2, 0x2e, 0x34, 0x92, 0xa9, + 0xc1, 0x34, 0xef, 0xf1, 0xc0, 0xdb, 0x72, 0x6a, 0xd0, 0x95, 0x96, 0x5f, 0x17, 0xe0, 0x06, 0x1f, + 0x71, 0x12, 0xfb, 0xdf, 0x73, 0xa2, 0xc8, 0x3a, 0x76, 0x76, 0x82, 0x70, 0x67, 0xfa, 0xfd, 0xf7, + 0x17, 0xe2, 0x1e, 0xac, 0xed, 0x5b, 0xa1, 0xe3, 0xc7, 0x89, 0xe7, 0x81, 0x34, 0xaa, 0xce, 0x82, + 0xc5, 0x63, 0xd0, 0x18, 0xc4, 0x9e, 0xfc, 0x2d, 0x75, 0x6e, 0x3e, 0x7b, 0x10, 0x35, 0x47, 0xa5, + 0xff, 0xe3, 0x02, 0x54, 0xb7, 0xdd, 0x28, 0x36, 0x70, 0xbb, 0x14, 0x5f, 0x80, 0xe6, 0x05, 0x67, + 0xa8, 0xec, 0x93, 0x18, 0x9d, 0xd1, 0x39, 0xe5, 0x2e, 0x99, 0x2a, 0x9a, 0x0d, 0x22, 0x4c, 0x35, + 0xc5, 0x2f, 0x40, 0x9b, 0x4e, 0x26, 0xf9, 0xac, 0x4b, 0x2f, 0xc9, 0x4a, 0x84, 0x69, 0xd6, 0xf7, + 0xa0, 0x96, 0xf9, 0xea, 0x02, 0xbd, 0x14, 0xd2, 0x6f, 0x21, 0x71, 0xe6, 0x3b, 0x0b, 0x6e, 0x12, + 0x41, 0x5a, 0xba, 0xfe, 0xef, 0x2f, 0x81, 0x26, 0x2d, 0xba, 0x96, 0xed, 0x84, 0xe4, 0xc0, 0x90, + 0xb3, 0x68, 0x14, 0x5e, 0x69, 0xd1, 0xb8, 0x03, 0xcb, 0x9e, 0x3b, 0x4e, 0x5c, 0x90, 0x73, 0x07, + 0xc0, 0x84, 0xc0, 0xb1, 0x0e, 0x42, 0xf7, 0x98, 0x6c, 0x2f, 0xd9, 0xcb, 0x25, 0x74, 0x50, 0xb0, + 0x33, 0xf5, 0x47, 0x34, 0x44, 0x0f, 0x00, 0x6c, 0x37, 0x8a, 0x4d, 0xb2, 0x46, 0xe6, 0xcd, 0xd8, + 0x49, 0xff, 0x1b, 0x55, 0x3b, 0x19, 0x8a, 0x7b, 0xa0, 0x65, 0xe4, 0x64, 0x3f, 0x31, 0x24, 0x2e, + 0x1b, 0xa9, 0xfc, 0xdc, 0xf2, 0x5b, 0x7e, 0x3c, 0x47, 0x89, 0x32, 0xe1, 0xca, 0x1c, 0x25, 0xca, + 0x83, 0xf7, 0x40, 0x0b, 0x5e, 0x38, 0xa1, 0x79, 0xe4, 0xc4, 0xa3, 0x13, 0x93, 0x9b, 0x55, 0xe6, + 0x83, 0x1b, 0x84, 0xef, 0x20, 0xb8, 0x8b, 0x50, 0xfd, 0x1c, 0x2e, 0x3f, 0x73, 0x46, 0x71, 0x10, + 0x76, 0x12, 0xcf, 0x17, 0x79, 0xb3, 0x2f, 0x0c, 0xbc, 0xc4, 0xb6, 0x8f, 0xbf, 0xc5, 0x3b, 0x80, + 0x1a, 0x87, 0x33, 0x52, 0x3d, 0xb4, 0x50, 0x21, 0x71, 0x46, 0xd8, 0x4f, 0xcb, 0xa9, 0x6c, 0x34, + 0x2f, 0xf8, 0x30, 0x52, 0xff, 0x5b, 0x65, 0x58, 0xcb, 0x7c, 0x9a, 0xae, 0xc4, 0x3c, 0x84, 0xba, + 0x3c, 0x02, 0x48, 0x9d, 0xbe, 0x16, 0x7c, 0xa8, 0xc6, 0x44, 0x2c, 0x6a, 0x3d, 0x06, 0x2d, 0x9b, + 0xe7, 0x07, 0xb4, 0xa0, 0x46, 0x26, 0x1b, 0xea, 0x42, 0x77, 0x61, 0x99, 0x4f, 0xe6, 0x72, 0xf5, + 0x4c, 0x4e, 0x3d, 0x19, 0x29, 0x7e, 0x07, 0x56, 0xf9, 0xe4, 0xd7, 0x94, 0x77, 0x7f, 0x4a, 0x59, + 0x05, 0x6f, 0x41, 0xe7, 0x19, 0x75, 0xa6, 0xa7, 0x74, 0x24, 0x3e, 0x80, 0x3a, 0xb9, 0x76, 0x9b, + 0x2f, 0x88, 0x34, 0xef, 0x4d, 0xca, 0x66, 0x38, 0xc2, 0x73, 0x49, 0xe2, 0x3d, 0x58, 0xc7, 0xb9, + 0x61, 0xf9, 0x23, 0x87, 0x26, 0x1a, 0xd9, 0x29, 0xf9, 0x94, 0x58, 0x53, 0x88, 0xe4, 0x08, 0xe6, + 0xb7, 0xa0, 0x6a, 0xbb, 0xa1, 0xc3, 0x44, 0xe5, 0x1f, 0x63, 0xb3, 0x4c, 0xe9, 0xc5, 0x23, 0xdc, + 0xdb, 0x7c, 0xdb, 0x25, 0x1d, 0x83, 0xe7, 0x48, 0x65, 0xae, 0x6e, 0x8d, 0x84, 0x84, 0xe6, 0x8b, + 0xf8, 0x8c, 0xf8, 0x1d, 0x57, 0x8f, 0x67, 0x78, 0x75, 0xf1, 0x0c, 0x5f, 0x55, 0x64, 0x3c, 0xcb, + 0xdf, 0x83, 0xda, 0x24, 0x74, 0xcc, 0x23, 0xd7, 0x8b, 0x9d, 0x10, 0x15, 0xf1, 0x59, 0x3b, 0x09, + 0x4c, 0x42, 0x67, 0x87, 0xb1, 0x0b, 0x1d, 0x8f, 0x6a, 0x0b, 0x1d, 0x8f, 0xc4, 0x03, 0xb8, 0xec, + 0xfa, 0x6e, 0xec, 0x5a, 0x9e, 0xc9, 0xd6, 0x23, 0xb6, 0x12, 0xd7, 0xe9, 0xc8, 0x6d, 0x5d, 0xa2, + 0xf6, 0x11, 0x43, 0xe6, 0x62, 0xf1, 0x19, 0xac, 0x1f, 0xb9, 0x21, 0x2e, 0x4f, 0xe2, 0x5e, 0xdc, + 0xec, 0xd5, 0xb9, 0x66, 0xaf, 0x11, 0x91, 0x81, 0x34, 0xdc, 0xee, 0xf7, 0x41, 0x1c, 0x4e, 0x47, + 0xa7, 0x4e, 0x6c, 0x3a, 0xe7, 0x13, 0xcb, 0xb7, 0xcd, 0x28, 0x76, 0x26, 0xa4, 0xc4, 0xad, 0x1a, + 0x1a, 0x63, 0xda, 0x84, 0x18, 0xc4, 0xce, 0x44, 0xbc, 0x05, 0x8d, 0xf8, 0x04, 0xb7, 0x84, 0xc8, + 0x8c, 0x1c, 0x2b, 0x1c, 0x9d, 0xf0, 0xb5, 0x6d, 0x63, 0x55, 0x42, 0x07, 0x04, 0x14, 0x8f, 0x60, + 0x95, 0x04, 0xd9, 0xe4, 0x1e, 0x9d, 0xb6, 0xf0, 0x1e, 0x5d, 0x1d, 0x89, 0x54, 0x4a, 0x3c, 0x82, + 0xab, 0x93, 0x20, 0x8a, 0x65, 0x57, 0x9a, 0xe9, 0x3a, 0x27, 0xa1, 0xae, 0x62, 0x5c, 0x46, 0x2c, + 0xf7, 0x64, 0x5f, 0xad, 0x75, 0xf1, 0x19, 0x90, 0x80, 0x6c, 0xa2, 0x10, 0x2c, 0xf5, 0xb2, 0xf9, + 0x09, 0x8c, 0x4b, 0xf0, 0x79, 0x10, 0x9e, 0xb2, 0x44, 0x8c, 0xbf, 0xf4, 0xbf, 0xfd, 0x3e, 0x94, + 0x7a, 0x81, 0xed, 0x88, 0x8f, 0xa0, 0x4a, 0x77, 0x74, 0x32, 0x3b, 0x85, 0x34, 0x54, 0x21, 0x9a, + 0xfe, 0x10, 0xcb, 0xaf, 0xf8, 0xf2, 0xd7, 0xcb, 0x2f, 0x8b, 0xbe, 0x41, 0x06, 0x56, 0x72, 0xd6, + 0xc3, 0x7a, 0xd4, 0xd4, 0x0d, 0x68, 0x2b, 0x8e, 0x0c, 0xc6, 0xa0, 0x90, 0x4e, 0x8e, 0x03, 0xa1, + 0xe3, 0xd3, 0x72, 0x5b, 0x36, 0x92, 0x34, 0x99, 0xb5, 0xc3, 0x00, 0x59, 0x01, 0x8b, 0xb2, 0xcb, + 0x0b, 0xcc, 0xda, 0x8c, 0x27, 0xd9, 0xf6, 0x23, 0xa8, 0x7e, 0x1b, 0xb8, 0x3e, 0x57, 0x7c, 0x65, + 0xae, 0xe2, 0x5f, 0x05, 0xae, 0xcf, 0x15, 0xff, 0x56, 0xfe, 0x12, 0x6f, 0x42, 0x39, 0xf0, 0xb9, + 0xec, 0xf2, 0x5c, 0xd9, 0x2b, 0x81, 0xdf, 0xe5, 0xdb, 0x12, 0xab, 0x6e, 0x64, 0x86, 0xa4, 0xeb, + 0x62, 0x4e, 0xe9, 0xe4, 0x57, 0x73, 0x23, 0x03, 0x61, 0x58, 0x2c, 0xce, 0x79, 0x39, 0x48, 0x54, + 0x58, 0x75, 0x7e, 0xce, 0x33, 0x9a, 0x0a, 0x7c, 0x0b, 0x2a, 0xc7, 0x61, 0x40, 0x96, 0x82, 0x05, + 0xab, 0xa3, 0x4c, 0xb8, 0xad, 0x0b, 0xd4, 0xc3, 0xe8, 0xa7, 0xeb, 0x1f, 0x9b, 0x74, 0x52, 0x81, + 0xeb, 0xa2, 0x62, 0xd4, 0x15, 0x90, 0xce, 0x20, 0xde, 0x82, 0x8a, 0x75, 0x7c, 0x6c, 0xca, 0x4b, + 0x1f, 0x73, 0x65, 0x59, 0xc7, 0xc7, 0xf4, 0xc9, 0x07, 0xb0, 0x7a, 0xe6, 0xfa, 0x66, 0x34, 0x71, + 0x46, 0x4c, 0xbb, 0x3a, 0xdf, 0x95, 0x67, 0xae, 0x8f, 0x3c, 0x84, 0xe8, 0xb3, 0xfb, 0x69, 0xe3, + 0xc7, 0xef, 0xa7, 0x6b, 0x2f, 0xdb, 0x4f, 0x75, 0x58, 0x91, 0x4e, 0x05, 0xda, 0x1c, 0x89, 0xc4, + 0x88, 0x8f, 0xa1, 0x16, 0x5a, 0xfe, 0xa9, 0x29, 0x3d, 0x26, 0xbf, 0xc9, 0x5a, 0xdb, 0x0d, 0xcb, + 0x3f, 0x95, 0x0e, 0x93, 0x10, 0x26, 0xbf, 0xf3, 0xba, 0xf7, 0xfa, 0x2b, 0xec, 0x61, 0x19, 0x33, + 0x9b, 0xf8, 0x61, 0x33, 0xdb, 0xa7, 0x64, 0xcf, 0x72, 0xfc, 0xd8, 0x54, 0x19, 0x2e, 0x2f, 0xce, + 0x50, 0x67, 0xb2, 0x3e, 0x67, 0xc3, 0x06, 0xd0, 0x69, 0x97, 0x49, 0x47, 0x63, 0x1b, 0xb9, 0x06, + 0x24, 0xc7, 0x60, 0x06, 0x84, 0xe9, 0x91, 0x58, 0x13, 0xd6, 0xd2, 0x9b, 0xa3, 0x7c, 0x5d, 0xf7, + 0x4a, 0xf6, 0xbc, 0x3f, 0x77, 0xd5, 0x54, 0x59, 0xd0, 0xdc, 0xdc, 0xfd, 0xd3, 0x37, 0x61, 0x95, + 0x9d, 0xa7, 0xb9, 0xdf, 0x22, 0xe9, 0xaf, 0x5e, 0x27, 0x20, 0xf7, 0x53, 0x44, 0x92, 0x8a, 0x34, + 0xeb, 0xc5, 0xe7, 0xa4, 0x6e, 0xa5, 0x7c, 0x9c, 0xed, 0x78, 0xf1, 0xb9, 0x51, 0xb5, 0xd5, 0x4f, + 0xd4, 0x22, 0x0e, 0x5d, 0xdf, 0xc6, 0xa9, 0x17, 0x5b, 0xc7, 0xd1, 0xe6, 0x26, 0xad, 0xcc, 0x9a, + 0x84, 0x0d, 0xad, 0xe3, 0x48, 0x7c, 0x02, 0x75, 0x8b, 0xad, 0x16, 0x5c, 0xef, 0xeb, 0xd9, 0xd3, + 0xa1, 0x8c, 0x3d, 0xc3, 0xa8, 0x59, 0x19, 0xe3, 0xc6, 0xe7, 0x20, 0x94, 0xcf, 0x53, 0xc6, 0x96, + 0x7e, 0x63, 0x6e, 0x36, 0xae, 0x49, 0xa7, 0xa7, 0xc4, 0x92, 0x7e, 0x1b, 0xa4, 0x28, 0xc0, 0xec, + 0xf8, 0x35, 0xaa, 0x10, 0x30, 0x88, 0x18, 0xf1, 0xe7, 0xb0, 0x9a, 0x37, 0xd7, 0xdc, 0x5c, 0xe0, + 0x3a, 0xc4, 0x1b, 0x77, 0x7d, 0x94, 0x35, 0xe0, 0xbc, 0xc9, 0x37, 0xa0, 0x49, 0xd5, 0xa2, 0x8c, + 0xec, 0x1e, 0x53, 0xf7, 0x83, 0xb8, 0xa5, 0x60, 0xd8, 0x81, 0xca, 0x98, 0x1a, 0x9f, 0x93, 0x76, + 0x96, 0x74, 0x60, 0x62, 0x83, 0x32, 0xaa, 0x6e, 0x62, 0x8e, 0xda, 0x06, 0xa1, 0x1c, 0x14, 0x50, + 0x4a, 0x65, 0xf7, 0x5b, 0x52, 0xc6, 0x12, 0x6f, 0xa2, 0x59, 0x21, 0xd6, 0x60, 0x57, 0xe5, 0xac, + 0x58, 0xfb, 0x18, 0x1a, 0xb8, 0x95, 0x66, 0xbe, 0xac, 0x67, 0x1b, 0xb5, 0x1f, 0x3a, 0xe9, 0xc7, + 0xeb, 0x93, 0x4c, 0x4a, 0xfc, 0x1c, 0xd6, 0x33, 0x39, 0xa7, 0xa7, 0x94, 0xf9, 0x4d, 0xca, 0xbc, + 0x31, 0x93, 0xf9, 0xe0, 0x14, 0xb3, 0x37, 0x26, 0xb9, 0xb4, 0xd8, 0x80, 0xe5, 0x4e, 0xd4, 0xf6, + 0x6d, 0x52, 0xd2, 0x2a, 0x06, 0x27, 0xc4, 0x23, 0xa8, 0xb3, 0x45, 0x84, 0x0c, 0x93, 0xd1, 0xe6, + 0xdb, 0xd9, 0xe3, 0x5f, 0x32, 0x8b, 0xb0, 0x75, 0xb3, 0xe6, 0x25, 0xbf, 0x23, 0xdc, 0x88, 0xf9, + 0x6c, 0x3e, 0xcb, 0x22, 0xdf, 0x99, 0x1f, 0x72, 0x22, 0xda, 0x49, 0xf9, 0xa4, 0x01, 0xd7, 0xc3, + 0xa9, 0x4f, 0x56, 0x12, 0x99, 0x93, 0xf7, 0x7d, 0xca, 0x7f, 0x8f, 0xf2, 0xcb, 0x98, 0x1a, 0x06, + 0x93, 0x71, 0x5e, 0xe2, 0x4d, 0x57, 0xc3, 0x2c, 0x88, 0xa4, 0x82, 0x97, 0x94, 0xc9, 0xa7, 0x29, + 0x54, 0xe6, 0xbb, 0x3f, 0xa5, 0x4c, 0x3a, 0x69, 0xa1, 0x32, 0x05, 0x94, 0xa6, 0x53, 0xd7, 0x26, + 0x95, 0xb1, 0x6e, 0xd0, 0x6f, 0x14, 0x0b, 0x42, 0x67, 0x34, 0x0d, 0x23, 0xf7, 0x85, 0x63, 0x46, + 0xae, 0x7f, 0x4a, 0xca, 0x62, 0xc5, 0x58, 0x4d, 0xa0, 0x03, 0xd7, 0x3f, 0x45, 0x96, 0xe1, 0x9c, + 0xc7, 0x4e, 0xe8, 0xf3, 0xd5, 0xf1, 0xf7, 0xb3, 0x2c, 0xa3, 0x4d, 0x08, 0x5c, 0xe7, 0x06, 0x38, + 0xc9, 0xef, 0x99, 0x91, 0x8d, 0x78, 0x64, 0x1f, 0xfc, 0xa8, 0x91, 0x1d, 0xd0, 0xc8, 0xbe, 0x0d, + 0x15, 0xd7, 0x8f, 0x9d, 0xf0, 0x85, 0xe5, 0x6d, 0x7e, 0x38, 0xc7, 0x8d, 0x13, 0x9c, 0xb8, 0x0b, + 0xe5, 0xc8, 0x73, 0x71, 0xbd, 0x6f, 0x7e, 0x34, 0x47, 0xa6, 0x50, 0xe2, 0x1e, 0x54, 0x93, 0x40, + 0x2f, 0x9b, 0x1f, 0xcf, 0xd1, 0xa5, 0x48, 0x71, 0x0b, 0x4a, 0x67, 0x38, 0xa1, 0x1e, 0xce, 0x1f, + 0xd7, 0x23, 0x1c, 0xb7, 0xef, 0x23, 0x54, 0xfe, 0x69, 0xfb, 0x7e, 0x34, 0xb7, 0x7d, 0xef, 0xb8, + 0x9e, 0xc7, 0xdb, 0xf7, 0x91, 0xfc, 0x85, 0x9b, 0x1f, 0xe5, 0xc0, 0x96, 0x7c, 0x32, 0xbf, 0xf9, + 0x21, 0xee, 0x19, 0x85, 0xc4, 0xa9, 0x45, 0x74, 0x06, 0xcd, 0x47, 0xe9, 0x9f, 0x66, 0xfb, 0x2a, + 0x7f, 0x38, 0x6d, 0x40, 0x94, 0xa4, 0xc5, 0xeb, 0x20, 0x8f, 0xd8, 0x49, 0xfb, 0xfa, 0x8c, 0x03, + 0x0f, 0x30, 0x04, 0x15, 0xaf, 0x8f, 0x60, 0x55, 0xf9, 0x4e, 0xe3, 0xe7, 0xa2, 0xcd, 0xcf, 0xe7, + 0x6a, 0x90, 0x27, 0x10, 0xdb, 0x50, 0x3f, 0x9a, 0x7e, 0xff, 0xfd, 0xc5, 0x98, 0x6d, 0x02, 0x9b, + 0x8f, 0xa9, 0x22, 0x77, 0xd4, 0xc6, 0xfa, 0x32, 0x9b, 0x81, 0x91, 0xcb, 0x25, 0x1e, 0x80, 0x70, + 0x8f, 0x78, 0x3c, 0x77, 0xc2, 0x60, 0xcc, 0x7a, 0xff, 0xe6, 0x17, 0xf2, 0x5c, 0x62, 0x0e, 0x43, + 0x0e, 0x39, 0x8e, 0x6f, 0x9b, 0xe3, 0x48, 0x8a, 0x09, 0x5f, 0x52, 0x3d, 0x25, 0xf3, 0x4a, 0x02, + 0x42, 0xa9, 0x03, 0x57, 0xa4, 0xdd, 0x8b, 0x58, 0x6a, 0xf8, 0x02, 0x70, 0xba, 0xbe, 0x48, 0xb3, + 0xfe, 0xd6, 0x0f, 0x66, 0x45, 0x5a, 0x95, 0xf5, 0x31, 0x34, 0xf8, 0x34, 0x84, 0x24, 0x32, 0x9c, + 0xa2, 0x3f, 0xcb, 0x72, 0xae, 0xec, 0x31, 0xae, 0x51, 0xb7, 0xb3, 0x87, 0xba, 0x9f, 0xc3, 0x5a, + 0xe6, 0x30, 0x84, 0x3e, 0xfb, 0xdb, 0xd9, 0xcf, 0x26, 0xa7, 0x21, 0xc6, 0xea, 0x54, 0xfd, 0xa4, + 0x4f, 0xce, 0x89, 0xd8, 0xbf, 0xf3, 0x23, 0x44, 0xec, 0x37, 0x21, 0x5d, 0x91, 0xe6, 0x28, 0x76, + 0x36, 0x7f, 0xce, 0xcc, 0x3f, 0x01, 0xb6, 0x62, 0x47, 0x3c, 0x02, 0xb0, 0x26, 0x13, 0xef, 0x82, + 0xa7, 0xe6, 0x2f, 0x68, 0x6a, 0x6e, 0x64, 0xa6, 0x66, 0x13, 0x91, 0x34, 0x37, 0xab, 0x96, 0xfa, + 0x89, 0x0a, 0x2e, 0x09, 0xef, 0xf6, 0xd8, 0xa3, 0xf6, 0x37, 0xb3, 0x6b, 0x7b, 0x3f, 0x88, 0xe2, + 0xed, 0xb1, 0x87, 0xad, 0x80, 0x49, 0xf2, 0x5b, 0x74, 0xe1, 0x72, 0xe0, 0x9b, 0xf6, 0x74, 0xe2, + 0xb9, 0x23, 0xec, 0x01, 0x3e, 0x85, 0xdc, 0xdc, 0xca, 0xde, 0x4f, 0xa2, 0x2f, 0xf6, 0xfd, 0x6d, + 0x45, 0x24, 0x4f, 0x37, 0xd7, 0x83, 0x59, 0x10, 0x19, 0xac, 0x68, 0x0c, 0x92, 0xab, 0x3d, 0x2d, + 0x16, 0x0d, 0x08, 0xaa, 0xee, 0xf6, 0x3c, 0x86, 0xb5, 0x94, 0x0a, 0x1b, 0x18, 0x6d, 0x6e, 0x67, + 0x67, 0x72, 0xe6, 0x16, 0xe4, 0xaa, 0xca, 0x88, 0xb0, 0x88, 0xfa, 0x2e, 0xf0, 0xbc, 0xe9, 0x44, + 0xb2, 0xd2, 0xcd, 0xb6, 0xec, 0x3b, 0x02, 0x32, 0x97, 0xcc, 0xd8, 0xf4, 0x9c, 0xf1, 0xe6, 0x4e, + 0xd6, 0xa6, 0xe7, 0x8c, 0x51, 0xcc, 0x90, 0x7e, 0xf6, 0x2f, 0x5c, 0xe7, 0x2c, 0xda, 0x7c, 0x42, + 0x9a, 0x9f, 0xbc, 0xf3, 0xf7, 0x0c, 0x41, 0xb8, 0xef, 0xb3, 0x1e, 0x4b, 0x24, 0x9b, 0xbb, 0x7c, + 0xe9, 0x8b, 0x41, 0x48, 0x21, 0x5a, 0xb0, 0x49, 0xec, 0x5c, 0xae, 0xd5, 0x9c, 0x1f, 0x4c, 0x67, + 0x6e, 0x49, 0x5e, 0x41, 0x5a, 0x76, 0xb3, 0xd9, 0xcf, 0x78, 0xc4, 0xfc, 0x02, 0x5e, 0x5f, 0x5c, + 0x88, 0x0a, 0x3b, 0xf0, 0x15, 0xc9, 0x1b, 0xd7, 0x17, 0xe4, 0x96, 0xb1, 0x07, 0xbe, 0x84, 0xd5, + 0x63, 0x8b, 0x7a, 0xc2, 0x33, 0xc7, 0x81, 0xed, 0x6c, 0x3e, 0xcd, 0x06, 0xd9, 0xa1, 0x41, 0x7b, + 0x62, 0x61, 0xa7, 0x78, 0x7b, 0x81, 0xed, 0x18, 0xb5, 0xe3, 0x34, 0x21, 0x1e, 0xc3, 0x66, 0x3a, + 0x09, 0xa7, 0x3e, 0x7e, 0x17, 0x55, 0x6a, 0xd7, 0x1f, 0xc5, 0x9b, 0x5d, 0xea, 0xd3, 0xab, 0x09, + 0xfe, 0x00, 0xd1, 0xdb, 0x12, 0x2b, 0x5a, 0xa0, 0x11, 0x73, 0x90, 0xbb, 0x58, 0xe4, 0xda, 0xce, + 0xe6, 0x5e, 0x36, 0x88, 0x06, 0xb3, 0x4e, 0x24, 0xa1, 0xfd, 0x6a, 0xe0, 0xda, 0x8e, 0xd1, 0x38, + 0xca, 0xa5, 0xc5, 0xbb, 0xb0, 0xae, 0xf4, 0x11, 0xf3, 0xc4, 0x8a, 0x4e, 0xcc, 0x53, 0xe7, 0x62, + 0xb3, 0x47, 0x0d, 0x6e, 0x48, 0x65, 0x64, 0xd7, 0x8a, 0x4e, 0x9e, 0x3a, 0x17, 0xe2, 0x3e, 0xea, + 0xd4, 0xb4, 0x6d, 0xba, 0x91, 0x79, 0x68, 0x85, 0xa1, 0xeb, 0x84, 0x9b, 0x7d, 0x3e, 0x42, 0x63, + 0x44, 0x27, 0xda, 0x62, 0x30, 0xea, 0xd1, 0xd9, 0xc1, 0x90, 0xea, 0xfa, 0x3e, 0xf1, 0x51, 0x2d, + 0xe3, 0x8e, 0xc4, 0xda, 0xfa, 0x47, 0xd0, 0x48, 0xfa, 0x8f, 0x9d, 0x72, 0x7e, 0x39, 0xb7, 0x4f, + 0xd4, 0x65, 0xa7, 0x0d, 0xc8, 0x2b, 0xe7, 0x7d, 0xa8, 0x27, 0x39, 0x1c, 0xdf, 0xde, 0x34, 0xe6, + 0xcd, 0x86, 0x92, 0x1e, 0x77, 0x97, 0x4f, 0xe1, 0x1a, 0x4f, 0x73, 0x3e, 0x3a, 0x39, 0x75, 0x2e, + 0x92, 0x98, 0x29, 0x03, 0xaa, 0xff, 0x06, 0xa1, 0x3b, 0x88, 0x7d, 0xea, 0x5c, 0x44, 0x09, 0xf7, + 0xbc, 0x4e, 0xae, 0x05, 0x23, 0x79, 0x63, 0x98, 0xcd, 0xea, 0xb2, 0x2d, 0x43, 0x1e, 0x1b, 0x24, + 0x68, 0x25, 0x78, 0x43, 0xba, 0xab, 0x89, 0x26, 0xac, 0xb3, 0x1d, 0x28, 0x1b, 0x1c, 0xe6, 0x80, + 0x2a, 0x79, 0x65, 0xa1, 0x42, 0x6e, 0xac, 0xbd, 0x98, 0x31, 0x92, 0x3d, 0x81, 0x1b, 0xc9, 0x59, + 0xa9, 0xf3, 0xdd, 0xd4, 0xa2, 0xeb, 0x56, 0xa7, 0xce, 0x05, 0xb3, 0xc5, 0xe7, 0x73, 0xb3, 0xfb, + 0x9a, 0xa2, 0x6e, 0x4b, 0xe2, 0xa7, 0xce, 0x05, 0xf1, 0xc6, 0xbb, 0xd0, 0xb0, 0xa2, 0xe0, 0x48, + 0x6a, 0xb1, 0xa3, 0xc0, 0xdb, 0x7c, 0x46, 0xe3, 0x50, 0x47, 0xa8, 0xa1, 0x8e, 0x66, 0x7b, 0x70, + 0x39, 0x1d, 0x31, 0xcb, 0x3b, 0x0e, 0x42, 0x37, 0x3e, 0x19, 0x6f, 0xfe, 0x2a, 0x6b, 0x6d, 0xa2, + 0x09, 0x95, 0x4c, 0xfe, 0xa6, 0x22, 0x32, 0xd2, 0xb1, 0x4e, 0x60, 0xe2, 0x31, 0x5c, 0x4f, 0xcb, + 0x8b, 0x83, 0x89, 0xe9, 0x9b, 0x67, 0x6e, 0x7c, 0x62, 0x92, 0x5f, 0xf3, 0xef, 0xca, 0xc8, 0x1a, + 0x8a, 0x60, 0x18, 0x4c, 0x7a, 0xcf, 0xdd, 0xf8, 0x64, 0xe8, 0x3a, 0x91, 0xd8, 0x82, 0x5b, 0x96, + 0x6d, 0x4d, 0x62, 0x5c, 0x10, 0x98, 0x31, 0x89, 0x06, 0x12, 0xf8, 0xa6, 0x33, 0x9e, 0xc4, 0x17, + 0x9b, 0x7f, 0x8d, 0xb2, 0xdf, 0x50, 0x54, 0xc3, 0x60, 0xb2, 0x23, 0x69, 0xfa, 0x7e, 0x1b, 0x29, + 0xf4, 0x7f, 0xba, 0x0c, 0x15, 0x65, 0xac, 0x10, 0x35, 0x28, 0x1f, 0xf4, 0x9e, 0xf6, 0xfa, 0xcf, + 0x7b, 0x1c, 0x62, 0xaa, 0x39, 0x18, 0xb4, 0x8d, 0xa1, 0x66, 0x8b, 0x06, 0x00, 0x85, 0x53, 0x31, + 0x07, 0xad, 0x66, 0x8f, 0x43, 0x4e, 0x51, 0x10, 0x17, 0x4e, 0x2f, 0x89, 0x75, 0x58, 0xdd, 0x39, + 0xe8, 0xf1, 0x95, 0x23, 0x02, 0x15, 0x11, 0xd4, 0xfe, 0x9a, 0xfd, 0xfe, 0x18, 0x54, 0x42, 0xd0, + 0x5e, 0x73, 0xd8, 0x36, 0x3a, 0x0a, 0xb4, 0x2c, 0xae, 0xc0, 0x7a, 0x42, 0xa5, 0x4a, 0xd0, 0xca, + 0x08, 0x7e, 0xd6, 0x6e, 0x0d, 0xfb, 0x86, 0xd9, 0xe9, 0x6d, 0xb7, 0xbf, 0x66, 0xea, 0x0a, 0xd6, + 0x6f, 0xdf, 0xe8, 0x7f, 0xd5, 0x6e, 0x0d, 0x35, 0x20, 0x57, 0xc2, 0x27, 0x4f, 0xb4, 0x9a, 0xa8, + 0x43, 0x65, 0xbb, 0x33, 0x18, 0x76, 0x7a, 0xad, 0xa1, 0x56, 0xc7, 0x6a, 0xef, 0x74, 0xba, 0xc3, + 0xb6, 0xa1, 0xad, 0x8a, 0x0a, 0x94, 0xbe, 0xea, 0x77, 0x7a, 0x5a, 0x83, 0x82, 0xcb, 0x34, 0xf7, + 0xf6, 0xbb, 0x6d, 0x6d, 0x0d, 0xa1, 0x83, 0xbe, 0x31, 0xd4, 0x34, 0x84, 0x3e, 0xef, 0xf4, 0xb6, + 0xfb, 0xcf, 0xb5, 0x75, 0x51, 0x85, 0xe5, 0x83, 0x1e, 0x7e, 0x5d, 0x88, 0x55, 0xa8, 0xd2, 0x4f, + 0xb3, 0xd9, 0xed, 0x6a, 0x97, 0x33, 0xfe, 0x87, 0x1b, 0x88, 0x22, 0x6f, 0xc6, 0x01, 0xd6, 0xe1, + 0x0a, 0xb6, 0x28, 0x49, 0x12, 0xf5, 0x55, 0x2c, 0x67, 0xaf, 0xd3, 0x3b, 0x18, 0x68, 0xd7, 0x90, + 0x98, 0x7e, 0x12, 0x66, 0x13, 0xcb, 0xe9, 0xf4, 0xa8, 0x43, 0x6f, 0xe1, 0xef, 0xed, 0x76, 0xb7, + 0x3d, 0x6c, 0x6b, 0xb7, 0xb1, 0x55, 0xdd, 0x7e, 0xeb, 0xa9, 0xd9, 0xdf, 0xd7, 0xde, 0xc0, 0x9e, + 0xdd, 0x37, 0xda, 0xa6, 0x24, 0x7c, 0x53, 0x68, 0x50, 0xdf, 0x39, 0xf8, 0xd5, 0xaf, 0xbe, 0x31, + 0x65, 0xa3, 0xde, 0xc2, 0x6f, 0xa6, 0x14, 0xe6, 0xc1, 0x53, 0xed, 0xed, 0x19, 0xd0, 0xe0, 0xa9, + 0xf6, 0x0e, 0x76, 0x8a, 0xea, 0x6b, 0xed, 0x1e, 0x12, 0x18, 0xed, 0xd6, 0x81, 0x31, 0xe8, 0x3c, + 0x6b, 0x9b, 0xad, 0x61, 0x5b, 0x7b, 0x97, 0x7a, 0xa1, 0xd3, 0x7b, 0xaa, 0xdd, 0xc7, 0x6a, 0xe2, + 0x2f, 0xee, 0xe4, 0xf7, 0x84, 0x80, 0x46, 0x4a, 0x4b, 0xb0, 0xf7, 0x91, 0x64, 0xcb, 0xe8, 0x37, + 0xb7, 0x5b, 0xcd, 0xc1, 0x50, 0xfb, 0x00, 0xdb, 0x38, 0xd8, 0xef, 0x76, 0x86, 0xda, 0x03, 0x6c, + 0xc8, 0x93, 0xe6, 0x70, 0xb7, 0x6d, 0x68, 0x1f, 0x8a, 0x35, 0xa8, 0x0d, 0x3b, 0x7b, 0x6d, 0x53, + 0xf6, 0xe9, 0x43, 0xfc, 0xc6, 0x4e, 0xa7, 0xdb, 0xd5, 0x1e, 0x91, 0xff, 0x5c, 0xd3, 0x18, 0x76, + 0x68, 0x7c, 0x3f, 0xc1, 0x02, 0x9a, 0xfb, 0xfb, 0xdd, 0x6f, 0xb4, 0x4f, 0xb1, 0x81, 0x7b, 0x07, + 0xdd, 0x61, 0xc7, 0x3c, 0xd8, 0xdf, 0x6e, 0x0e, 0xdb, 0xda, 0x67, 0x34, 0xca, 0xfd, 0xc1, 0x70, + 0x7b, 0xaf, 0xab, 0x7d, 0x4e, 0x65, 0xd2, 0x4c, 0x6b, 0x75, 0xfb, 0xbd, 0xb6, 0xf6, 0x18, 0xe9, + 0x9b, 0xdb, 0xcd, 0xfd, 0x21, 0xd6, 0x6e, 0xd8, 0xdf, 0xd7, 0xbe, 0xd0, 0x4b, 0x95, 0x15, 0x6d, + 0x45, 0x2f, 0x55, 0xee, 0x68, 0x77, 0xf4, 0x52, 0x45, 0xd7, 0xf4, 0xfb, 0xb5, 0x41, 0xff, 0xc0, + 0x68, 0x71, 0xed, 0xf5, 0xbf, 0x51, 0x80, 0x8a, 0xb2, 0x6a, 0xe1, 0x87, 0x3b, 0xbd, 0x5e, 0xdb, + 0xd0, 0x2e, 0x61, 0xe5, 0xba, 0xed, 0x9d, 0xa1, 0x56, 0x20, 0xf7, 0xc3, 0xce, 0x93, 0xdd, 0xa1, + 0xb6, 0x84, 0x3f, 0xfb, 0x07, 0xd8, 0xcf, 0x45, 0xea, 0xa0, 0xf6, 0x5e, 0x47, 0x2b, 0xe1, 0xaf, + 0x66, 0x6f, 0xd8, 0xd1, 0x96, 0x69, 0x1a, 0x75, 0x7a, 0x4f, 0xba, 0x6d, 0x6d, 0x05, 0xa1, 0x7b, + 0x4d, 0xe3, 0xa9, 0x56, 0xe6, 0x42, 0xb7, 0xdb, 0x5f, 0x6b, 0x15, 0xb1, 0x02, 0x4b, 0xdd, 0x87, + 0x5a, 0x15, 0x41, 0xdb, 0xed, 0xed, 0x83, 0x7d, 0x0d, 0x28, 0xf7, 0xa0, 0xbf, 0xa3, 0xd5, 0xb0, + 0x13, 0xf0, 0x97, 0x49, 0x9f, 0xad, 0xeb, 0xf7, 0xa0, 0xdc, 0x3c, 0x3e, 0xa6, 0xbd, 0x0d, 0x3b, + 0xea, 0xa0, 0xdb, 0xe5, 0x55, 0xb7, 0xd5, 0x1f, 0x0e, 0xfb, 0x7b, 0x5a, 0x01, 0x67, 0x38, 0xb6, + 0x70, 0x49, 0xef, 0x40, 0x45, 0x09, 0xf6, 0x99, 0xc0, 0x4a, 0x15, 0x28, 0xed, 0x1b, 0xed, 0x67, + 0xec, 0x4c, 0xdb, 0x6b, 0x7f, 0x8d, 0xf5, 0xc7, 0x5f, 0x58, 0x50, 0x11, 0x6b, 0xc0, 0x11, 0x90, + 0x28, 0xb2, 0x52, 0xb7, 0xd3, 0x6b, 0x37, 0x0d, 0x6d, 0x59, 0x7f, 0x0c, 0xb5, 0xcc, 0x0e, 0x8b, + 0x13, 0xe3, 0x49, 0x73, 0x1f, 0x27, 0x57, 0xd7, 0x94, 0xc5, 0x5e, 0x05, 0x91, 0x80, 0xd2, 0x31, + 0x2b, 0xe8, 0x9f, 0xc2, 0xfa, 0x9c, 0x40, 0x45, 0x15, 0x6f, 0x76, 0x64, 0xc5, 0x3b, 0x4f, 0x7a, + 0x7d, 0xa3, 0xcd, 0x41, 0x9e, 0xe4, 0x68, 0x2e, 0xe9, 0xef, 0x41, 0x35, 0x91, 0xfc, 0x70, 0x76, + 0xb7, 0x8c, 0xfe, 0x60, 0xc0, 0x83, 0x7f, 0x09, 0xd3, 0xd4, 0xdd, 0x9c, 0x2e, 0xe8, 0x2e, 0x34, + 0xf2, 0xdb, 0xb0, 0xb8, 0x03, 0x37, 0x79, 0xfe, 0x6f, 0x1d, 0x74, 0xba, 0xdb, 0xe6, 0xa0, 0xb3, + 0xdd, 0x9e, 0xb9, 0x3d, 0x7e, 0x03, 0xae, 0xce, 0x51, 0x70, 0x84, 0xa9, 0x82, 0xb8, 0x0e, 0x57, + 0xe6, 0x70, 0x34, 0xeb, 0x97, 0xf4, 0x7d, 0x10, 0xf3, 0x0c, 0x5a, 0xdc, 0x84, 0xcd, 0xa4, 0xcd, + 0x66, 0xb3, 0xfb, 0xa4, 0x6f, 0x74, 0x86, 0xbb, 0x7b, 0x26, 0xf1, 0x8b, 0x4b, 0x2f, 0xc3, 0xee, + 0x36, 0x07, 0xbb, 0x5a, 0xe1, 0xab, 0x52, 0xe5, 0xb6, 0x76, 0xe7, 0xab, 0x52, 0xe5, 0xae, 0xf6, + 0x96, 0x3e, 0x80, 0x75, 0x25, 0x3d, 0xd3, 0xdd, 0x7c, 0x32, 0xeb, 0x6c, 0xc0, 0x72, 0xd7, 0x79, + 0xe1, 0x78, 0xea, 0x2a, 0x37, 0x25, 0x10, 0xda, 0x3f, 0xfc, 0xb6, 0x93, 0x84, 0x51, 0xa4, 0x04, + 0xaa, 0xcb, 0xbd, 0x4c, 0x24, 0x47, 0x0a, 0xa7, 0xf0, 0xaf, 0x16, 0xa0, 0x92, 0xc8, 0xe4, 0x77, + 0x61, 0x69, 0x38, 0x90, 0x07, 0x42, 0x1b, 0x0f, 0xd2, 0xb0, 0xbd, 0x43, 0xf5, 0xcb, 0x58, 0x1a, + 0x0e, 0xc4, 0xfb, 0xb0, 0xc2, 0xc1, 0xe4, 0xe4, 0x11, 0xd0, 0x46, 0x5e, 0xce, 0x1f, 0x12, 0xce, + 0x90, 0x34, 0xe2, 0x53, 0xa8, 0x26, 0xb5, 0x95, 0xd6, 0xe8, 0x6b, 0xf9, 0x0c, 0x09, 0xda, 0x48, + 0x29, 0xf5, 0x2e, 0x34, 0xf2, 0x05, 0x8a, 0x5b, 0x00, 0x5c, 0x64, 0xe6, 0xec, 0x36, 0x03, 0x11, + 0x37, 0x40, 0xc5, 0xb8, 0xdb, 0xa6, 0x8a, 0xad, 0x26, 0x31, 0xef, 0xb6, 0xf5, 0x7f, 0x6b, 0x19, + 0x20, 0xd5, 0xea, 0xb1, 0x23, 0x12, 0x1b, 0xfb, 0xb2, 0xf4, 0xf2, 0x7d, 0x0d, 0xaa, 0x5e, 0x60, + 0xd9, 0xd9, 0xf0, 0xbb, 0x15, 0x04, 0xd0, 0x1c, 0xcb, 0xc6, 0x9b, 0xa9, 0xca, 0xd0, 0x31, 0x57, + 0x61, 0xe5, 0x28, 0x08, 0xc7, 0x56, 0x2c, 0xef, 0xed, 0xcb, 0x14, 0x85, 0x94, 0x21, 0x27, 0x35, + 0xdb, 0xf4, 0x5c, 0xdf, 0xe1, 0xc0, 0x59, 0x25, 0xa3, 0x2e, 0x81, 0x5d, 0x84, 0xa1, 0x70, 0xed, + 0xf8, 0x23, 0x2f, 0x40, 0xb1, 0xe6, 0x90, 0x6f, 0x2d, 0xd4, 0x0d, 0x50, 0xa0, 0xad, 0x0b, 0x6e, + 0x6d, 0x38, 0x76, 0x7d, 0x2b, 0x96, 0xde, 0x3b, 0xd4, 0x5a, 0x05, 0xc1, 0xea, 0x7e, 0x1b, 0x05, + 0xd2, 0xe4, 0xce, 0x01, 0x4d, 0x2a, 0x08, 0xa0, 0xea, 0xbe, 0x0e, 0xe0, 0x44, 0x23, 0x6b, 0xc2, + 0x85, 0x57, 0x39, 0xfe, 0x9b, 0x84, 0x6c, 0x5d, 0x88, 0x2e, 0x34, 0x86, 0x87, 0xa8, 0x4c, 0x04, + 0xdb, 0x56, 0x6c, 0xb5, 0x02, 0x4f, 0x1a, 0xc3, 0xef, 0xce, 0x9a, 0x3f, 0x1e, 0xe4, 0xc9, 0xf8, + 0xe6, 0xdc, 0x4c, 0x5e, 0xf1, 0x09, 0xd4, 0xdd, 0x91, 0x73, 0xe8, 0x84, 0xc7, 0x2c, 0x68, 0xd5, + 0x72, 0x17, 0xee, 0x19, 0x43, 0x42, 0x56, 0xcd, 0x4d, 0x13, 0xa8, 0xa4, 0x8d, 0x03, 0xff, 0x38, + 0xb0, 0x0f, 0x39, 0x57, 0x3d, 0x6b, 0xd8, 0xdb, 0x43, 0x0c, 0xe7, 0x91, 0x44, 0x94, 0xe7, 0xb7, + 0x61, 0x0d, 0x7b, 0x3e, 0x8a, 0x43, 0xc7, 0x1a, 0x73, 0xb6, 0xd5, 0xec, 0x0c, 0xc4, 0x1a, 0x0d, + 0x08, 0x49, 0x79, 0x1b, 0x29, 0x31, 0x65, 0xff, 0x24, 0xbd, 0xce, 0x4e, 0x79, 0x1b, 0x39, 0xaf, + 0x7a, 0xc6, 0xf0, 0x47, 0x8f, 0xd2, 0x84, 0x78, 0x00, 0x70, 0x6a, 0x1d, 0x9d, 0x5a, 0x9c, 0x67, + 0x2d, 0x5b, 0xcd, 0xa7, 0x08, 0xa7, 0x1c, 0xd5, 0x53, 0xf5, 0xf3, 0x46, 0x13, 0x2e, 0x2f, 0xe8, + 0xb5, 0x9f, 0x74, 0x0d, 0xec, 0xef, 0x14, 0xa0, 0x91, 0x6f, 0xcb, 0x4c, 0x2c, 0xcd, 0x6a, 0x12, + 0x4b, 0x53, 0x40, 0x69, 0x12, 0x84, 0xea, 0xc6, 0x06, 0xfd, 0x4e, 0x43, 0x5b, 0x17, 0xb3, 0xa1, + 0xad, 0x37, 0xa1, 0x1c, 0x3a, 0x7c, 0xfb, 0x9a, 0x23, 0x35, 0xa8, 0x24, 0x4e, 0xd8, 0xc9, 0x34, + 0x3a, 0x71, 0x6c, 0xa5, 0x4d, 0xf2, 0x35, 0x82, 0x3a, 0x03, 0xa5, 0x36, 0x79, 0x0d, 0xca, 0xd6, + 0xc4, 0x25, 0x05, 0x45, 0xc6, 0x65, 0xb4, 0x26, 0xee, 0x53, 0xe7, 0x42, 0xff, 0x1e, 0x6a, 0x99, + 0xbe, 0xc3, 0x0a, 0x9d, 0xba, 0xbe, 0x8a, 0x2c, 0x41, 0xbf, 0xb1, 0xf2, 0x32, 0x14, 0x21, 0xdf, + 0x05, 0x91, 0x29, 0xfc, 0xb0, 0xba, 0xc6, 0x47, 0xa7, 0xb3, 0xea, 0xa8, 0x5f, 0x02, 0x7f, 0x89, + 0x30, 0x5c, 0xd6, 0x58, 0x11, 0x3b, 0x38, 0xf3, 0x65, 0xc5, 0x93, 0xb4, 0xfe, 0x9f, 0x2e, 0x41, + 0x35, 0x19, 0x04, 0x6c, 0xe1, 0x61, 0x18, 0x9c, 0x3a, 0x61, 0x24, 0xbf, 0xae, 0x92, 0xd4, 0x23, + 0xc1, 0xc4, 0x1d, 0xa9, 0x4b, 0xd1, 0x94, 0x10, 0x37, 0xb3, 0x57, 0x20, 0x39, 0x5a, 0x49, 0xe6, + 0xc6, 0xe3, 0x2d, 0x00, 0x6b, 0x1a, 0x07, 0xa3, 0x60, 0x3c, 0x76, 0x63, 0xf9, 0xe5, 0x0c, 0x04, + 0xcb, 0x24, 0x15, 0x4d, 0xf6, 0x16, 0x27, 0x32, 0x4c, 0x61, 0x25, 0xc7, 0x14, 0x6e, 0x42, 0x35, + 0x72, 0x26, 0x56, 0x68, 0xc5, 0x41, 0x28, 0x57, 0x73, 0x0a, 0xa0, 0x70, 0x98, 0xa8, 0x59, 0xa9, + 0xb8, 0x75, 0x45, 0xa3, 0x4c, 0xe9, 0x8e, 0x2d, 0xee, 0xd0, 0x55, 0x24, 0x33, 0x41, 0xb3, 0x1f, + 0x36, 0x9c, 0x58, 0xd1, 0x40, 0x52, 0x08, 0x28, 0x91, 0x4f, 0x0c, 0x7b, 0xe1, 0xd1, 0x6f, 0xf1, + 0x0e, 0x50, 0xd0, 0xf5, 0x60, 0x1a, 0x9b, 0x91, 0x33, 0x0a, 0x7c, 0x3b, 0x92, 0x7e, 0x78, 0x0d, + 0x09, 0x1e, 0x30, 0x54, 0xff, 0xaf, 0x97, 0xa0, 0x96, 0x59, 0xa3, 0xe4, 0x82, 0x64, 0x4d, 0xe8, + 0xe4, 0x2b, 0xb9, 0xbf, 0x5d, 0x95, 0x10, 0x0e, 0x11, 0x32, 0xb2, 0x62, 0xcb, 0x0b, 0x8e, 0x33, + 0xc1, 0x4f, 0x24, 0xa4, 0x63, 0x93, 0x57, 0xa0, 0x35, 0x76, 0x38, 0x08, 0xba, 0xbc, 0xbc, 0x9f, + 0x00, 0xd2, 0x79, 0x59, 0xca, 0xce, 0x4b, 0x8d, 0xdd, 0x47, 0xb9, 0x17, 0xc9, 0x5b, 0xf4, 0x36, + 0xd4, 0x94, 0x25, 0x09, 0xbf, 0x22, 0x3d, 0x1c, 0x15, 0xa8, 0x63, 0x8b, 0xb7, 0x21, 0x0d, 0x29, + 0x6f, 0x5a, 0x91, 0x19, 0x1c, 0xa9, 0x7b, 0x73, 0x09, 0xb8, 0x19, 0xf5, 0x8f, 0x12, 0xb7, 0x23, + 0xb2, 0x0a, 0x48, 0x1e, 0x89, 0x00, 0x92, 0x52, 0x1e, 0xc0, 0x65, 0x79, 0x84, 0x49, 0x13, 0xdf, + 0xf1, 0x6c, 0xd3, 0xb5, 0xd9, 0x7f, 0x7a, 0xd9, 0x58, 0x4f, 0x50, 0x3b, 0x88, 0xe9, 0xd8, 0x64, + 0x73, 0x91, 0x0a, 0xb8, 0xed, 0x1e, 0x3b, 0x51, 0x2c, 0x6f, 0x79, 0xd5, 0x19, 0xb8, 0x4d, 0x30, + 0xfd, 0x9f, 0xad, 0x40, 0x35, 0x61, 0x5e, 0xaf, 0xea, 0xcc, 0x37, 0x61, 0x75, 0x14, 0xf8, 0x3e, + 0x7b, 0x0a, 0xa4, 0xfd, 0x59, 0x4f, 0x81, 0x74, 0x4f, 0x57, 0x64, 0x88, 0xd4, 0x2d, 0x74, 0x8e, + 0xd5, 0xb1, 0x9e, 0x62, 0x9e, 0xc9, 0xfb, 0xe8, 0x37, 0xa0, 0x82, 0x5c, 0xef, 0xd0, 0x8a, 0x54, + 0x37, 0x27, 0x69, 0x9c, 0xd1, 0xa3, 0xc0, 0xf3, 0xa4, 0x27, 0x83, 0x0c, 0x9e, 0x9b, 0x42, 0xc4, + 0x43, 0x0a, 0x9f, 0x4c, 0x8e, 0x00, 0x2b, 0xb4, 0x1f, 0x6c, 0x66, 0xb8, 0x31, 0xfb, 0x02, 0xec, + 0x71, 0xe5, 0x0d, 0x45, 0x28, 0x7e, 0x0e, 0x9a, 0xe4, 0x1d, 0x93, 0xd0, 0xb1, 0x49, 0x8a, 0x93, + 0x97, 0x14, 0x36, 0x32, 0x99, 0xf7, 0x15, 0xce, 0x58, 0x63, 0xea, 0x04, 0x80, 0x33, 0x35, 0x1d, + 0x86, 0x89, 0x15, 0x9f, 0xb0, 0xeb, 0x7b, 0xd5, 0x68, 0x24, 0xe0, 0x7d, 0x84, 0x8a, 0x4f, 0xe0, + 0x6a, 0xe8, 0x44, 0xae, 0x3d, 0xb5, 0x3c, 0x33, 0x3f, 0x10, 0x1c, 0x8a, 0x77, 0x43, 0x61, 0x77, + 0x32, 0x03, 0x82, 0xc5, 0x8f, 0xad, 0x73, 0x3a, 0x04, 0xf2, 0x3c, 0xc7, 0x73, 0xa3, 0xb1, 0x8c, + 0xc8, 0xd8, 0x18, 0x5b, 0xe7, 0xfb, 0x29, 0x94, 0x6e, 0x24, 0x4d, 0x3c, 0x77, 0x26, 0xca, 0x1f, + 0x8f, 0x25, 0xc2, 0x0d, 0x46, 0x0b, 0x1d, 0x56, 0xb1, 0x40, 0xb2, 0x77, 0x26, 0xce, 0xec, 0x45, + 0xa3, 0x36, 0xb6, 0xd8, 0x92, 0x10, 0x9c, 0xd1, 0xb5, 0xfc, 0x84, 0x86, 0xfd, 0x67, 0xa5, 0x0b, + 0xab, 0x24, 0x62, 0x17, 0x5a, 0xaa, 0x1a, 0xcf, 0x0e, 0x35, 0xac, 0x0d, 0x76, 0x1f, 0x92, 0x60, + 0x35, 0xa6, 0xd7, 0x81, 0x8f, 0x52, 0x71, 0x8a, 0xac, 0x11, 0x45, 0x99, 0xd2, 0xbc, 0x12, 0xa6, + 0x91, 0x13, 0x32, 0xfb, 0x34, 0x89, 0xf1, 0x72, 0xa4, 0xbf, 0x55, 0x04, 0x13, 0x03, 0x7d, 0x8a, + 0x1c, 0xf8, 0x1e, 0x68, 0x44, 0xa7, 0x4e, 0x5e, 0xa2, 0xc0, 0xa7, 0x53, 0xdb, 0xba, 0xd1, 0x40, + 0xb8, 0x3c, 0x57, 0x89, 0x02, 0x5f, 0x7c, 0x0e, 0x9b, 0x44, 0x39, 0x71, 0x27, 0x0e, 0x8a, 0x2f, + 0xc8, 0x79, 0x8e, 0x1d, 0xce, 0x21, 0xee, 0x14, 0xef, 0xd5, 0x8d, 0x2b, 0x88, 0xdf, 0x97, 0xe8, + 0x01, 0x62, 0x29, 0xe3, 0x7d, 0x58, 0xcf, 0x54, 0x45, 0x0e, 0x0d, 0xc7, 0x0d, 0x5b, 0x4b, 0x2a, + 0x23, 0x47, 0xe5, 0x23, 0xd8, 0x90, 0x3e, 0x26, 0x92, 0x9c, 0xa7, 0x13, 0x1d, 0xdc, 0x56, 0x0c, + 0x21, 0x71, 0x94, 0x83, 0xe7, 0x9d, 0x78, 0x03, 0xea, 0x64, 0x7d, 0x90, 0x11, 0x36, 0x65, 0xec, + 0xb0, 0x1a, 0xc1, 0x38, 0x80, 0x9d, 0xfe, 0xd7, 0x0b, 0x20, 0xe6, 0xa7, 0xea, 0xcb, 0xa2, 0xe1, + 0xe0, 0x54, 0x53, 0xa1, 0x28, 0xf0, 0xb7, 0x78, 0x17, 0xca, 0xe3, 0x80, 0xc5, 0xa9, 0xe2, 0x4b, + 0x62, 0xd1, 0xad, 0x8c, 0x03, 0x12, 0xaf, 0xde, 0x81, 0xb5, 0x51, 0xe0, 0xcb, 0x41, 0x63, 0xee, + 0xc2, 0x6b, 0xad, 0x91, 0x82, 0x91, 0xc7, 0xe8, 0xff, 0x49, 0x01, 0x1a, 0xf9, 0x05, 0x20, 0xde, + 0xa6, 0x28, 0xde, 0xb9, 0x38, 0xe0, 0x79, 0x8a, 0xfe, 0x84, 0xa2, 0x7b, 0x2f, 0xaa, 0xe2, 0xeb, + 0x00, 0x24, 0x24, 0xf0, 0x68, 0xc8, 0xb0, 0xbe, 0x04, 0xa1, 0x11, 0xb8, 0x0d, 0x35, 0x7e, 0xa6, + 0x82, 0xf1, 0x25, 0x1a, 0x2d, 0xce, 0x11, 0x11, 0xc1, 0x47, 0x19, 0x8f, 0x0f, 0xf6, 0xe8, 0x58, + 0xbc, 0x48, 0x13, 0x2a, 0xfd, 0x8f, 0x0b, 0x00, 0xe9, 0x1a, 0xc0, 0x99, 0x78, 0xea, 0x5c, 0xd0, + 0x32, 0x55, 0x5b, 0xec, 0xa9, 0x73, 0xb1, 0x2f, 0xeb, 0x26, 0xdd, 0x0e, 0x23, 0x79, 0xe7, 0xb3, + 0x6e, 0x54, 0xd9, 0xd3, 0x30, 0xe2, 0x20, 0x4b, 0xd2, 0xd1, 0x30, 0x53, 0x75, 0xf6, 0x2d, 0x8c, + 0x28, 0x8c, 0xc6, 0x1a, 0xe7, 0xa6, 0xa1, 0x8f, 0xdc, 0x17, 0x2a, 0x9c, 0x14, 0x3b, 0x46, 0x76, + 0x14, 0x14, 0x09, 0xb9, 0x9c, 0x94, 0x90, 0x2f, 0x61, 0xb1, 0x1b, 0x64, 0x42, 0xa8, 0x7b, 0x4a, + 0xe0, 0x6f, 0xc6, 0x31, 0x6d, 0xb0, 0x89, 0x29, 0xbe, 0xa0, 0x62, 0x48, 0xb1, 0x15, 0xfe, 0x35, + 0xba, 0xab, 0x2a, 0xc3, 0x47, 0x48, 0xb9, 0x3f, 0x09, 0x0b, 0xf1, 0x36, 0x8e, 0xb4, 0xa7, 0xb6, + 0x87, 0xc4, 0x8f, 0x6d, 0xd9, 0x58, 0x1d, 0x05, 0x1e, 0x6f, 0x0d, 0x08, 0xd4, 0xff, 0xb5, 0x65, + 0x80, 0xf4, 0x10, 0x36, 0xb7, 0x62, 0x0b, 0xf9, 0x15, 0xfb, 0x10, 0xae, 0xca, 0xf8, 0x7e, 0xc9, + 0x85, 0x2c, 0xd7, 0x37, 0x0f, 0x2d, 0x25, 0xc2, 0x09, 0x89, 0xe5, 0x6b, 0x34, 0x1d, 0x7f, 0xcb, + 0x8a, 0xc5, 0x63, 0xe4, 0x91, 0x69, 0x9e, 0xf8, 0x62, 0xf2, 0xd2, 0x29, 0xba, 0x9a, 0x66, 0x1f, + 0x5e, 0x4c, 0xc4, 0x47, 0x14, 0x26, 0x29, 0x74, 0xa2, 0x13, 0x33, 0x8e, 0xb2, 0x1f, 0xe3, 0x5b, + 0xf1, 0xeb, 0x12, 0x39, 0x8c, 0x92, 0x6f, 0x7d, 0x04, 0x57, 0x24, 0x93, 0x98, 0xa9, 0x1e, 0xbb, + 0x4b, 0x4a, 0x23, 0x74, 0xb6, 0x76, 0x34, 0xf2, 0x74, 0x32, 0xad, 0x9e, 0x53, 0xa9, 0xe0, 0xc8, + 0x63, 0x67, 0xc8, 0xd0, 0xd9, 0x74, 0xbc, 0x2c, 0x25, 0x17, 0x4e, 0x08, 0x1d, 0x4a, 0xb8, 0x42, + 0x88, 0x19, 0x37, 0x1e, 0x36, 0x1e, 0xd0, 0x73, 0x31, 0x14, 0xf6, 0x3c, 0xb0, 0x1d, 0x83, 0x70, + 0xe2, 0x03, 0xdc, 0xa1, 0xd3, 0x66, 0xab, 0x98, 0xff, 0x35, 0x69, 0xc7, 0x4e, 0x1a, 0x6a, 0x70, + 0xf4, 0xff, 0xf7, 0x40, 0x64, 0x6a, 0xae, 0xa8, 0xeb, 0x44, 0xbd, 0x96, 0x54, 0x5b, 0x12, 0xbf, + 0x03, 0x54, 0xc5, 0xf4, 0x6a, 0xd1, 0xcc, 0x59, 0x2c, 0x22, 0xe5, 0x75, 0xa4, 0x2b, 0x69, 0xeb, + 0x4c, 0x2b, 0x36, 0xe3, 0x13, 0x87, 0x8c, 0xde, 0x7c, 0xb7, 0x68, 0x3d, 0x69, 0x68, 0x33, 0x1e, + 0x9e, 0x38, 0x6d, 0xe2, 0xb5, 0x89, 0xb7, 0xcb, 0xda, 0x0f, 0x7b, 0xbb, 0x7c, 0x06, 0x9b, 0xf9, + 0xf3, 0x8e, 0x4c, 0x77, 0x33, 0x1b, 0xdf, 0xc8, 0xde, 0xd9, 0x4a, 0x7a, 0xfc, 0x3e, 0xac, 0xa3, + 0x4c, 0x98, 0xcb, 0x2b, 0x1d, 0xd3, 0xd6, 0x4e, 0xac, 0x28, 0x7b, 0x40, 0xa2, 0xff, 0x83, 0x15, + 0x68, 0xe4, 0x8f, 0xa5, 0x39, 0x9e, 0x1a, 0xef, 0xf3, 0x05, 0x92, 0x76, 0x92, 0xdd, 0xfc, 0x35, + 0xa8, 0xf2, 0xc5, 0x2e, 0x64, 0xc6, 0x2a, 0xf4, 0xf4, 0xa9, 0x64, 0xc1, 0xef, 0x42, 0x79, 0x72, + 0xfa, 0x0a, 0x06, 0x39, 0xe1, 0xb0, 0x27, 0xef, 0x42, 0x79, 0x7a, 0x9a, 0x06, 0x16, 0x5f, 0x48, + 0x3a, 0x3d, 0x95, 0x9e, 0xce, 0xd7, 0xe5, 0x81, 0xba, 0xbc, 0xf5, 0x35, 0x9e, 0x7a, 0xb1, 0x6b, + 0xd2, 0x91, 0x80, 0x5c, 0xda, 0x57, 0x99, 0xa0, 0x43, 0x78, 0x8a, 0x9c, 0x40, 0x87, 0x98, 0xc8, + 0xef, 0x64, 0xb0, 0xa5, 0x44, 0x66, 0x59, 0x36, 0x80, 0x83, 0x2b, 0x51, 0x73, 0xde, 0x05, 0x0d, + 0x35, 0x0d, 0xcf, 0x1d, 0xc5, 0x09, 0x55, 0x99, 0xa8, 0xd6, 0x14, 0x5c, 0x91, 0xbe, 0x05, 0x0d, + 0x79, 0x37, 0x47, 0x11, 0x72, 0x38, 0x80, 0x55, 0x86, 0x2a, 0xb2, 0xcf, 0xe0, 0x5a, 0x60, 0x9f, + 0x4e, 0xd5, 0x35, 0x33, 0x2b, 0x3c, 0x74, 0xe3, 0xd0, 0x4a, 0xe2, 0xcc, 0x55, 0x8c, 0x2b, 0x88, + 0x66, 0x2e, 0xd0, 0x4c, 0x91, 0xe4, 0xab, 0xc8, 0x59, 0x54, 0xf1, 0x40, 0xf5, 0x58, 0x65, 0xa8, + 0x2a, 0xfe, 0x13, 0xb8, 0x9a, 0xc4, 0x3f, 0x71, 0xc6, 0x8e, 0x1f, 0x9b, 0xa1, 0x43, 0xae, 0x5e, + 0xf2, 0x6d, 0x80, 0x0d, 0x15, 0x06, 0x85, 0x90, 0x06, 0xe3, 0xc4, 0x43, 0xb8, 0x32, 0x93, 0x4b, + 0x8e, 0x20, 0xcf, 0xfd, 0xcb, 0xb9, 0x4c, 0x72, 0x30, 0xdb, 0x70, 0x7b, 0x26, 0x4f, 0x2e, 0x9a, + 0x27, 0xe6, 0x5e, 0xa5, 0xdc, 0x37, 0x73, 0xb9, 0xb3, 0x51, 0x2b, 0xb1, 0x98, 0xcf, 0x61, 0x73, + 0xa6, 0x18, 0x1c, 0x11, 0x66, 0x94, 0x1c, 0xb5, 0xf4, 0x4a, 0x2e, 0xff, 0x53, 0xe7, 0x82, 0x19, + 0xeb, 0xcf, 0xe1, 0xe6, 0x4c, 0xc6, 0x5c, 0xf7, 0xcb, 0x6b, 0x78, 0xd7, 0x73, 0x99, 0xfb, 0x99, + 0xa1, 0xc0, 0xa9, 0x8a, 0x9f, 0xe2, 0xe0, 0x88, 0x1a, 0x49, 0x8c, 0xb8, 0x37, 0xf5, 0x28, 0x3e, + 0xe2, 0x3b, 0x8c, 0xe4, 0x33, 0xd5, 0xf5, 0xd9, 0x33, 0x55, 0x22, 0xe4, 0x83, 0xd4, 0xb7, 0x61, + 0x4d, 0x11, 0xf2, 0xc9, 0x52, 0x44, 0x42, 0xce, 0xb2, 0xb1, 0x2a, 0x49, 0xe8, 0x40, 0x29, 0xd2, + 0xff, 0x70, 0x19, 0xea, 0x59, 0x9f, 0x9f, 0x1f, 0x73, 0xe9, 0xed, 0x27, 0x5d, 0x19, 0x95, 0x6a, + 0x1e, 0xf5, 0x09, 0xae, 0xe6, 0x62, 0xa2, 0xe6, 0x35, 0xa7, 0x31, 0x4a, 0x34, 0xa4, 0x7a, 0x05, + 0x9e, 0x8a, 0x10, 0xc4, 0xfc, 0x1b, 0x77, 0x2e, 0x19, 0x1c, 0xe8, 0x23, 0x19, 0x80, 0x8c, 0x42, + 0x42, 0x52, 0x70, 0x86, 0x79, 0x1f, 0xe8, 0xba, 0x8a, 0x08, 0x49, 0xc1, 0x28, 0x1e, 0xc2, 0x5a, + 0x1a, 0xee, 0x89, 0xb3, 0xac, 0xcc, 0x65, 0x59, 0x4d, 0x62, 0x3d, 0xc9, 0x20, 0xe3, 0xab, 0x6e, + 0x64, 0x06, 0x9e, 0xad, 0xc2, 0xf6, 0x95, 0x95, 0x47, 0x66, 0xdf, 0xb3, 0x65, 0x68, 0x3e, 0xa6, + 0xf1, 0x9d, 0x33, 0x45, 0x93, 0x78, 0x6d, 0xf6, 0x9c, 0x33, 0x49, 0xf3, 0x00, 0x2e, 0x63, 0x73, + 0xe5, 0x9a, 0xe0, 0x60, 0x1d, 0x41, 0x28, 0xd7, 0x10, 0x32, 0x37, 0x5e, 0x42, 0x03, 0x89, 0xc8, + 0x5c, 0xd7, 0x0c, 0x83, 0x33, 0xd3, 0x9f, 0x8e, 0x0f, 0x99, 0xcd, 0x4b, 0x61, 0x5e, 0x5e, 0xd7, + 0x34, 0x82, 0xb3, 0x1e, 0xa1, 0xb0, 0xbf, 0xee, 0xc3, 0xba, 0x5a, 0xa5, 0x23, 0x3a, 0xcd, 0x52, + 0x37, 0x8e, 0x97, 0x8d, 0x35, 0x46, 0x34, 0x09, 0x8e, 0xb4, 0xef, 0x26, 0xb4, 0x7c, 0x71, 0x94, + 0x68, 0x79, 0xf5, 0x34, 0xe2, 0xf4, 0xd6, 0x28, 0x92, 0xb6, 0xe0, 0x56, 0x1c, 0x5a, 0xa3, 0x53, + 0xf3, 0x65, 0xcb, 0x47, 0x5e, 0x54, 0x7d, 0x8d, 0xa8, 0x9a, 0x0b, 0x17, 0xcf, 0x8f, 0x59, 0x7d, + 0x8d, 0x57, 0xaf, 0x3e, 0xfd, 0x0f, 0x4a, 0xb0, 0x3e, 0xe7, 0x2c, 0x85, 0x0a, 0x75, 0xfa, 0xb6, + 0x18, 0xfe, 0x44, 0xe1, 0x79, 0x6c, 0xc5, 0xa3, 0x13, 0xd4, 0xd1, 0x8e, 0xdc, 0x73, 0xf5, 0xae, + 0x1a, 0xc1, 0xf6, 0x09, 0x84, 0xbc, 0x94, 0xe5, 0x2a, 0x76, 0x27, 0x65, 0x21, 0x87, 0x45, 0x36, + 0xf6, 0xcd, 0x56, 0x21, 0x3f, 0xe6, 0xaf, 0x88, 0x70, 0xc8, 0x8f, 0x1b, 0x50, 0xf5, 0x03, 0xba, + 0x46, 0x3c, 0x39, 0x95, 0x7c, 0xbb, 0xec, 0x07, 0x71, 0xdf, 0xdf, 0x3f, 0x45, 0x06, 0x35, 0x8d, + 0xe8, 0x22, 0xd8, 0xa1, 0x13, 0x46, 0x27, 0x6e, 0xe2, 0xb6, 0xc0, 0xc2, 0xc2, 0xe5, 0x69, 0xe4, + 0xec, 0x25, 0x38, 0x69, 0x6f, 0x6a, 0x42, 0x9d, 0x66, 0xb2, 0x3f, 0x0a, 0xc8, 0x11, 0x8a, 0x1d, + 0xef, 0x6f, 0x2d, 0xf0, 0x10, 0x7b, 0xea, 0x5c, 0xb4, 0x25, 0x95, 0x81, 0x1b, 0x82, 0x4a, 0x88, + 0x77, 0x29, 0x9a, 0xd3, 0xa1, 0x93, 0xda, 0x48, 0xf3, 0x6c, 0xa0, 0x4a, 0x58, 0xda, 0x85, 0x9e, + 0xc2, 0x75, 0xde, 0x4a, 0xc6, 0x93, 0xc0, 0xc7, 0xf1, 0x48, 0x33, 0x46, 0x79, 0x9f, 0xe2, 0xcc, + 0x16, 0x76, 0x95, 0xb6, 0x1a, 0x99, 0x63, 0x5f, 0x95, 0x85, 0xdb, 0x0e, 0xb0, 0x53, 0x00, 0x75, + 0x18, 0xcc, 0x7b, 0x66, 0x11, 0x96, 0xd6, 0xd3, 0xbb, 0xa0, 0x45, 0x23, 0xcb, 0xb3, 0xc2, 0x8c, + 0xfa, 0xcc, 0xac, 0x7e, 0x8d, 0xe1, 0xa9, 0xe2, 0xf0, 0x3a, 0xc0, 0x78, 0x1a, 0xc5, 0x26, 0xf9, + 0xb9, 0xa8, 0x30, 0xd2, 0x08, 0xa1, 0x93, 0x10, 0xfd, 0x26, 0xac, 0x74, 0x12, 0xa7, 0xb8, 0x24, + 0x26, 0x43, 0x51, 0x3e, 0x5f, 0x14, 0x40, 0x95, 0xbd, 0x25, 0xf6, 0xac, 0x89, 0xb8, 0x0f, 0xc5, + 0xb1, 0x35, 0x91, 0xb7, 0x75, 0x36, 0x93, 0x2b, 0x4d, 0x8c, 0x7d, 0xb0, 0x67, 0x4d, 0xd8, 0xce, + 0x8b, 0x44, 0x37, 0x3e, 0x83, 0x8a, 0x02, 0xfc, 0xb4, 0x48, 0x56, 0x4b, 0x50, 0xdd, 0xce, 0x3a, + 0xb5, 0xa2, 0x2e, 0x1c, 0x87, 0x53, 0x9f, 0x9a, 0x28, 0x1f, 0x6a, 0x19, 0x59, 0xfe, 0x50, 0x82, + 0x14, 0x43, 0x7d, 0xc9, 0xad, 0x17, 0x62, 0xa8, 0x37, 0x01, 0xe4, 0xf2, 0x74, 0x6d, 0x25, 0x87, + 0x57, 0x42, 0x5c, 0x98, 0x1d, 0xfb, 0x7c, 0xf1, 0x1d, 0xe3, 0xd2, 0x8f, 0xbf, 0x63, 0xbc, 0xbc, + 0xf0, 0x8e, 0xf1, 0xdb, 0xa9, 0xe8, 0x4d, 0x3b, 0x9b, 0x7d, 0x2e, 0x1f, 0x85, 0x50, 0x82, 0x36, + 0xee, 0x68, 0xf6, 0xb9, 0xf8, 0x12, 0x1a, 0xaa, 0x75, 0xb2, 0x3c, 0xc8, 0xc5, 0x15, 0x94, 0x38, + 0xf6, 0x82, 0x5d, 0x8d, 0xb3, 0xc9, 0xfc, 0x46, 0x51, 0x7b, 0xc5, 0x3d, 0xe6, 0xbf, 0x59, 0x00, + 0x21, 0x7d, 0x98, 0x76, 0xa6, 0x9e, 0x37, 0x74, 0xce, 0x69, 0x3f, 0xba, 0x0f, 0xeb, 0xb9, 0x0b, + 0x3a, 0x19, 0x4d, 0x67, 0x2d, 0x73, 0x23, 0x47, 0x05, 0x6b, 0x9e, 0x0b, 0xcd, 0xbb, 0xb4, 0x30, + 0x34, 0xef, 0xe2, 0x90, 0xbf, 0xb7, 0xa1, 0x96, 0x0d, 0x6c, 0xcb, 0xaa, 0x2f, 0x58, 0x49, 0x4c, + 0x5b, 0xfd, 0x7f, 0x5a, 0x02, 0x48, 0xfd, 0xac, 0xfe, 0xb2, 0x2f, 0x88, 0x2f, 0x18, 0x92, 0xe2, + 0xa2, 0x21, 0xb9, 0x07, 0x5a, 0x96, 0x2e, 0x13, 0x61, 0xb9, 0x91, 0x12, 0x2a, 0x15, 0xd0, 0x8d, + 0xb2, 0x41, 0x6c, 0x29, 0x74, 0x9a, 0xbc, 0x53, 0xcb, 0x48, 0x16, 0x41, 0x25, 0xc3, 0xaa, 0xb8, + 0x11, 0x4b, 0x02, 0x24, 0xbd, 0xaa, 0x9c, 0xe4, 0x61, 0x11, 0x4c, 0xe3, 0xe4, 0xfe, 0x4d, 0x59, + 0x4a, 0xaf, 0xb2, 0xa4, 0xe7, 0x8c, 0x56, 0xf7, 0x6f, 0x3e, 0x85, 0xea, 0xd1, 0xd4, 0xf3, 0xcc, + 0xd8, 0x39, 0x57, 0x77, 0x82, 0x36, 0x73, 0x2e, 0x6a, 0x99, 0xe1, 0x35, 0x2a, 0x47, 0x32, 0xa1, + 0xff, 0xaf, 0x2b, 0xb0, 0xcc, 0x86, 0xf1, 0xcf, 0xa0, 0x1a, 0xc5, 0xe3, 0x38, 0x7b, 0x5b, 0x44, + 0xba, 0x1e, 0x11, 0x9e, 0x2e, 0x7b, 0xd0, 0xb6, 0xc1, 0x32, 0x0f, 0xd2, 0x12, 0xaf, 0xdb, 0x80, + 0xe5, 0x28, 0x76, 0x26, 0x91, 0x8c, 0xbb, 0xc2, 0x09, 0x71, 0x07, 0x96, 0xfd, 0xc0, 0x76, 0xa2, + 0x7c, 0x74, 0x95, 0x1e, 0x6a, 0x63, 0x8c, 0x10, 0x3a, 0xac, 0x24, 0x23, 0x3e, 0x77, 0x63, 0x83, + 0x31, 0x14, 0xb3, 0xcd, 0xb1, 0x90, 0xfb, 0xaa, 0x88, 0xd5, 0x49, 0x1a, 0xd5, 0x0e, 0x3a, 0x4f, + 0xb3, 0x8e, 0x55, 0x0c, 0x7f, 0x99, 0x14, 0x77, 0xa0, 0x86, 0x3f, 0x9f, 0x87, 0x6e, 0xec, 0x0c, + 0x1e, 0x29, 0x99, 0x22, 0x03, 0x12, 0xb7, 0x00, 0x6c, 0x27, 0x76, 0x46, 0xf1, 0xe0, 0x3b, 0x4f, + 0x19, 0x08, 0x33, 0x10, 0xf1, 0x25, 0x88, 0x43, 0x6b, 0x74, 0x7a, 0xcc, 0x17, 0x8e, 0xbe, 0x9b, + 0x3a, 0xa1, 0x9b, 0x30, 0xee, 0x5a, 0xa6, 0x53, 0x8c, 0xf5, 0x94, 0xec, 0x97, 0x4c, 0x25, 0xae, + 0xc2, 0xca, 0xd8, 0x3a, 0xdf, 0x0e, 0x26, 0xd2, 0x82, 0x2e, 0x53, 0xe2, 0x11, 0x5c, 0x45, 0x19, + 0x25, 0x1b, 0x7d, 0x44, 0x7a, 0x05, 0x32, 0x87, 0x46, 0x09, 0x26, 0x0d, 0x3b, 0x22, 0xcf, 0xae, + 0xb7, 0x60, 0x43, 0x19, 0xc8, 0x6d, 0x67, 0xe2, 0xf8, 0xb6, 0xe3, 0x8f, 0xdc, 0x24, 0xe6, 0xe7, + 0xdc, 0xe4, 0xbf, 0x2c, 0x89, 0xb7, 0x33, 0xb4, 0xe2, 0x4d, 0x58, 0xc5, 0x0f, 0x87, 0x4e, 0x3c, + 0x0d, 0x7d, 0xdc, 0xfb, 0x58, 0xa2, 0x40, 0x01, 0xd1, 0x50, 0x30, 0x76, 0x73, 0x96, 0x89, 0xf4, + 0x9e, 0xd4, 0xb2, 0xb1, 0x9a, 0x40, 0xc9, 0x37, 0xff, 0x11, 0x5c, 0x65, 0x07, 0xca, 0xe8, 0x3b, + 0x4f, 0xca, 0x59, 0x66, 0x7a, 0x63, 0xa4, 0x62, 0x5c, 0x26, 0xec, 0xe0, 0x3b, 0x8f, 0x45, 0x2d, + 0xde, 0xeb, 0xfb, 0x70, 0x75, 0xea, 0x87, 0x4e, 0x14, 0x78, 0x2f, 0x92, 0xe0, 0xca, 0x27, 0x2e, + 0x0a, 0xc7, 0x5a, 0xf6, 0x5a, 0xde, 0x41, 0x42, 0x43, 0x32, 0xfd, 0xae, 0xeb, 0xc7, 0xc6, 0xc6, + 0x74, 0x1e, 0x18, 0x89, 0x1e, 0x6c, 0xa8, 0xb7, 0x9f, 0x72, 0xbd, 0xc2, 0xa2, 0xf9, 0x6b, 0xea, + 0xa2, 0x06, 0x51, 0xec, 0x7b, 0x96, 0x9f, 0x74, 0xc7, 0x85, 0x71, 0x59, 0x66, 0xcc, 0xf6, 0x90, + 0xfe, 0x7b, 0xb0, 0x9a, 0x9b, 0xdd, 0x73, 0x4e, 0x46, 0x83, 0x76, 0xb7, 0xdd, 0x1a, 0xb2, 0xd7, + 0x80, 0x74, 0x7b, 0x59, 0xca, 0xf8, 0xc7, 0x94, 0x32, 0xde, 0x04, 0xcb, 0xe4, 0x5d, 0xd3, 0x36, + 0x9e, 0xb4, 0xc9, 0xe1, 0xa3, 0xa8, 0x15, 0xf5, 0xbf, 0xb5, 0x04, 0xeb, 0xc3, 0xd0, 0xf2, 0x23, + 0x8b, 0xb5, 0x68, 0x3f, 0x0e, 0x03, 0x4f, 0x7c, 0x09, 0x95, 0x78, 0xe4, 0x65, 0x97, 0xdb, 0x6d, + 0xc5, 0xdc, 0x67, 0x48, 0x1f, 0x0c, 0x47, 0xec, 0x30, 0x5d, 0x8e, 0xf9, 0x87, 0xf8, 0x00, 0x96, + 0x0f, 0x9d, 0x63, 0xd7, 0x97, 0xfb, 0xdb, 0x95, 0xd9, 0x8c, 0x5b, 0x88, 0xdc, 0xbd, 0x64, 0x30, + 0x95, 0xf8, 0x08, 0x56, 0xe4, 0xb9, 0x53, 0x31, 0x7b, 0x6f, 0x21, 0xfb, 0x21, 0xc4, 0xee, 0x5e, + 0x32, 0x24, 0x9d, 0xf8, 0x0c, 0x2a, 0x61, 0x20, 0x1f, 0x94, 0x2a, 0x65, 0x99, 0x49, 0x9a, 0xc7, + 0x90, 0xf8, 0xdd, 0x4b, 0x46, 0x42, 0xab, 0x3f, 0x80, 0xb2, 0xac, 0x2c, 0x76, 0xc3, 0x56, 0xfb, + 0x49, 0x47, 0xf6, 0x60, 0xab, 0xbf, 0xb7, 0xd7, 0x19, 0x72, 0xbc, 0x69, 0xa3, 0xdf, 0xed, 0x6e, + 0x35, 0x5b, 0x4f, 0xb5, 0xa5, 0xad, 0x0a, 0xac, 0xf0, 0x22, 0xd0, 0xff, 0xc5, 0x02, 0xac, 0xcd, + 0x34, 0x40, 0x3c, 0x86, 0x12, 0x59, 0x43, 0xb9, 0x7b, 0xee, 0x2e, 0x6c, 0x65, 0x26, 0xcd, 0xb6, + 0x1e, 0xcc, 0xa1, 0x7f, 0x01, 0x8d, 0x3c, 0x3c, 0xe3, 0x93, 0xb2, 0x0a, 0x55, 0xa3, 0xdd, 0xdc, + 0x36, 0xfb, 0xbd, 0xee, 0x37, 0xec, 0x27, 0x46, 0xc9, 0xe7, 0x46, 0x87, 0x9c, 0x41, 0x7e, 0x17, + 0xb4, 0xd9, 0x8e, 0x11, 0x4f, 0x60, 0x0d, 0x65, 0x39, 0xcf, 0x61, 0x07, 0xb8, 0x74, 0xc8, 0x6e, + 0x2d, 0xe8, 0x49, 0x49, 0xc6, 0xb7, 0xa9, 0x47, 0xb9, 0xb4, 0xfe, 0x7b, 0x20, 0xe6, 0x7b, 0xf0, + 0x2f, 0xaf, 0xf8, 0xff, 0xbb, 0x00, 0x25, 0x9c, 0xf0, 0xe2, 0x4d, 0x58, 0xe6, 0x23, 0xd0, 0x42, + 0xf6, 0xbe, 0x1e, 0xf1, 0x2c, 0x9c, 0x16, 0x84, 0x13, 0xef, 0x41, 0x31, 0x1e, 0xa9, 0xc8, 0xd2, + 0xd7, 0x5e, 0x32, 0xf9, 0x76, 0x2f, 0x19, 0x48, 0x25, 0xee, 0x41, 0xd1, 0xb6, 0x55, 0x5c, 0xb2, + 0xcc, 0x01, 0xf9, 0xb6, 0x73, 0x44, 0x37, 0x36, 0xe9, 0x2d, 0x25, 0x24, 0x11, 0x6f, 0x41, 0xd1, + 0x1e, 0x79, 0xf9, 0x20, 0x73, 0x7c, 0x76, 0x9d, 0x14, 0x68, 0x8f, 0x3c, 0xd4, 0xeb, 0xe2, 0xf0, + 0xc2, 0x0c, 0xa7, 0x3e, 0x85, 0xe5, 0x50, 0x0f, 0x82, 0xd5, 0x50, 0x56, 0x9c, 0x52, 0x6c, 0x8f, + 0x48, 0x86, 0xa8, 0x95, 0x2f, 0xfe, 0x28, 0x5b, 0xa0, 0x1b, 0xc9, 0xb7, 0x81, 0xb6, 0x56, 0x80, + 0x1e, 0x93, 0xd6, 0xdf, 0xa7, 0xc7, 0x65, 0x50, 0x8d, 0xd7, 0xd5, 0xaf, 0x05, 0x2f, 0x6f, 0x4a, + 0x8c, 0xfe, 0x4f, 0x8a, 0x50, 0xcb, 0xd4, 0x47, 0x7c, 0x02, 0x15, 0x3b, 0xbf, 0x10, 0xaf, 0xcf, + 0x55, 0xfa, 0xc1, 0xb6, 0x5a, 0x82, 0xb6, 0x9c, 0xde, 0xe4, 0x8d, 0x1f, 0x9b, 0x2f, 0xac, 0xd0, + 0xe5, 0x2b, 0xc6, 0x4b, 0x59, 0xb7, 0xf8, 0x81, 0x13, 0x3f, 0x53, 0x98, 0xdd, 0x4b, 0x46, 0x3d, + 0xca, 0xa4, 0xc9, 0xf2, 0x25, 0x9b, 0x54, 0xcc, 0xc6, 0x2e, 0x96, 0xcd, 0xda, 0xbd, 0x64, 0x28, + 0x3c, 0x92, 0x3a, 0xe7, 0xce, 0x68, 0x1a, 0x2b, 0xcb, 0xd7, 0xaa, 0x6a, 0x10, 0x01, 0xe9, 0x79, + 0x5c, 0xfe, 0x29, 0x1e, 0xe2, 0x9e, 0x66, 0x79, 0x5e, 0x40, 0x22, 0xf1, 0x72, 0xf6, 0xd8, 0x69, + 0x3b, 0x81, 0xf3, 0x73, 0xbc, 0x2a, 0x25, 0xde, 0x86, 0xe5, 0x20, 0x3e, 0x71, 0x94, 0xa6, 0xae, + 0x9e, 0xa9, 0x41, 0xd0, 0x76, 0xab, 0x8b, 0x33, 0x85, 0xd0, 0xfa, 0x1f, 0x15, 0xa0, 0x2c, 0x7b, + 0x40, 0xac, 0xc3, 0xea, 0xa0, 0x3d, 0x34, 0x9f, 0x35, 0x8d, 0x4e, 0x73, 0xab, 0xdb, 0x96, 0xb1, + 0xf1, 0x9e, 0x18, 0xcd, 0x9e, 0x64, 0x90, 0x46, 0xfb, 0x59, 0xff, 0x69, 0x9b, 0x1d, 0xbd, 0xb6, + 0xdb, 0xbd, 0x6f, 0xb4, 0x22, 0x3b, 0x45, 0xb6, 0xf7, 0x9b, 0x06, 0xf2, 0xca, 0x1a, 0x94, 0xdb, + 0x5f, 0xb7, 0x5b, 0x07, 0xc4, 0x2c, 0x1b, 0x00, 0xdb, 0xed, 0x66, 0xb7, 0xdb, 0x6f, 0x21, 0xf3, + 0x5c, 0x11, 0x02, 0x1a, 0x2d, 0xa3, 0xdd, 0x1c, 0xb6, 0xcd, 0x66, 0xab, 0xd5, 0x3f, 0xe8, 0x0d, + 0xb5, 0x32, 0x7e, 0xb1, 0xd9, 0x1d, 0xb6, 0x8d, 0x04, 0x44, 0x8f, 0xef, 0x6d, 0x1b, 0xfd, 0xfd, + 0x04, 0x52, 0xdd, 0xaa, 0x42, 0x79, 0xc4, 0x63, 0xa5, 0xff, 0xc7, 0xeb, 0xec, 0xef, 0x90, 0x4e, + 0x4d, 0xf1, 0x39, 0x54, 0x6c, 0x3b, 0x37, 0xc6, 0x37, 0x17, 0x4d, 0xe1, 0x07, 0xdb, 0xb6, 0x1a, + 0x66, 0xfe, 0x21, 0xde, 0x50, 0x0b, 0x69, 0x69, 0x6e, 0x21, 0xa9, 0x65, 0xf4, 0x73, 0x58, 0x93, + 0x6f, 0x9f, 0x24, 0x47, 0xa5, 0xb9, 0x55, 0xd2, 0x22, 0xe4, 0xb6, 0xc4, 0xed, 0x5e, 0x32, 0x1a, + 0xa3, 0x1c, 0x44, 0xfc, 0x0c, 0x1a, 0x16, 0x1f, 0x40, 0x66, 0x8f, 0x5a, 0x13, 0x61, 0xbf, 0x49, + 0xe7, 0x8f, 0x69, 0xf6, 0x55, 0x2b, 0x0b, 0xc0, 0x89, 0x68, 0x87, 0xc1, 0x24, 0xcd, 0xbc, 0x9c, + 0xbb, 0x9f, 0x11, 0x06, 0x93, 0x4c, 0xde, 0xba, 0x9d, 0x49, 0x8b, 0xcf, 0xa0, 0x2e, 0x6b, 0x9e, + 0x1a, 0xdb, 0x93, 0x25, 0xcb, 0xd5, 0x26, 0xe1, 0x7d, 0xf7, 0x92, 0x51, 0x1b, 0xa5, 0x49, 0xf1, + 0x08, 0x25, 0xf6, 0x54, 0xd5, 0x29, 0x67, 0xe7, 0x1a, 0xd5, 0x56, 0xe5, 0x02, 0x2b, 0x49, 0x89, + 0x8f, 0x00, 0xa8, 0x9e, 0x9c, 0xa7, 0x92, 0xbb, 0xb9, 0x18, 0x06, 0x13, 0x95, 0xa5, 0x6a, 0xab, + 0x44, 0xa6, 0x7a, 0x6c, 0x01, 0xac, 0xce, 0x57, 0x8f, 0x85, 0x82, 0xa4, 0x7a, 0x6c, 0x0c, 0x4c, + 0xaa, 0xc7, 0xd9, 0x60, 0xae, 0x7a, 0x2a, 0x17, 0x57, 0x8f, 0x33, 0xa9, 0xea, 0x71, 0x9e, 0xda, + 0x6c, 0xf5, 0x54, 0x16, 0xaa, 0x1e, 0xe7, 0xf8, 0xd9, 0x9c, 0x8e, 0x56, 0x7f, 0xa9, 0x8e, 0x86, + 0xc3, 0x96, 0xd7, 0xd2, 0x7e, 0x06, 0x8d, 0xe8, 0x24, 0x38, 0xcb, 0x30, 0x90, 0xd5, 0x6c, 0xee, + 0xc1, 0x49, 0x70, 0x96, 0xe5, 0x20, 0xab, 0x51, 0x16, 0x80, 0xb5, 0xe5, 0x26, 0xd2, 0x5d, 0x8a, + 0x46, 0xb6, 0xb6, 0xd4, 0xc2, 0x67, 0xae, 0x73, 0x86, 0xb5, 0xb5, 0x54, 0x02, 0x3b, 0x25, 0x3d, + 0x78, 0x88, 0xe4, 0x51, 0x42, 0xee, 0xbe, 0x9f, 0xfc, 0x12, 0x24, 0x47, 0x10, 0x11, 0xce, 0xad, + 0xa9, 0x9f, 0xcd, 0xa6, 0x65, 0xe7, 0xd6, 0x81, 0x9f, 0xcb, 0x58, 0x67, 0x52, 0x99, 0x35, 0x5d, + 0x15, 0x91, 0xf3, 0xdd, 0xd4, 0xf1, 0x47, 0x8e, 0xbc, 0xd7, 0x9b, 0x5b, 0x15, 0x03, 0x89, 0x4b, + 0x57, 0x85, 0x82, 0x24, 0xf3, 0x3a, 0xc9, 0x2e, 0x66, 0xe7, 0x75, 0x26, 0x33, 0xcd, 0xeb, 0x24, + 0x6b, 0xb2, 0xa0, 0x92, 0xbc, 0x97, 0xe7, 0x16, 0x54, 0x26, 0x33, 0x2f, 0xa8, 0x24, 0xf7, 0x23, + 0x90, 0xb3, 0x89, 0x3b, 0x37, 0x77, 0xfb, 0x97, 0x6b, 0x2d, 0x7b, 0x17, 0x46, 0x49, 0x0a, 0xe7, + 0x6a, 0xe8, 0xa0, 0x4e, 0x28, 0xa7, 0xc2, 0x95, 0xec, 0x5c, 0x35, 0x08, 0x93, 0x2c, 0xa5, 0x30, + 0x4d, 0x66, 0x3e, 0x36, 0x71, 0xe3, 0x70, 0xd3, 0x9e, 0xff, 0xd8, 0xbe, 0x1b, 0x87, 0xe9, 0xc7, + 0x30, 0x25, 0x3e, 0x00, 0x9a, 0x86, 0x9c, 0xc5, 0xc9, 0xb2, 0x6e, 0xec, 0x16, 0x99, 0xa1, 0x62, + 0xcb, 0xdf, 0x38, 0x59, 0xe4, 0x37, 0x46, 0xf6, 0x68, 0xf3, 0x28, 0x3b, 0x59, 0xf8, 0x13, 0xad, + 0xed, 0x16, 0x4e, 0x16, 0x26, 0x6a, 0xd9, 0x23, 0x71, 0x1f, 0x28, 0x37, 0xd1, 0x1f, 0x67, 0xf7, + 0x1d, 0x2c, 0x9f, 0xa9, 0xcb, 0x48, 0x80, 0xb4, 0xd8, 0x02, 0x2f, 0xf0, 0x55, 0xc3, 0x4f, 0x72, + 0x2d, 0x40, 0x44, 0xc2, 0x0c, 0x46, 0x49, 0x4a, 0xff, 0x97, 0x57, 0xa0, 0x2c, 0x79, 0xad, 0xb8, + 0x0c, 0x6b, 0x92, 0xe5, 0x6f, 0x37, 0x87, 0xcd, 0xad, 0xe6, 0x00, 0x85, 0x34, 0x01, 0x0d, 0xe6, + 0xf9, 0x09, 0xac, 0x80, 0xfb, 0x00, 0x31, 0xfd, 0x04, 0xb4, 0x84, 0xfb, 0x80, 0xcc, 0xcb, 0xee, + 0xb4, 0x45, 0xb1, 0x06, 0x35, 0xce, 0xc8, 0x00, 0x0a, 0xd5, 0x4b, 0xb9, 0x38, 0xbd, 0x9c, 0xc9, + 0xc2, 0x0e, 0xd1, 0x2b, 0x69, 0x16, 0x06, 0x94, 0x93, 0x2c, 0xca, 0x63, 0x5a, 0x40, 0x63, 0x68, + 0x1c, 0xf4, 0x5a, 0xe9, 0x77, 0xaa, 0x14, 0x5e, 0x95, 0x8b, 0x79, 0xd6, 0x69, 0x3f, 0xd7, 0x00, + 0x33, 0x71, 0x29, 0x94, 0x26, 0x4f, 0x6a, 0x2a, 0x84, 0x92, 0x75, 0x71, 0x0d, 0x2e, 0x0f, 0x76, + 0xfb, 0xcf, 0x4d, 0xce, 0x94, 0x34, 0x61, 0x55, 0x6c, 0x80, 0x96, 0x41, 0x70, 0xf1, 0x0d, 0xfc, + 0x24, 0x41, 0x15, 0xe1, 0x40, 0x5b, 0xa3, 0xc7, 0x59, 0x10, 0x36, 0xe4, 0x7d, 0x57, 0xc3, 0xa6, + 0x70, 0xd6, 0x7e, 0xf7, 0x60, 0xaf, 0x37, 0xd0, 0xd6, 0xb1, 0x12, 0x04, 0xe1, 0x9a, 0x8b, 0xa4, + 0x98, 0x74, 0xb7, 0xbe, 0x4c, 0x1b, 0x38, 0xc2, 0x9e, 0x37, 0x8d, 0x5e, 0xa7, 0xf7, 0x64, 0xa0, + 0x6d, 0x24, 0x25, 0xb7, 0x0d, 0xa3, 0x6f, 0x0c, 0xb4, 0x2b, 0x09, 0x60, 0x30, 0x6c, 0x0e, 0x0f, + 0x06, 0xda, 0xd5, 0xa4, 0x96, 0xfb, 0x46, 0xbf, 0xd5, 0x1e, 0x0c, 0xba, 0x9d, 0xc1, 0x50, 0xbb, + 0x26, 0xae, 0xc0, 0x7a, 0x5a, 0x23, 0x45, 0xbc, 0x99, 0xa9, 0xa8, 0xf1, 0xa4, 0x3d, 0xd4, 0xae, + 0x27, 0xd5, 0x68, 0xf5, 0xbb, 0xdd, 0x26, 0xf9, 0x6a, 0xdf, 0x40, 0x22, 0xba, 0x52, 0x20, 0x5b, + 0xf3, 0x1a, 0xd6, 0xeb, 0xa0, 0x97, 0x05, 0xdd, 0xcc, 0x4c, 0x8d, 0x41, 0xfb, 0x97, 0x07, 0xed, + 0x5e, 0xab, 0xad, 0xbd, 0x9e, 0x4e, 0x8d, 0x04, 0x76, 0x2b, 0x99, 0x1a, 0x09, 0xe8, 0x76, 0xf2, + 0x4d, 0x05, 0x1a, 0x68, 0x77, 0x92, 0x0e, 0x3b, 0xd8, 0x7f, 0x62, 0x34, 0xb7, 0xdb, 0x9a, 0x8e, + 0x10, 0xa3, 0xdd, 0x6b, 0xee, 0xa9, 0x81, 0x7d, 0x33, 0x33, 0xb0, 0xfb, 0x9d, 0xa1, 0xa1, 0xdd, + 0x4d, 0x06, 0x92, 0x92, 0x6f, 0x89, 0xd7, 0xe0, 0x5a, 0x76, 0xca, 0x99, 0xcf, 0x3b, 0xc3, 0x5d, + 0xe9, 0xf9, 0xff, 0x36, 0x3b, 0x8f, 0x13, 0xb2, 0xb5, 0xdd, 0xe2, 0x2b, 0x0e, 0x94, 0x17, 0x53, + 0xf7, 0xf4, 0x52, 0xe5, 0x0d, 0xed, 0x8d, 0xfb, 0x6b, 0xb2, 0x2b, 0x7a, 0x3d, 0xba, 0x3e, 0x32, + 0xd8, 0xaa, 0xa3, 0xe4, 0xa6, 0x44, 0x10, 0xfd, 0x2b, 0x10, 0xd9, 0xe7, 0xb4, 0x65, 0x80, 0x04, + 0x01, 0xa5, 0xa3, 0x30, 0x18, 0x2b, 0xb7, 0x13, 0xfc, 0x2d, 0xee, 0x40, 0x6d, 0x32, 0x3d, 0x24, + 0x5f, 0xf7, 0x34, 0x30, 0x76, 0x16, 0xa4, 0xff, 0x3b, 0x05, 0x68, 0xe4, 0xc5, 0x0f, 0x3a, 0x4e, + 0x39, 0x32, 0xfd, 0x20, 0xe6, 0xf7, 0xb1, 0xa2, 0xe4, 0x95, 0xeb, 0xa3, 0x5e, 0x10, 0xd3, 0x03, + 0x59, 0x51, 0xce, 0xeb, 0x6b, 0x69, 0xc6, 0xeb, 0xab, 0x03, 0x97, 0x73, 0xaf, 0x97, 0xe7, 0x5e, + 0x27, 0x93, 0x4a, 0xe2, 0x7c, 0xfd, 0x0d, 0x11, 0xcd, 0xb7, 0x49, 0x86, 0x37, 0x2f, 0xa5, 0xe1, + 0xcd, 0x77, 0x61, 0x35, 0x27, 0xed, 0x90, 0xb5, 0xec, 0x28, 0x5f, 0xd3, 0x8a, 0x7b, 0xf4, 0xea, + 0x6a, 0xea, 0x7f, 0xa7, 0x00, 0xf5, 0xac, 0xec, 0xf3, 0x1b, 0x97, 0x44, 0xf7, 0x16, 0xe5, 0x6f, + 0xd3, 0xb5, 0xd5, 0xb3, 0x56, 0x0a, 0x44, 0x2e, 0x95, 0x35, 0x3e, 0x99, 0xda, 0x39, 0x1d, 0x24, + 0xcd, 0xc9, 0x82, 0xc8, 0x53, 0xee, 0xc4, 0x19, 0x9d, 0xee, 0x3c, 0x45, 0x02, 0xe5, 0x29, 0x97, + 0x40, 0xf4, 0xdb, 0x50, 0xdd, 0x39, 0x55, 0xd7, 0x38, 0xb3, 0xaf, 0xc4, 0x55, 0x39, 0x9a, 0xba, + 0xfe, 0xc7, 0x05, 0x68, 0xa4, 0xb6, 0x21, 0x72, 0xd4, 0xe7, 0x57, 0xef, 0x79, 0x3a, 0x2c, 0xd9, + 0x87, 0xa9, 0x37, 0xe4, 0x52, 0xd6, 0x1b, 0xf2, 0x4d, 0x59, 0x58, 0x31, 0xcb, 0xf4, 0x93, 0x6f, + 0xc9, 0x58, 0xed, 0x8f, 0xa0, 0x8e, 0xff, 0x0d, 0xe7, 0xc8, 0x09, 0x43, 0xc7, 0xce, 0xc7, 0xbf, + 0x4a, 0x89, 0x73, 0x44, 0xa4, 0xe5, 0x25, 0x4f, 0x36, 0x2c, 0x7c, 0x54, 0x86, 0x1e, 0x3b, 0xfa, + 0x3f, 0x8b, 0x50, 0xcb, 0x48, 0x92, 0x3f, 0x6a, 0xfa, 0xdd, 0x84, 0x6a, 0xfa, 0xc4, 0x89, 0x0c, + 0x90, 0x9d, 0x00, 0x72, 0x63, 0x55, 0x9c, 0x19, 0x2b, 0x72, 0x4a, 0xa6, 0xa8, 0x9c, 0xa9, 0x53, + 0x32, 0x25, 0xf3, 0x46, 0xf1, 0xe5, 0x57, 0x9c, 0x9e, 0x7e, 0x0c, 0xf5, 0x8c, 0x45, 0x5b, 0xb9, + 0x2f, 0xce, 0xd2, 0xd7, 0x52, 0xeb, 0x76, 0x24, 0xae, 0xc0, 0xca, 0xd1, 0xa9, 0x69, 0x1f, 0xb2, + 0x47, 0x40, 0xd5, 0x58, 0x3e, 0x3a, 0xdd, 0x3e, 0x24, 0x0f, 0x88, 0xa3, 0x44, 0x78, 0x62, 0x3b, + 0x63, 0xe5, 0x48, 0x89, 0x48, 0xf7, 0xa0, 0x7c, 0x74, 0x9a, 0x0d, 0xb3, 0x3b, 0xd7, 0xe5, 0x2b, + 0x47, 0xa7, 0x14, 0xe9, 0xf5, 0x43, 0xd8, 0x90, 0x3b, 0xb8, 0x15, 0x29, 0xb3, 0x1b, 0x2e, 0x1d, + 0x7e, 0x33, 0x6e, 0x9d, 0x71, 0xcd, 0x88, 0x8d, 0x6e, 0x38, 0xe3, 0x74, 0xa8, 0x67, 0x26, 0x20, + 0xdb, 0x0b, 0xab, 0x46, 0x0e, 0x26, 0x1e, 0x43, 0xfd, 0xe8, 0x94, 0x07, 0x74, 0x18, 0xec, 0x39, + 0x32, 0x92, 0xcc, 0xc6, 0xec, 0x50, 0xd2, 0x4d, 0x8a, 0x1c, 0xa5, 0xb8, 0x0a, 0x2b, 0x86, 0x75, + 0x36, 0xf8, 0x65, 0x97, 0xc4, 0xc8, 0xaa, 0x21, 0x53, 0xfc, 0xa2, 0x9c, 0xfe, 0x0f, 0x0a, 0xd0, + 0x48, 0xb5, 0x00, 0x5c, 0x84, 0xe2, 0x7e, 0xfa, 0x98, 0x74, 0x43, 0x31, 0x89, 0x3c, 0xc9, 0x83, + 0xe1, 0xc5, 0x84, 0x1f, 0x67, 0x5d, 0xf4, 0xae, 0xd3, 0xa2, 0x23, 0x86, 0xe2, 0xc2, 0xc7, 0xef, + 0x9f, 0x40, 0x71, 0x78, 0x31, 0x61, 0x8b, 0x13, 0x6e, 0x8a, 0xac, 0x9d, 0xf2, 0x76, 0x48, 0xb7, + 0x95, 0x9e, 0xb6, 0xbf, 0xe1, 0x80, 0xfe, 0xfb, 0x46, 0x67, 0xaf, 0x69, 0x7c, 0x63, 0x22, 0x80, + 0xc4, 0x86, 0x9d, 0xbe, 0xd1, 0xee, 0x3c, 0xe9, 0x11, 0xa0, 0x44, 0xf6, 0xa8, 0xb4, 0x8a, 0x4d, + 0xdb, 0xde, 0x39, 0xcd, 0x3e, 0x89, 0x53, 0xc8, 0x3d, 0x89, 0x93, 0xbc, 0x1e, 0x95, 0x7d, 0xea, + 0x30, 0x4e, 0xce, 0x3d, 0x44, 0xb2, 0x0a, 0x93, 0x25, 0x2d, 0xde, 0x81, 0xd2, 0xd1, 0xa9, 0x73, + 0x91, 0x57, 0xf5, 0xf2, 0x0b, 0x88, 0x08, 0xf4, 0x3f, 0x2b, 0x80, 0xc8, 0x55, 0x84, 0xb5, 0x8f, + 0xdf, 0xb4, 0x2e, 0x9f, 0xc3, 0xa6, 0x7a, 0x17, 0x95, 0xa8, 0x32, 0x67, 0x1a, 0xb2, 0x4b, 0xaf, + 0x04, 0x69, 0x04, 0x83, 0xf4, 0xe9, 0x29, 0xf1, 0x21, 0xf0, 0x2b, 0x86, 0x74, 0xf1, 0xa6, 0xf4, + 0x12, 0x4d, 0xd1, 0x48, 0x69, 0xd2, 0x67, 0x0b, 0xb3, 0xcf, 0x31, 0xf2, 0x71, 0xc8, 0x5a, 0x3a, + 0x6a, 0xb4, 0xe6, 0xf5, 0xbf, 0x51, 0x80, 0xcb, 0xf9, 0x09, 0xf1, 0x17, 0x6b, 0x65, 0xfe, 0xed, + 0xc9, 0xe2, 0xec, 0xdb, 0x93, 0x8b, 0xe6, 0x53, 0x69, 0xe1, 0x7c, 0xfa, 0xfd, 0x02, 0x6c, 0x64, + 0x7a, 0x3f, 0xd5, 0x17, 0xff, 0x8a, 0x6a, 0x96, 0x79, 0x82, 0xb2, 0x94, 0x7b, 0x82, 0x52, 0xff, + 0xd3, 0x02, 0x5c, 0x9d, 0xa9, 0x89, 0xe1, 0xfc, 0x95, 0xd6, 0x25, 0xff, 0x54, 0x25, 0x1d, 0xc9, + 0xa8, 0xa0, 0xf7, 0x85, 0x7b, 0xc5, 0xcc, 0x53, 0x95, 0x74, 0x4e, 0x47, 0x87, 0xc5, 0xaf, 0xcb, + 0xb7, 0x51, 0xcc, 0xe8, 0xc2, 0x1f, 0xc9, 0xc1, 0xae, 0x12, 0x64, 0x70, 0xe1, 0x8f, 0x70, 0x93, + 0x1a, 0x3b, 0xe1, 0xb1, 0x32, 0xe5, 0x71, 0x42, 0xff, 0x0f, 0x0b, 0x70, 0x7d, 0xa6, 0x65, 0xcd, + 0x69, 0x1c, 0x48, 0xdf, 0x8e, 0xbf, 0xa2, 0xc6, 0xdd, 0x06, 0x7a, 0xb5, 0x49, 0x39, 0x95, 0x64, + 0x2e, 0x64, 0xc8, 0xef, 0x6a, 0x50, 0xb4, 0xad, 0x0b, 0x19, 0x33, 0x19, 0x7f, 0xe2, 0x32, 0x3e, + 0x09, 0xa6, 0xa1, 0xbc, 0x41, 0x40, 0xbf, 0xf5, 0x4f, 0x60, 0x3d, 0xad, 0x7a, 0x4b, 0xbe, 0x23, + 0x7a, 0x1b, 0x6a, 0xbe, 0x73, 0x66, 0xaa, 0x57, 0x46, 0xe5, 0xdd, 0x32, 0xdf, 0x39, 0x93, 0x04, + 0xfa, 0x4e, 0x96, 0x43, 0x52, 0x75, 0xae, 0x43, 0x25, 0xf0, 0xec, 0x9c, 0x47, 0x69, 0xe0, 0xd9, + 0x0a, 0x85, 0xa5, 0x65, 0x5a, 0x59, 0xf6, 0x9d, 0x33, 0x9a, 0x9d, 0x67, 0xb2, 0x9c, 0xa6, 0xad, + 0x3c, 0xa8, 0x16, 0xb9, 0x27, 0x5f, 0x87, 0xca, 0x24, 0xcc, 0x75, 0x53, 0x79, 0x12, 0xf2, 0x67, + 0xef, 0xca, 0x9b, 0x6b, 0x2f, 0xf3, 0xc0, 0xe3, 0xbb, 0x6c, 0x1a, 0x14, 0x27, 0x41, 0x24, 0x9d, + 0x84, 0xf0, 0xa7, 0xfe, 0xa9, 0x64, 0x8e, 0xa4, 0x0f, 0xf2, 0x97, 0x35, 0x28, 0xba, 0xf6, 0x39, + 0x7d, 0x78, 0xd5, 0xc0, 0x9f, 0x24, 0xdf, 0x39, 0xdf, 0xc9, 0xcb, 0x73, 0xf8, 0x53, 0xdf, 0x82, + 0x9a, 0x91, 0x53, 0x7e, 0xeb, 0x19, 0x3b, 0x52, 0x94, 0x7f, 0x83, 0x26, 0xed, 0x20, 0xa3, 0x96, + 0x9a, 0x91, 0x22, 0x3d, 0x92, 0xec, 0xf0, 0x99, 0x15, 0x8e, 0x4e, 0xac, 0xb0, 0xeb, 0xf8, 0xc7, + 0xf1, 0x09, 0x76, 0x39, 0x9b, 0x77, 0xb3, 0x5d, 0x08, 0x0c, 0x52, 0xd3, 0x01, 0x7b, 0xd1, 0x23, + 0x72, 0xe9, 0x60, 0x50, 0xf5, 0x9d, 0x33, 0x99, 0xff, 0x75, 0x00, 0xec, 0x7f, 0x89, 0x96, 0xb7, + 0x77, 0x02, 0xcf, 0x66, 0xb4, 0xbe, 0x2e, 0xdb, 0x2b, 0x63, 0x7e, 0x6f, 0x3b, 0x47, 0xba, 0x27, + 0x47, 0x9e, 0x1b, 0x24, 0x3b, 0xe1, 0x37, 0x1a, 0x46, 0xf1, 0x06, 0xd4, 0x95, 0xa5, 0x82, 0x9e, + 0x3d, 0xe2, 0xcf, 0xd7, 0x14, 0xac, 0x37, 0x1d, 0xeb, 0xff, 0x51, 0x09, 0xea, 0x4d, 0xf6, 0x39, + 0x9d, 0x5c, 0xf4, 0x27, 0xb1, 0xf8, 0x3d, 0xb8, 0x42, 0xf1, 0xf6, 0x39, 0xf4, 0x01, 0xb9, 0x7a, + 0xb2, 0x93, 0x23, 0x77, 0xe2, 0xfd, 0x4c, 0x27, 0xca, 0x2c, 0x0f, 0x06, 0xa7, 0xee, 0x84, 0xa3, + 0x21, 0x74, 0xec, 0x73, 0xf2, 0x79, 0x64, 0xcf, 0x0c, 0x0a, 0xcd, 0x9f, 0x47, 0x50, 0xe8, 0x67, + 0x2c, 0x7e, 0x72, 0x2a, 0x8b, 0x95, 0x4e, 0x3e, 0x08, 0xdc, 0x3f, 0x65, 0x9a, 0xd4, 0x25, 0x6a, + 0x6e, 0x5b, 0x96, 0x2e, 0x51, 0xe9, 0xfc, 0x1e, 0xc0, 0xba, 0x7c, 0x1e, 0x80, 0x5e, 0x25, 0x34, + 0x47, 0xc1, 0xe4, 0x42, 0x1e, 0xfc, 0xbe, 0xf3, 0x92, 0xaa, 0x76, 0x98, 0x14, 0x41, 0x5c, 0xcf, + 0xb5, 0x28, 0x0f, 0x15, 0xcf, 0x40, 0x60, 0x97, 0x4e, 0xbc, 0x29, 0xee, 0x67, 0xea, 0x3d, 0x44, + 0x76, 0x45, 0xbf, 0xb7, 0xa0, 0xd4, 0x9e, 0x73, 0xb6, 0x4f, 0xb4, 0xb2, 0x10, 0x2e, 0x56, 0xf3, + 0x67, 0xc0, 0x37, 0xda, 0x70, 0xed, 0x25, 0x7d, 0xf5, 0x2a, 0xa7, 0x95, 0x4a, 0xc6, 0x69, 0xe5, + 0xc6, 0x16, 0x6c, 0x2c, 0x6a, 0xc7, 0x4f, 0x2a, 0xa3, 0x05, 0x57, 0x16, 0xd6, 0xfa, 0xa7, 0x14, + 0xa2, 0xff, 0x7e, 0x03, 0x20, 0x5d, 0x4e, 0x39, 0x09, 0xba, 0x30, 0x23, 0x41, 0xff, 0x24, 0x2f, + 0xc3, 0x4f, 0xa0, 0x81, 0xe3, 0x98, 0x09, 0xe2, 0xba, 0x38, 0x7a, 0x6c, 0x1d, 0xa9, 0x86, 0x69, + 0xf8, 0xbe, 0x79, 0x6f, 0x99, 0xd2, 0x42, 0x6f, 0x99, 0x8f, 0xa1, 0xcc, 0xa7, 0x83, 0x6a, 0x50, + 0xaf, 0xcd, 0xb2, 0x86, 0x07, 0x32, 0x68, 0x8e, 0xa2, 0x13, 0x6d, 0x68, 0x24, 0xf1, 0x2e, 0xb2, + 0xf1, 0x23, 0x6f, 0xcd, 0xe7, 0x54, 0x64, 0xfc, 0xd0, 0xa2, 0x95, 0x4d, 0x66, 0x04, 0xee, 0x78, + 0x2c, 0x4d, 0xd6, 0x24, 0x70, 0x97, 0xb3, 0x02, 0xf7, 0x70, 0xcc, 0x86, 0x6a, 0x14, 0xb8, 0x3f, + 0x80, 0xcb, 0xd2, 0xef, 0x18, 0x33, 0x60, 0x77, 0x12, 0x3d, 0xdf, 0x12, 0xd3, 0x64, 0x3c, 0xfa, + 0x31, 0xa9, 0xa3, 0x48, 0xfe, 0x35, 0x6c, 0xf0, 0x93, 0x09, 0xf4, 0x3a, 0xfd, 0x28, 0xf0, 0x3a, + 0xb6, 0x39, 0xb6, 0x26, 0x52, 0x0f, 0x78, 0x67, 0xae, 0xb2, 0xfc, 0x62, 0xc2, 0xf0, 0xd0, 0x23, + 0xbf, 0xed, 0xc4, 0xa7, 0x6a, 0x7d, 0x34, 0x0b, 0x9f, 0x71, 0x6d, 0x80, 0x39, 0xd7, 0x86, 0x59, + 0xcd, 0xa0, 0xb6, 0x40, 0x33, 0x48, 0xe5, 0xfb, 0x7a, 0x56, 0xbe, 0x17, 0xef, 0x43, 0x59, 0xc6, + 0x21, 0x94, 0xc6, 0x6a, 0x31, 0xbf, 0xc8, 0x0c, 0x45, 0x82, 0x5f, 0x52, 0x8e, 0x36, 0x14, 0xf3, + 0xba, 0xc1, 0x5f, 0xca, 0xc2, 0xc4, 0x96, 0xb4, 0xd4, 0x26, 0x3e, 0xe6, 0xd2, 0x30, 0x7d, 0x23, + 0x53, 0x70, 0x82, 0x93, 0xa6, 0x84, 0x99, 0x1c, 0x37, 0xfe, 0xb0, 0x0c, 0x2b, 0xd2, 0x5d, 0xe2, + 0x3e, 0x94, 0xec, 0x50, 0xde, 0x87, 0x49, 0x54, 0x99, 0xbc, 0x5c, 0xb9, 0x7b, 0xc9, 0x20, 0x1a, + 0xf1, 0x00, 0x56, 0x2c, 0xdb, 0x36, 0x8f, 0x4e, 0xf3, 0x87, 0xe8, 0x33, 0x32, 0xff, 0xee, 0x25, + 0x63, 0xd9, 0x22, 0xe1, 0xff, 0x73, 0xa8, 0x22, 0x7d, 0x36, 0xfa, 0xf0, 0x9c, 0x26, 0xa3, 0xa4, + 0xf3, 0xdd, 0x4b, 0x46, 0xc5, 0x52, 0x92, 0xfa, 0x6f, 0xe7, 0x8f, 0x23, 0x4a, 0x73, 0x0d, 0x9c, + 0x11, 0x2d, 0x67, 0x0e, 0x26, 0x7e, 0x07, 0xd8, 0x3e, 0x9d, 0x88, 0x13, 0xcb, 0xd9, 0xf3, 0xda, + 0x39, 0xe1, 0x63, 0xf7, 0x92, 0xc1, 0x9b, 0xaa, 0x12, 0x46, 0x3e, 0x55, 0x47, 0x05, 0xc4, 0x9e, + 0x57, 0x16, 0xf7, 0x0c, 0xf2, 0xe8, 0xe4, 0xbc, 0x80, 0x18, 0x36, 0x66, 0xb3, 0x13, 0xf7, 0xd1, + 0xf2, 0x5c, 0xb6, 0x44, 0xe4, 0xa0, 0x6c, 0x89, 0xfc, 0xf1, 0x18, 0x6a, 0x6c, 0x39, 0xe6, 0x7c, + 0x95, 0xb9, 0xae, 0x4d, 0x25, 0x06, 0x3a, 0x8b, 0x4c, 0xe5, 0x87, 0x96, 0x6a, 0x67, 0xe8, 0x64, + 0x8f, 0x7b, 0x6e, 0x2e, 0xec, 0x28, 0x23, 0x39, 0xf9, 0xe1, 0xc6, 0x1a, 0x9c, 0x47, 0x74, 0x61, + 0x43, 0x9e, 0x8b, 0xb0, 0x74, 0xa0, 0x36, 0x74, 0x98, 0x1b, 0xaf, 0x9c, 0xf8, 0xb0, 0x7b, 0xc9, + 0x10, 0xd6, 0xbc, 0x50, 0xd1, 0x82, 0x75, 0x55, 0x25, 0xda, 0xf6, 0x33, 0x1e, 0x75, 0xd9, 0x26, + 0xa5, 0x42, 0xc1, 0xee, 0x25, 0x63, 0xcd, 0xca, 0x83, 0x44, 0x07, 0x2e, 0xab, 0x42, 0xe8, 0x7c, + 0x20, 0xe3, 0x4c, 0x9f, 0x1f, 0xc5, 0xac, 0x20, 0xb1, 0x7b, 0xc9, 0x58, 0xb7, 0xe6, 0xa4, 0x8b, + 0x3d, 0x55, 0x9f, 0xac, 0xe4, 0xca, 0x2b, 0xf1, 0xf6, 0xc2, 0x6e, 0x4a, 0xc5, 0xe8, 0xa4, 0x66, + 0x19, 0xc9, 0xfa, 0x97, 0xaa, 0xb3, 0xf2, 0xce, 0xc3, 0xf2, 0x38, 0xe9, 0xf5, 0xb9, 0x12, 0xb3, + 0xbe, 0xc3, 0x49, 0x8f, 0xe5, 0xa0, 0xa9, 0x3f, 0xc7, 0x0d, 0x03, 0xae, 0x2e, 0x66, 0x5a, 0xd9, + 0x9d, 0xab, 0xc4, 0x3b, 0x97, 0x9e, 0xdd, 0xb9, 0x66, 0xc3, 0xe2, 0x67, 0xf6, 0xb1, 0x5f, 0xc0, + 0x6a, 0x8e, 0x6b, 0x8b, 0x1a, 0x94, 0xd5, 0x8b, 0xe2, 0x14, 0x6b, 0xa4, 0xd5, 0xdf, 0xff, 0x46, + 0x2b, 0x20, 0xb8, 0xd3, 0x1b, 0x0c, 0x9b, 0xbd, 0xa1, 0xb6, 0xc4, 0x89, 0xfd, 0x6e, 0xb3, 0xd5, + 0xd6, 0x8a, 0xfa, 0xdf, 0x2f, 0x42, 0x35, 0x39, 0x6d, 0xfc, 0xcd, 0x6d, 0x82, 0x8b, 0xaf, 0xc4, + 0xcf, 0x28, 0xbc, 0x7c, 0x97, 0xa0, 0xa4, 0x62, 0x60, 0x67, 0xd5, 0xca, 0x68, 0x3e, 0xc8, 0xe9, + 0xf2, 0x8f, 0x0c, 0x72, 0x9a, 0xbd, 0x0b, 0xb6, 0x92, 0xbf, 0x0b, 0x36, 0xf3, 0x00, 0x7f, 0x99, + 0xde, 0x6e, 0xce, 0x3e, 0xc0, 0x7f, 0x15, 0x56, 0xdc, 0xe8, 0x99, 0xeb, 0x9c, 0x49, 0xcf, 0x78, + 0x99, 0xca, 0x6f, 0xfa, 0xf0, 0x8a, 0x4d, 0xff, 0xc7, 0x6c, 0x20, 0x0f, 0x61, 0xe3, 0xe8, 0x34, + 0x79, 0x31, 0x3a, 0x35, 0x31, 0xd5, 0xa9, 0x4a, 0x0b, 0x71, 0xe2, 0x1d, 0x58, 0x89, 0xd5, 0x41, + 0x68, 0x71, 0xc1, 0xd9, 0xb0, 0x21, 0xd1, 0xfa, 0x1f, 0x16, 0x00, 0xd2, 0x73, 0xb8, 0xbf, 0xb0, + 0x41, 0x3b, 0x63, 0x33, 0x2c, 0xfe, 0x80, 0xcd, 0xf0, 0x55, 0x0f, 0x02, 0x7d, 0x07, 0xd5, 0xe4, + 0xe4, 0xf5, 0x37, 0x9f, 0x58, 0x3f, 0xe9, 0x93, 0xff, 0x9c, 0x32, 0xee, 0x27, 0x47, 0x97, 0x7f, + 0xd1, 0xbe, 0xc8, 0x7d, 0x7e, 0xb1, 0x2c, 0x97, 0x7e, 0xfe, 0x9c, 0x2d, 0xec, 0xc9, 0xc7, 0xff, + 0x92, 0x57, 0x53, 0x76, 0xa2, 0x97, 0x72, 0x13, 0x5d, 0x9f, 0xca, 0x63, 0x82, 0xbf, 0xf8, 0xa7, + 0x7f, 0x52, 0x83, 0xff, 0x8f, 0x82, 0xb2, 0x65, 0x27, 0x8f, 0x7c, 0xbf, 0x54, 0x8e, 0x5e, 0x6c, + 0x8e, 0xff, 0x29, 0x9f, 0xfb, 0x41, 0x4b, 0x5d, 0xe9, 0x87, 0x2c, 0x75, 0xef, 0xa8, 0x37, 0x12, + 0x96, 0x5f, 0x66, 0xa5, 0x93, 0xcf, 0x24, 0xdc, 0x86, 0x5a, 0xd6, 0x36, 0xc7, 0x46, 0x19, 0x36, + 0xaa, 0xb0, 0x59, 0x4e, 0x97, 0x7a, 0x03, 0xb7, 0x77, 0x43, 0x95, 0x2b, 0x63, 0x03, 0x51, 0x42, + 0xff, 0x6b, 0xcc, 0x51, 0x7f, 0xd3, 0x2e, 0xf9, 0x61, 0x33, 0x8d, 0xfe, 0xff, 0x16, 0x60, 0x35, + 0xe7, 0x49, 0xf1, 0x1b, 0x7c, 0x62, 0x21, 0x5f, 0x2e, 0xfe, 0xff, 0x88, 0x2f, 0xe7, 0x1c, 0xc6, + 0x2b, 0x79, 0x87, 0x71, 0x64, 0x77, 0xf5, 0x9c, 0x56, 0xb4, 0x48, 0x7f, 0x2a, 0x2c, 0xd4, 0x9f, + 0x6e, 0x01, 0x58, 0x23, 0xba, 0x87, 0xd6, 0xd9, 0x66, 0xff, 0xec, 0x55, 0x23, 0x03, 0x11, 0x5f, + 0xc0, 0x75, 0x69, 0x34, 0xe1, 0xfe, 0x09, 0x8e, 0x4c, 0x85, 0xb5, 0xa5, 0x11, 0xe2, 0x2a, 0x13, + 0xd0, 0xe8, 0xf6, 0x8f, 0x9a, 0x0a, 0xab, 0x77, 0x60, 0x35, 0xe7, 0xa2, 0x82, 0x7b, 0xcb, 0xb1, + 0x17, 0x1c, 0x5a, 0x9e, 0xac, 0x8b, 0x4c, 0x89, 0x3b, 0xb0, 0x7c, 0x76, 0xe2, 0x84, 0xce, 0x82, + 0xa7, 0x6c, 0x19, 0xa1, 0xff, 0x0c, 0xea, 0x59, 0x77, 0x39, 0xf1, 0x3e, 0x2c, 0xbb, 0xb1, 0x33, + 0x56, 0xe6, 0xa0, 0xab, 0xf3, 0x1e, 0x75, 0x9d, 0xd8, 0x19, 0x1b, 0x4c, 0xa4, 0xff, 0x51, 0x01, + 0xb4, 0x59, 0x1c, 0x85, 0xb7, 0xb9, 0x88, 0x62, 0x67, 0xac, 0x2a, 0xc3, 0xa9, 0x4c, 0x25, 0x97, + 0x72, 0x95, 0x54, 0x56, 0xb3, 0x62, 0xc6, 0x6a, 0x76, 0x47, 0x09, 0x25, 0xf3, 0x57, 0x94, 0x18, + 0x21, 0xde, 0x86, 0x4a, 0xe8, 0x50, 0xe0, 0x1c, 0x7b, 0xc1, 0xed, 0xb8, 0x04, 0xa7, 0xff, 0x41, + 0x01, 0xca, 0xd2, 0xb7, 0x6f, 0xa1, 0x7d, 0xee, 0x5d, 0x28, 0x47, 0xa3, 0x13, 0x67, 0x6c, 0xa9, + 0x77, 0x81, 0xe6, 0xfc, 0xba, 0x15, 0x5e, 0xdc, 0x62, 0x8f, 0xc7, 0xbc, 0xbd, 0x6e, 0xdf, 0xb3, + 0x7c, 0x83, 0xe0, 0x38, 0xd5, 0xd8, 0x4e, 0xcb, 0x57, 0x8d, 0xf8, 0x1d, 0x06, 0x20, 0x10, 0x5d, + 0x26, 0xd2, 0x7f, 0x1b, 0xca, 0xd2, 0x77, 0x70, 0x61, 0x55, 0x6e, 0x41, 0xc9, 0x0a, 0x8f, 0xa3, + 0x05, 0x83, 0x45, 0x70, 0xfd, 0x0e, 0x40, 0xea, 0x4c, 0xb8, 0xa8, 0x04, 0xfd, 0x3e, 0x54, 0x94, + 0xff, 0x20, 0xce, 0xbf, 0xf4, 0xd3, 0xf2, 0x72, 0x70, 0xb6, 0x32, 0x9e, 0x7c, 0x9e, 0xbe, 0x1b, + 0x8c, 0x4e, 0xe9, 0xc8, 0xe0, 0x43, 0xa0, 0x9b, 0xd2, 0xc3, 0xb9, 0x07, 0x2b, 0x12, 0x32, 0xbe, + 0x7c, 0xa0, 0x88, 0xc4, 0x7d, 0x48, 0xf8, 0xe5, 0xab, 0xac, 0x15, 0x7a, 0x53, 0xdd, 0xa9, 0xa7, + 0x59, 0xf6, 0x48, 0x5a, 0x8f, 0xbb, 0xf4, 0xf2, 0x5a, 0x21, 0xfb, 0x8c, 0x6b, 0xae, 0x4e, 0x46, + 0x86, 0x4c, 0x6f, 0x40, 0x3d, 0xeb, 0xf4, 0xa4, 0x37, 0x61, 0x7d, 0xcf, 0x89, 0x2d, 0xe4, 0x3f, + 0x2a, 0x8c, 0x3f, 0xcf, 0x5f, 0xfc, 0x91, 0x9f, 0xbf, 0xb3, 0x74, 0x06, 0x13, 0xe9, 0x7f, 0xbf, + 0x04, 0xda, 0x2c, 0xee, 0x87, 0xe2, 0x0b, 0xdc, 0x86, 0x1a, 0x3f, 0xd9, 0x93, 0xb5, 0x24, 0x02, + 0x83, 0x32, 0xb7, 0x4f, 0xf8, 0x39, 0x9b, 0xf4, 0xe1, 0xfe, 0x5d, 0x4a, 0x8b, 0x6b, 0x7c, 0x99, + 0xdc, 0x0b, 0x46, 0x34, 0xad, 0xeb, 0x74, 0x77, 0xbc, 0x1b, 0x8c, 0x28, 0x6c, 0x81, 0x34, 0x78, + 0xb0, 0x27, 0x6e, 0xdd, 0xa8, 0x48, 0x2b, 0x07, 0x9d, 0x62, 0xca, 0x3b, 0x29, 0x71, 0x24, 0x63, + 0x8b, 0x55, 0x18, 0x30, 0x8c, 0xd4, 0x23, 0xe4, 0x23, 0x3f, 0x96, 0x51, 0x73, 0x56, 0xc2, 0xe0, + 0xac, 0xe5, 0x53, 0xd4, 0x02, 0x7a, 0x02, 0x14, 0x31, 0x95, 0xf4, 0x19, 0x78, 0x44, 0x51, 0xa8, + 0x1a, 0x8e, 0xb3, 0xca, 0x0f, 0x70, 0x55, 0xe5, 0xcb, 0x6b, 0x12, 0x98, 0xbc, 0x6f, 0xc8, 0xfb, + 0x5f, 0x26, 0x1e, 0x11, 0x30, 0x88, 0x08, 0xae, 0x43, 0xe5, 0xfb, 0xc0, 0x77, 0xc8, 0x70, 0x52, + 0xa3, 0x5a, 0x95, 0x31, 0xbd, 0x67, 0x4d, 0x70, 0x23, 0xf0, 0x28, 0x8c, 0x1d, 0xdf, 0xba, 0xe4, + 0x84, 0xfe, 0xdf, 0x17, 0x60, 0x63, 0xb6, 0xaf, 0x69, 0x1a, 0xd5, 0xa1, 0xd2, 0xea, 0x77, 0xcd, + 0x5e, 0x73, 0xaf, 0xad, 0x5d, 0x12, 0x6b, 0x50, 0xeb, 0x6f, 0x7d, 0xd5, 0x6e, 0x0d, 0x19, 0x50, + 0xa0, 0x88, 0x9a, 0x03, 0x73, 0xb7, 0xb3, 0xbd, 0xdd, 0xee, 0xb1, 0x46, 0xd1, 0xdf, 0xfa, 0xca, + 0xec, 0xf6, 0x5b, 0x5a, 0x11, 0x71, 0xca, 0x1d, 0x64, 0xa0, 0x95, 0xc8, 0x59, 0x84, 0x2e, 0x05, + 0x60, 0x72, 0x99, 0xbd, 0xdd, 0x9f, 0x0f, 0xcc, 0x56, 0x6f, 0xa8, 0xad, 0x60, 0xaa, 0x77, 0xd0, + 0xed, 0x52, 0x8a, 0xdc, 0x5a, 0x5b, 0xfd, 0xbd, 0x7d, 0xa3, 0x3d, 0x18, 0x98, 0x83, 0xce, 0xaf, + 0xda, 0x5a, 0x85, 0xbe, 0x6c, 0x74, 0x9e, 0x74, 0x7a, 0x0c, 0xa8, 0x8a, 0x32, 0x14, 0xf7, 0x3a, + 0x3d, 0x8e, 0x24, 0xba, 0xd7, 0xfc, 0x5a, 0xab, 0xe1, 0x8f, 0xc1, 0xc1, 0x9e, 0x56, 0x17, 0x55, + 0x58, 0xee, 0xb6, 0x9f, 0xb5, 0xbb, 0xda, 0xaa, 0xfe, 0x4f, 0x8b, 0x4a, 0x22, 0x26, 0x7f, 0xaf, + 0x1f, 0x23, 0x05, 0x2e, 0x3a, 0x65, 0x4d, 0x3a, 0xad, 0x98, 0xe9, 0x34, 0xf1, 0x06, 0xd4, 0xe5, + 0xa6, 0x90, 0x3d, 0x27, 0xab, 0x49, 0x18, 0x4d, 0xb9, 0x37, 0x61, 0x35, 0x71, 0x91, 0xc8, 0x3c, + 0x1c, 0x5e, 0x57, 0xc0, 0x05, 0xc7, 0x35, 0x2b, 0x0b, 0x8e, 0x6b, 0x26, 0x6e, 0x8c, 0x8a, 0x3b, + 0xf2, 0x5c, 0x9e, 0x49, 0x55, 0x84, 0x3c, 0x23, 0x5e, 0xfb, 0x1a, 0x50, 0xc2, 0x9c, 0xfa, 0xf2, + 0xc9, 0xa3, 0xaa, 0x51, 0x41, 0xc0, 0x81, 0xef, 0xc6, 0xb3, 0x2e, 0x1a, 0xd5, 0x39, 0x17, 0x8d, + 0xec, 0xe6, 0x0c, 0xf9, 0xcd, 0xf9, 0xf5, 0x64, 0x8f, 0x44, 0x64, 0x8d, 0xce, 0x2a, 0xaa, 0xc9, + 0x2e, 0x28, 0xde, 0x07, 0x31, 0x9a, 0x86, 0xf4, 0x84, 0x48, 0x86, 0x8c, 0x9f, 0x2a, 0xd2, 0x24, + 0x26, 0xd9, 0x15, 0x29, 0x92, 0x4b, 0x9e, 0x9a, 0xd4, 0xf3, 0xaa, 0xd1, 0xc8, 0x93, 0x8a, 0x07, + 0x70, 0x59, 0xce, 0xed, 0x5c, 0xdf, 0xca, 0x20, 0x10, 0x8c, 0x6a, 0xa6, 0x3d, 0xac, 0xff, 0x16, + 0x54, 0x94, 0x6b, 0xdf, 0x0f, 0x0b, 0xbb, 0x0b, 0xc6, 0x55, 0xff, 0xf7, 0x96, 0xa0, 0x9a, 0x38, + 0xfa, 0xfd, 0xa8, 0xd9, 0xf1, 0x1a, 0xca, 0xa9, 0xd1, 0x69, 0x96, 0xc5, 0x54, 0x10, 0xa0, 0x46, + 0x4a, 0xde, 0x0d, 0x9c, 0x86, 0xae, 0x92, 0xd8, 0x18, 0x72, 0x10, 0xba, 0x14, 0x27, 0xdc, 0xf5, + 0x33, 0xe1, 0x1a, 0xaa, 0x46, 0x05, 0x01, 0xb4, 0xd0, 0xae, 0x03, 0xfd, 0xa6, 0x9c, 0x3c, 0x49, + 0xca, 0x98, 0xc6, 0x7c, 0x57, 0x13, 0xfd, 0x4f, 0x86, 0x3a, 0x8b, 0x13, 0xc1, 0x42, 0xfa, 0x18, + 0xb1, 0x67, 0x85, 0x4c, 0xe1, 0x77, 0x28, 0x40, 0x10, 0xd5, 0x51, 0xce, 0x08, 0x04, 0xa8, 0x3a, + 0x66, 0x86, 0xab, 0x3a, 0x3b, 0xaa, 0xb3, 0x73, 0x1a, 0xe6, 0xe6, 0xb4, 0x1e, 0x43, 0x59, 0x3a, + 0x3b, 0xfe, 0x70, 0x87, 0xff, 0x60, 0x57, 0x69, 0x50, 0xb4, 0x3c, 0x75, 0xfb, 0x1e, 0x7f, 0xce, + 0x54, 0xac, 0x34, 0x53, 0x31, 0xfd, 0xdf, 0x5c, 0x02, 0x48, 0x9d, 0x26, 0xc5, 0x07, 0x33, 0x0e, + 0xda, 0x85, 0xb9, 0x6d, 0x7f, 0xc6, 0x2f, 0x7b, 0x26, 0x70, 0xfe, 0xd2, 0x8f, 0x08, 0x9c, 0xff, + 0x10, 0x56, 0xa3, 0x70, 0xf4, 0x4a, 0x1b, 0x7e, 0x2d, 0x0a, 0x47, 0x89, 0x09, 0xff, 0x43, 0xc0, + 0x24, 0x3d, 0xaa, 0x93, 0x2a, 0xaa, 0x73, 0x52, 0x4b, 0x35, 0x0a, 0x47, 0xfd, 0xc3, 0x6f, 0xb7, + 0xf9, 0x42, 0xa6, 0x1d, 0xc5, 0xe6, 0x22, 0x2e, 0xb1, 0x66, 0x47, 0xf1, 0x76, 0x96, 0x51, 0xdc, + 0x85, 0x06, 0xd2, 0xce, 0x31, 0x8b, 0xba, 0x1d, 0xa5, 0x07, 0x4a, 0xfa, 0xbf, 0xa4, 0x0e, 0xe6, + 0x67, 0xcc, 0xc3, 0xe2, 0x33, 0xa9, 0x88, 0x67, 0x84, 0x88, 0xcd, 0x45, 0xd6, 0x64, 0xbe, 0xb3, + 0x9d, 0x90, 0x8a, 0xc7, 0xb0, 0x9a, 0xe0, 0xb6, 0x9d, 0x23, 0x25, 0x03, 0xa9, 0x17, 0x5a, 0x32, + 0x28, 0x23, 0x4f, 0x88, 0x42, 0x51, 0xfa, 0xac, 0x11, 0xae, 0xc0, 0xe4, 0xd2, 0x52, 0x55, 0x5e, + 0x47, 0x7a, 0x0c, 0xd7, 0x5e, 0x62, 0x47, 0x53, 0xe7, 0x92, 0x32, 0x0e, 0x83, 0x0c, 0xea, 0xe6, + 0x3b, 0x67, 0x1c, 0x87, 0x41, 0xf7, 0xe1, 0xf2, 0x82, 0xf7, 0xc8, 0xc5, 0x1d, 0x72, 0xd9, 0x4a, + 0xdf, 0x5f, 0x97, 0xb2, 0xd5, 0x28, 0x7d, 0x74, 0xfd, 0x53, 0x58, 0x73, 0x3c, 0xf7, 0xd8, 0x3d, + 0x74, 0x29, 0xd6, 0xf8, 0x28, 0xf0, 0x16, 0xbd, 0xce, 0x6f, 0x34, 0x32, 0x44, 0xad, 0xc0, 0xd3, + 0xff, 0x95, 0x42, 0xee, 0x71, 0x41, 0xf5, 0xbc, 0x18, 0x3f, 0x2e, 0x28, 0x5f, 0x31, 0x2e, 0x18, + 0xf4, 0x1b, 0x57, 0xa6, 0x7c, 0xb8, 0x56, 0x3e, 0x16, 0xc6, 0x29, 0xf1, 0x21, 0x6c, 0xc8, 0x78, + 0xe9, 0x14, 0xad, 0xcc, 0x9c, 0x38, 0xa1, 0x19, 0x06, 0x67, 0x34, 0xb1, 0x0a, 0x86, 0x8c, 0xa5, + 0x4e, 0x41, 0xcb, 0xf6, 0x9d, 0xd0, 0x08, 0xce, 0xc4, 0x26, 0x49, 0x25, 0xce, 0x28, 0x56, 0x67, + 0xcc, 0x2a, 0xa9, 0xff, 0x2e, 0x5c, 0x5e, 0x70, 0x2d, 0x50, 0xbc, 0xa5, 0xf4, 0xbc, 0x97, 0x5c, + 0x02, 0x5e, 0xa8, 0x5b, 0x2e, 0xcd, 0xea, 0x96, 0x7f, 0x5c, 0x80, 0x9a, 0x7a, 0x96, 0xcf, 0xe0, + 0x40, 0x81, 0xea, 0xf5, 0xbe, 0x34, 0xd2, 0x12, 0x28, 0x50, 0xc7, 0x46, 0xd5, 0x33, 0x74, 0x5e, + 0xb8, 0x91, 0xf2, 0xb6, 0x2c, 0x19, 0x49, 0x5a, 0xbc, 0x07, 0xeb, 0x49, 0x68, 0xc2, 0x99, 0xb8, + 0x7a, 0x5a, 0x82, 0x50, 0x21, 0xd8, 0xe6, 0xb9, 0x40, 0x29, 0xcb, 0x9e, 0x66, 0xf6, 0xb3, 0xe5, + 0xd9, 0xfd, 0x4c, 0xff, 0x37, 0x0a, 0xb0, 0x39, 0xf8, 0xce, 0x93, 0x57, 0x1c, 0x3b, 0xe3, 0x89, + 0x47, 0x93, 0x89, 0x83, 0xc3, 0x7c, 0x0a, 0x57, 0x53, 0x77, 0x52, 0xf3, 0xc8, 0xf5, 0x8f, 0x9d, + 0x70, 0x12, 0xba, 0xd2, 0x11, 0xa1, 0x6e, 0x5c, 0x49, 0xb1, 0x3b, 0x29, 0x52, 0x3c, 0x05, 0x3d, + 0x72, 0xc6, 0x96, 0x1f, 0xbb, 0x23, 0x33, 0x93, 0x9f, 0x35, 0x8f, 0xa4, 0x45, 0x3c, 0xd2, 0xb7, + 0x15, 0x65, 0x7a, 0x75, 0x66, 0x40, 0x74, 0xb2, 0x81, 0xfa, 0x7f, 0x56, 0x84, 0xd7, 0xf6, 0x2f, + 0xe2, 0x93, 0xc0, 0x5f, 0x5c, 0xc7, 0x4d, 0x28, 0x9f, 0x58, 0xbe, 0xed, 0x25, 0x01, 0x48, 0x55, + 0x52, 0xdc, 0x80, 0x15, 0xde, 0x4b, 0x78, 0xbc, 0xb6, 0x96, 0x36, 0x0b, 0x86, 0x84, 0x10, 0xdb, + 0x3e, 0x74, 0x4d, 0xba, 0xe7, 0x63, 0x8d, 0x62, 0xb9, 0xf7, 0xd4, 0xac, 0x43, 0xb7, 0x25, 0x41, + 0xb8, 0x03, 0x53, 0x24, 0x79, 0x27, 0x4c, 0xaa, 0x2c, 0x1d, 0x7b, 0x24, 0x58, 0x0d, 0x01, 0x12, + 0x86, 0xb1, 0x7b, 0x64, 0x8d, 0x62, 0x15, 0x5d, 0x6e, 0x59, 0x12, 0x4a, 0xb0, 0x0c, 0x2e, 0xf7, + 0x01, 0x08, 0xc7, 0x7f, 0xe1, 0x86, 0x81, 0x4f, 0x91, 0x35, 0x24, 0x2d, 0xb3, 0xa4, 0xf5, 0x0c, + 0x46, 0x92, 0xdf, 0x86, 0x5a, 0x64, 0x9f, 0x26, 0x1f, 0x97, 0x91, 0x76, 0x23, 0xfb, 0x54, 0x7d, + 0xf8, 0x4b, 0xb8, 0xfe, 0xf2, 0xee, 0xe5, 0x28, 0x41, 0xd7, 0xec, 0xc5, 0xdd, 0x9a, 0xf0, 0x96, + 0x6a, 0xca, 0x5b, 0xc8, 0xd9, 0x84, 0x5e, 0xda, 0x0f, 0x3c, 0x77, 0x74, 0x21, 0xb7, 0x32, 0x40, + 0xd0, 0x3e, 0x41, 0x7e, 0x60, 0x3e, 0xb0, 0xfb, 0xe0, 0xe2, 0xf9, 0xa0, 0xff, 0x6f, 0xcb, 0x50, + 0x93, 0x83, 0xd7, 0xc2, 0x9d, 0x8b, 0xa3, 0x1f, 0x51, 0x2f, 0x27, 0xd5, 0xe5, 0xa0, 0x20, 0x6b, + 0x0a, 0xae, 0xaa, 0xf9, 0x09, 0xd4, 0x93, 0x85, 0x94, 0x46, 0x61, 0x50, 0x91, 0x71, 0xd3, 0x15, + 0x67, 0x24, 0xeb, 0x0d, 0x97, 0xdf, 0x0d, 0xa8, 0x78, 0x96, 0x7f, 0x3c, 0xb5, 0x8e, 0x13, 0xc7, + 0x4e, 0x95, 0x16, 0x1f, 0x43, 0xc3, 0x0a, 0x8f, 0xa7, 0x34, 0x02, 0xa9, 0x6a, 0x9b, 0x8f, 0xbf, + 0xb1, 0xaa, 0x28, 0x38, 0x6c, 0xc6, 0xc7, 0x50, 0xe3, 0xbb, 0xcb, 0x2c, 0x89, 0x2c, 0xbf, 0xc4, + 0xc3, 0x05, 0x98, 0x88, 0xb6, 0x80, 0x5b, 0x00, 0x2f, 0x02, 0xcf, 0x8a, 0x89, 0x1b, 0xca, 0x21, + 0xce, 0x40, 0x66, 0xbb, 0xba, 0x3c, 0xd7, 0xd5, 0x0f, 0xd9, 0xa3, 0x99, 0x4f, 0xbd, 0xe4, 0x91, + 0xf3, 0xcb, 0xd6, 0xe9, 0xee, 0x25, 0xf2, 0x79, 0x16, 0xbf, 0x05, 0x2b, 0x13, 0x5a, 0x29, 0xf2, + 0xc0, 0xeb, 0x0d, 0xb9, 0xe1, 0xbc, 0x7c, 0xf5, 0xec, 0x5e, 0x32, 0x64, 0x16, 0xf1, 0x33, 0xbe, + 0xf5, 0xe6, 0x9c, 0xc7, 0x32, 0xe6, 0xf2, 0xad, 0xdc, 0xe5, 0x67, 0x1c, 0xb8, 0x07, 0x2d, 0x26, + 0xa0, 0xc3, 0x17, 0x5a, 0x4e, 0x2a, 0x0b, 0x39, 0xcd, 0x58, 0x9e, 0x17, 0xb9, 0xb1, 0xa3, 0x84, + 0xdf, 0xaa, 0x01, 0x0a, 0xd4, 0xa1, 0xa8, 0xd0, 0x63, 0xeb, 0xc2, 0x74, 0xc2, 0x30, 0x08, 0x65, + 0x8c, 0x90, 0xca, 0xd8, 0xba, 0x68, 0x63, 0x1a, 0xa5, 0xfe, 0xc8, 0x19, 0x4d, 0x43, 0xdc, 0x5e, + 0x68, 0x56, 0xb2, 0xa8, 0x5b, 0x57, 0x40, 0xba, 0x76, 0x7b, 0x13, 0xaa, 0x9e, 0x63, 0x9d, 0x4e, + 0xc2, 0x20, 0x38, 0x92, 0xe2, 0x6d, 0x0a, 0x10, 0x8f, 0xe0, 0x4a, 0xca, 0x34, 0xb3, 0x33, 0x93, + 0xfd, 0x4a, 0x37, 0x12, 0x64, 0x66, 0x62, 0xde, 0xf8, 0x12, 0xea, 0xd9, 0x26, 0xbd, 0xca, 0x13, + 0xa2, 0x9a, 0x39, 0x41, 0xda, 0xd2, 0xa0, 0xe1, 0xe6, 0xfa, 0x52, 0xff, 0x67, 0x45, 0xb8, 0xb2, + 0xf0, 0xaa, 0xf8, 0xdc, 0x2c, 0x2e, 0xfc, 0xe4, 0x59, 0xbc, 0x34, 0x33, 0x8b, 0x17, 0x2d, 0xa1, + 0xe2, 0xe2, 0x25, 0xf4, 0xf2, 0x45, 0x5b, 0xfa, 0x81, 0x45, 0xfb, 0x57, 0xc6, 0xd5, 0xf2, 0x2b, + 0xa3, 0xfc, 0xaa, 0x95, 0x51, 0x99, 0x5b, 0x19, 0xb9, 0x99, 0x54, 0x7d, 0xd5, 0x4c, 0x82, 0x57, + 0xcd, 0xa4, 0xda, 0x8f, 0x9e, 0x49, 0xf5, 0x97, 0xcf, 0xa4, 0xfb, 0xff, 0x7a, 0x01, 0xd6, 0x07, + 0x71, 0xe8, 0xfa, 0xc7, 0x5d, 0x37, 0x76, 0x42, 0xcb, 0xdb, 0x09, 0xc2, 0x31, 0xdd, 0xd4, 0x19, + 0x1a, 0x9d, 0xde, 0x13, 0xb3, 0xdb, 0x19, 0xb6, 0x8d, 0x66, 0xf2, 0xea, 0xc0, 0x3c, 0x62, 0xd8, + 0xfe, 0x7a, 0xa8, 0x15, 0xc4, 0x5d, 0xb8, 0x33, 0x83, 0xd8, 0xea, 0xf4, 0x9a, 0xc6, 0x37, 0x66, + 0xa7, 0x37, 0x34, 0xfa, 0xdb, 0x07, 0xad, 0xb6, 0xa1, 0x2d, 0x89, 0xab, 0x20, 0x66, 0xa8, 0x76, + 0xdb, 0x5f, 0x6b, 0xc5, 0x05, 0xf0, 0xad, 0xce, 0x50, 0x2b, 0xdd, 0xdf, 0x83, 0xcb, 0xcd, 0xe3, + 0xe3, 0xd0, 0x39, 0x46, 0xc5, 0x8d, 0x22, 0x5c, 0xab, 0xeb, 0x52, 0xcd, 0x27, 0x4f, 0xcc, 0x56, + 0xbf, 0xb7, 0xd3, 0x79, 0xa2, 0xaa, 0xf6, 0x06, 0xbc, 0x9e, 0x01, 0x3e, 0x31, 0xfa, 0x07, 0xfb, + 0x98, 0x68, 0x35, 0x87, 0x66, 0xdf, 0xd8, 0x6e, 0x1b, 0x5a, 0xe1, 0xfe, 0x1b, 0xb8, 0x6c, 0xd8, + 0xbc, 0x92, 0x3c, 0xd2, 0x10, 0xf8, 0x8e, 0x76, 0x49, 0x94, 0xa1, 0xd8, 0xfd, 0xfe, 0x13, 0xad, + 0x70, 0x5f, 0x87, 0xda, 0xe0, 0x64, 0x7a, 0x74, 0xe4, 0x39, 0x8a, 0x62, 0xd7, 0x8a, 0x4e, 0xd8, + 0x85, 0x9a, 0x9e, 0x04, 0xd6, 0x0a, 0xf7, 0xdf, 0x86, 0x55, 0x49, 0xb3, 0xe7, 0xc4, 0x27, 0x81, + 0x2d, 0x00, 0x56, 0x7a, 0x41, 0x38, 0xb6, 0x3c, 0x49, 0xe7, 0x4c, 0x23, 0xa4, 0xfb, 0x10, 0xae, + 0x64, 0xca, 0xda, 0x09, 0x42, 0x8a, 0xb4, 0xd7, 0xea, 0x51, 0x38, 0x05, 0x5a, 0x83, 0x1c, 0x18, + 0x60, 0xf7, 0xe2, 0x30, 0x74, 0x6d, 0xad, 0x70, 0xff, 0x31, 0x54, 0xd3, 0x57, 0xc7, 0xe9, 0x79, + 0x93, 0xad, 0xfe, 0x41, 0x6f, 0x9b, 0xde, 0x4f, 0xa0, 0x27, 0x4d, 0x5a, 0xdd, 0x83, 0x41, 0xe7, + 0x99, 0xb4, 0xc7, 0xb4, 0xbf, 0x56, 0xc9, 0xa5, 0xfb, 0x7f, 0x50, 0x50, 0xc1, 0x39, 0x55, 0xb5, + 0xbb, 0xfd, 0xe6, 0x36, 0x1b, 0x72, 0x92, 0x97, 0x5b, 0x86, 0x5b, 0x5a, 0x01, 0x01, 0x46, 0x7b, + 0x70, 0xd0, 0x1d, 0xaa, 0x47, 0x61, 0x1a, 0x00, 0x9d, 0x56, 0x7b, 0xab, 0x6d, 0x3c, 0x41, 0x82, + 0x22, 0xa6, 0xf7, 0xfa, 0xbd, 0x27, 0xfd, 0xed, 0x2d, 0x4c, 0xd3, 0x73, 0x30, 0xdb, 0xcd, 0x61, + 0x73, 0x30, 0x34, 0xda, 0xcd, 0x3d, 0x04, 0xd1, 0x8d, 0x65, 0xe5, 0x29, 0x3e, 0xdc, 0x62, 0xa3, + 0xce, 0xd3, 0xe6, 0xce, 0xd3, 0x26, 0xa6, 0xca, 0xf7, 0xff, 0xdb, 0x25, 0xd0, 0x66, 0x03, 0xb0, + 0x8a, 0xd7, 0xe0, 0x1a, 0x95, 0x6a, 0xee, 0x1b, 0xed, 0xed, 0x4e, 0x8b, 0xef, 0x9e, 0x3d, 0x6b, + 0x76, 0x3b, 0xdb, 0x3c, 0xab, 0x66, 0x91, 0xcd, 0xde, 0x36, 0x3f, 0x0c, 0x31, 0x8b, 0x68, 0xff, + 0xf2, 0xa0, 0xd9, 0xd5, 0x96, 0xc4, 0xeb, 0x70, 0x7d, 0x16, 0xd5, 0xeb, 0x0f, 0x25, 0xba, 0x28, + 0x36, 0x61, 0x63, 0x16, 0xdd, 0x6d, 0x0f, 0x06, 0x5a, 0x49, 0xdc, 0x82, 0x1b, 0x8b, 0x30, 0x32, + 0xe7, 0xf2, 0xa2, 0x9a, 0x3e, 0x21, 0xeb, 0x96, 0xa1, 0xad, 0xe0, 0x24, 0x7b, 0x09, 0x52, 0xe6, + 0x2f, 0xe3, 0x5c, 0x9e, 0x6f, 0xa9, 0x56, 0x59, 0xd8, 0x03, 0x03, 0x93, 0x9e, 0x01, 0xa9, 0x8a, + 0xdb, 0xf0, 0xda, 0x22, 0x64, 0x7f, 0xc8, 0x04, 0x70, 0xff, 0x1f, 0x15, 0x60, 0xf3, 0x65, 0x31, + 0xba, 0x84, 0x0e, 0xb7, 0x8c, 0x83, 0x1e, 0x3d, 0xea, 0xc2, 0xef, 0xcf, 0x98, 0x4f, 0xdb, 0xdf, + 0xcc, 0xbc, 0xbf, 0xf1, 0x3a, 0x5c, 0x5f, 0x40, 0x63, 0x34, 0x9f, 0x9b, 0xcf, 0x3e, 0xd6, 0x0a, + 0xe2, 0x3d, 0x78, 0x67, 0x01, 0x7a, 0xa7, 0xdb, 0x6f, 0x0e, 0xcd, 0x5f, 0xb5, 0x8d, 0xbe, 0xd9, + 0xea, 0xf6, 0x07, 0xed, 0x6d, 0x24, 0x5e, 0x12, 0x77, 0xe0, 0xe6, 0x02, 0xe2, 0x01, 0x3f, 0x19, + 0xf4, 0xec, 0x63, 0xad, 0x28, 0xde, 0x82, 0x37, 0x5e, 0x4e, 0xb1, 0x73, 0xd0, 0x25, 0xb2, 0xd2, + 0xfd, 0x5f, 0xc0, 0xe6, 0xcb, 0x02, 0x3b, 0xe0, 0x42, 0x6a, 0xed, 0x36, 0x29, 0x78, 0x46, 0x1d, + 0x2a, 0xbd, 0xbe, 0xc9, 0x29, 0x72, 0x6d, 0x30, 0xda, 0xdd, 0x36, 0xdd, 0x7e, 0xbc, 0xff, 0xeb, + 0x42, 0xc6, 0x80, 0xae, 0x2e, 0xe7, 0x27, 0x00, 0xb9, 0xba, 0xb3, 0x20, 0xc3, 0xb1, 0x6c, 0xad, + 0x80, 0xa3, 0x94, 0x03, 0x75, 0x83, 0x91, 0xe5, 0x69, 0x4b, 0x74, 0xcf, 0x51, 0xc1, 0x29, 0x54, + 0x8e, 0x56, 0xc4, 0xae, 0x4b, 0x60, 0xdd, 0xe0, 0x6c, 0x3f, 0x74, 0x03, 0x64, 0xc9, 0x8c, 0x2e, + 0xdd, 0xff, 0xe7, 0xa5, 0x37, 0x6e, 0x4e, 0xad, 0xc6, 0x0f, 0x34, 0x6d, 0x3b, 0x85, 0x91, 0x25, + 0x87, 0xe7, 0x3a, 0x99, 0xb1, 0x66, 0x10, 0x05, 0x9c, 0x1f, 0xea, 0x94, 0x6f, 0x16, 0xb9, 0x84, + 0x48, 0xc3, 0xa1, 0xfd, 0x6e, 0x0e, 0x59, 0xdc, 0x7a, 0xfa, 0x0f, 0xff, 0xec, 0x56, 0xe1, 0x4f, + 0xfe, 0xec, 0x56, 0xe1, 0x7f, 0xf9, 0xb3, 0x5b, 0x97, 0xfe, 0xfa, 0x9f, 0xdf, 0x2a, 0xfc, 0xd1, + 0x9f, 0xdf, 0x2a, 0xfc, 0xc9, 0x9f, 0xdf, 0x2a, 0xfc, 0x8f, 0x7f, 0x7e, 0xab, 0xf0, 0xab, 0x0f, + 0x8e, 0xdd, 0xf8, 0x64, 0x7a, 0xf8, 0x60, 0x14, 0x8c, 0x3f, 0x1c, 0x5b, 0x71, 0xe8, 0x9e, 0xb3, + 0x6d, 0x4d, 0x25, 0x7c, 0xe7, 0xc3, 0xc9, 0xe9, 0xf1, 0x87, 0x93, 0xc3, 0x0f, 0x71, 0x57, 0x3f, + 0x5c, 0x99, 0x84, 0x41, 0x1c, 0x3c, 0xfa, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x9e, 0xe4, 0x62, + 0x46, 0xb0, 0xbc, 0x00, 0x00, } func (m *Type) Marshal() (dAtA []byte, err error) { @@ -18917,6 +19602,18 @@ func (m *Function) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if m.RoutineCall != nil { + { + size, err := m.RoutineCall.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPlan(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } if m.SyntaxExplicitCast { i-- if m.SyntaxExplicitCast { @@ -20185,20 +20882,20 @@ func (m *PrimaryKeyDef) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x10 } if len(m.Cols) > 0 { - dAtA35 := make([]byte, len(m.Cols)*10) - var j34 int + dAtA36 := make([]byte, len(m.Cols)*10) + var j35 int for _, num := range m.Cols { for num >= 1<<7 { - dAtA35[j34] = uint8(uint64(num)&0x7f | 0x80) + dAtA36[j35] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j34++ + j35++ } - dAtA35[j34] = uint8(num) - j34++ + dAtA36[j35] = uint8(num) + j35++ } - i -= j34 - copy(dAtA[i:], dAtA35[:j34]) - i = encodeVarintPlan(dAtA, i, uint64(j34)) + i -= j35 + copy(dAtA[i:], dAtA36[:j35]) + i = encodeVarintPlan(dAtA, i, uint64(j35)) i-- dAtA[i] = 0xa } @@ -20393,20 +21090,20 @@ func (m *ForeignKeyDef) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x28 } if len(m.ForeignCols) > 0 { - dAtA38 := make([]byte, len(m.ForeignCols)*10) - var j37 int + dAtA39 := make([]byte, len(m.ForeignCols)*10) + var j38 int for _, num := range m.ForeignCols { for num >= 1<<7 { - dAtA38[j37] = uint8(uint64(num)&0x7f | 0x80) + dAtA39[j38] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j37++ + j38++ } - dAtA38[j37] = uint8(num) - j37++ + dAtA39[j38] = uint8(num) + j38++ } - i -= j37 - copy(dAtA[i:], dAtA38[:j37]) - i = encodeVarintPlan(dAtA, i, uint64(j37)) + i -= j38 + copy(dAtA[i:], dAtA39[:j38]) + i = encodeVarintPlan(dAtA, i, uint64(j38)) i-- dAtA[i] = 0x22 } @@ -20416,20 +21113,20 @@ func (m *ForeignKeyDef) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x18 } if len(m.Cols) > 0 { - dAtA40 := make([]byte, len(m.Cols)*10) - var j39 int + dAtA41 := make([]byte, len(m.Cols)*10) + var j40 int for _, num := range m.Cols { for num >= 1<<7 { - dAtA40[j39] = uint8(uint64(num)&0x7f | 0x80) + dAtA41[j40] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j39++ + j40++ } - dAtA40[j39] = uint8(num) - j39++ + dAtA41[j40] = uint8(num) + j40++ } - i -= j39 - copy(dAtA[i:], dAtA40[:j39]) - i = encodeVarintPlan(dAtA, i, uint64(j39)) + i -= j40 + copy(dAtA[i:], dAtA41[:j40]) + i = encodeVarintPlan(dAtA, i, uint64(j40)) i-- dAtA[i] = 0x12 } @@ -21021,20 +21718,20 @@ func (m *TableDef) MarshalToSizedBuffer(dAtA []byte) (int, error) { } } if len(m.RefChildTbls) > 0 { - dAtA48 := make([]byte, len(m.RefChildTbls)*10) - var j47 int + dAtA49 := make([]byte, len(m.RefChildTbls)*10) + var j48 int for _, num := range m.RefChildTbls { for num >= 1<<7 { - dAtA48[j47] = uint8(uint64(num)&0x7f | 0x80) + dAtA49[j48] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j47++ + j48++ } - dAtA48[j47] = uint8(num) - j47++ + dAtA49[j48] = uint8(num) + j48++ } - i -= j47 - copy(dAtA[i:], dAtA48[:j47]) - i = encodeVarintPlan(dAtA, i, uint64(j47)) + i -= j48 + copy(dAtA[i:], dAtA49[:j48]) + i = encodeVarintPlan(dAtA, i, uint64(j48)) i-- dAtA[i] = 0x72 } @@ -21306,9 +22003,9 @@ func (m *HashMapStats) MarshalToSizedBuffer(dAtA []byte) (int, error) { } if len(m.Ranges) > 0 { for iNdEx := len(m.Ranges) - 1; iNdEx >= 0; iNdEx-- { - f54 := math.Float64bits(float64(m.Ranges[iNdEx])) + f55 := math.Float64bits(float64(m.Ranges[iNdEx])) i -= 8 - encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(f54)) + encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(f55)) } i = encodeVarintPlan(dAtA, i, uint64(len(m.Ranges)*8)) i-- @@ -22018,21 +22715,21 @@ func (m *DedupJoinCtx) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x48 } if len(m.UpdateCheckColIdxList) > 0 { - dAtA67 := make([]byte, len(m.UpdateCheckColIdxList)*10) - var j66 int + dAtA68 := make([]byte, len(m.UpdateCheckColIdxList)*10) + var j67 int for _, num1 := range m.UpdateCheckColIdxList { num := uint64(num1) for num >= 1<<7 { - dAtA67[j66] = uint8(uint64(num)&0x7f | 0x80) + dAtA68[j67] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j66++ + j67++ } - dAtA67[j66] = uint8(num) - j66++ + dAtA68[j67] = uint8(num) + j67++ } - i -= j66 - copy(dAtA[i:], dAtA67[:j66]) - i = encodeVarintPlan(dAtA, i, uint64(j66)) + i -= j67 + copy(dAtA[i:], dAtA68[:j67]) + i = encodeVarintPlan(dAtA, i, uint64(j67)) i-- dAtA[i] = 0x42 } @@ -22099,21 +22796,21 @@ func (m *DedupJoinCtx) MarshalToSizedBuffer(dAtA []byte) (int, error) { } } if len(m.UpdateColIdxList) > 0 { - dAtA71 := make([]byte, len(m.UpdateColIdxList)*10) - var j70 int + dAtA72 := make([]byte, len(m.UpdateColIdxList)*10) + var j71 int for _, num1 := range m.UpdateColIdxList { num := uint64(num1) for num >= 1<<7 { - dAtA71[j70] = uint8(uint64(num)&0x7f | 0x80) + dAtA72[j71] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j70++ + j71++ } - dAtA71[j70] = uint8(num) - j70++ + dAtA72[j71] = uint8(num) + j71++ } - i -= j70 - copy(dAtA[i:], dAtA71[:j70]) - i = encodeVarintPlan(dAtA, i, uint64(j70)) + i -= j71 + copy(dAtA[i:], dAtA72[:j71]) + i = encodeVarintPlan(dAtA, i, uint64(j71)) i-- dAtA[i] = 0x12 } @@ -22654,40 +23351,40 @@ func (m *AnalyzeInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x80 } if len(m.TimeConsumedArrayMinor) > 0 { - dAtA80 := make([]byte, len(m.TimeConsumedArrayMinor)*10) - var j79 int + dAtA81 := make([]byte, len(m.TimeConsumedArrayMinor)*10) + var j80 int for _, num1 := range m.TimeConsumedArrayMinor { num := uint64(num1) for num >= 1<<7 { - dAtA80[j79] = uint8(uint64(num)&0x7f | 0x80) + dAtA81[j80] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j79++ + j80++ } - dAtA80[j79] = uint8(num) - j79++ + dAtA81[j80] = uint8(num) + j80++ } - i -= j79 - copy(dAtA[i:], dAtA80[:j79]) - i = encodeVarintPlan(dAtA, i, uint64(j79)) + i -= j80 + copy(dAtA[i:], dAtA81[:j80]) + i = encodeVarintPlan(dAtA, i, uint64(j80)) i-- dAtA[i] = 0x7a } if len(m.TimeConsumedArrayMajor) > 0 { - dAtA82 := make([]byte, len(m.TimeConsumedArrayMajor)*10) - var j81 int + dAtA83 := make([]byte, len(m.TimeConsumedArrayMajor)*10) + var j82 int for _, num1 := range m.TimeConsumedArrayMajor { num := uint64(num1) for num >= 1<<7 { - dAtA82[j81] = uint8(uint64(num)&0x7f | 0x80) + dAtA83[j82] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j81++ + j82++ } - dAtA82[j81] = uint8(num) - j81++ + dAtA83[j82] = uint8(num) + j82++ } - i -= j81 - copy(dAtA[i:], dAtA82[:j81]) - i = encodeVarintPlan(dAtA, i, uint64(j81)) + i -= j82 + copy(dAtA[i:], dAtA83[:j82]) + i = encodeVarintPlan(dAtA, i, uint64(j82)) i-- dAtA[i] = 0x72 } @@ -23406,21 +24103,21 @@ func (m *Node) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0xf8 } if len(m.GroupByHashKey) > 0 { - dAtA103 := make([]byte, len(m.GroupByHashKey)*10) - var j102 int + dAtA104 := make([]byte, len(m.GroupByHashKey)*10) + var j103 int for _, num1 := range m.GroupByHashKey { 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] = 0x4 i-- @@ -23453,21 +24150,21 @@ func (m *Node) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0xd8 } if len(m.TimeWindowPartitionColPos) > 0 { - dAtA105 := make([]byte, len(m.TimeWindowPartitionColPos)*10) - var j104 int + dAtA106 := make([]byte, len(m.TimeWindowPartitionColPos)*10) + var j105 int for _, num1 := range m.TimeWindowPartitionColPos { num := uint64(num1) for num >= 1<<7 { - dAtA105[j104] = uint8(uint64(num)&0x7f | 0x80) + dAtA106[j105] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j104++ + j105++ } - dAtA105[j104] = uint8(num) - j104++ + dAtA106[j105] = uint8(num) + j105++ } - i -= j104 - copy(dAtA[i:], dAtA105[:j104]) - i = encodeVarintPlan(dAtA, i, uint64(j104)) + i -= j105 + copy(dAtA[i:], dAtA106[:j105]) + i = encodeVarintPlan(dAtA, i, uint64(j105)) i-- dAtA[i] = 0x4 i-- @@ -24019,21 +24716,21 @@ func (m *Node) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0xe2 } if len(m.SourceStep) > 0 { - dAtA123 := make([]byte, len(m.SourceStep)*10) - var j122 int + dAtA124 := make([]byte, len(m.SourceStep)*10) + var j123 int for _, num1 := range m.SourceStep { num := uint64(num1) for num >= 1<<7 { - dAtA123[j122] = uint8(uint64(num)&0x7f | 0x80) + dAtA124[j123] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j122++ + j123++ } - dAtA123[j122] = uint8(num) - j122++ + dAtA124[j123] = uint8(num) + j123++ } - i -= j122 - copy(dAtA[i:], dAtA123[:j122]) - i = encodeVarintPlan(dAtA, i, uint64(j122)) + i -= j123 + copy(dAtA[i:], dAtA124[:j123]) + i = encodeVarintPlan(dAtA, i, uint64(j123)) i-- dAtA[i] = 0x1 i-- @@ -24070,21 +24767,21 @@ func (m *Node) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0xca } if len(m.BindingTags) > 0 { - dAtA126 := make([]byte, len(m.BindingTags)*10) - var j125 int + dAtA127 := make([]byte, len(m.BindingTags)*10) + var j126 int for _, num1 := range m.BindingTags { num := uint64(num1) for num >= 1<<7 { - dAtA126[j125] = uint8(uint64(num)&0x7f | 0x80) + dAtA127[j126] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j125++ + j126++ } - dAtA126[j125] = uint8(num) - j125++ + dAtA127[j126] = uint8(num) + j126++ } - i -= j125 - copy(dAtA[i:], dAtA126[:j125]) - i = encodeVarintPlan(dAtA, i, uint64(j125)) + i -= j126 + copy(dAtA[i:], dAtA127[:j126]) + i = encodeVarintPlan(dAtA, i, uint64(j126)) i-- dAtA[i] = 0x1 i-- @@ -24334,21 +25031,21 @@ func (m *Node) MarshalToSizedBuffer(dAtA []byte) (int, error) { } } if len(m.Children) > 0 { - dAtA136 := make([]byte, len(m.Children)*10) - var j135 int + dAtA137 := make([]byte, len(m.Children)*10) + var j136 int for _, num1 := range m.Children { num := uint64(num1) for num >= 1<<7 { - dAtA136[j135] = uint8(uint64(num)&0x7f | 0x80) + dAtA137[j136] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j135++ + j136++ } - dAtA136[j135] = uint8(num) - j135++ + dAtA137[j136] = uint8(num) + j136++ } - i -= j135 - copy(dAtA[i:], dAtA136[:j135]) - i = encodeVarintPlan(dAtA, i, uint64(j135)) + i -= j136 + copy(dAtA[i:], dAtA137[:j136]) + i = encodeVarintPlan(dAtA, i, uint64(j136)) i-- dAtA[i] = 0x22 } @@ -24948,21 +25645,21 @@ func (m *IcebergScan) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x52 } if len(m.ProjectedFieldIds) > 0 { - dAtA147 := make([]byte, len(m.ProjectedFieldIds)*10) - var j146 int + dAtA148 := make([]byte, len(m.ProjectedFieldIds)*10) + var j147 int for _, num1 := range m.ProjectedFieldIds { num := uint64(num1) for num >= 1<<7 { - dAtA147[j146] = uint8(uint64(num)&0x7f | 0x80) + dAtA148[j147] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j146++ + j147++ } - dAtA147[j146] = uint8(num) - j146++ + dAtA148[j147] = uint8(num) + j147++ } - i -= j146 - copy(dAtA[i:], dAtA147[:j146]) - i = encodeVarintPlan(dAtA, i, uint64(j146)) + i -= j147 + copy(dAtA[i:], dAtA148[:j147]) + i = encodeVarintPlan(dAtA, i, uint64(j147)) i-- dAtA[i] = 0x4a } @@ -25621,21 +26318,21 @@ func (m *PreInsertUkCtx) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.XXX_unrecognized) } if len(m.KeyTypeCounts) > 0 { - dAtA155 := make([]byte, len(m.KeyTypeCounts)*10) - var j154 int + dAtA156 := make([]byte, len(m.KeyTypeCounts)*10) + var j155 int for _, num1 := range m.KeyTypeCounts { num := uint64(num1) for num >= 1<<7 { - dAtA155[j154] = uint8(uint64(num)&0x7f | 0x80) + dAtA156[j155] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j154++ + j155++ } - dAtA155[j154] = uint8(num) - j154++ + dAtA156[j155] = uint8(num) + j155++ } - i -= j154 - copy(dAtA[i:], dAtA155[:j154]) - i = encodeVarintPlan(dAtA, i, uint64(j154)) + i -= j155 + copy(dAtA[i:], dAtA156[:j155]) + i = encodeVarintPlan(dAtA, i, uint64(j155)) i-- dAtA[i] = 0x1 i-- @@ -25699,21 +26396,21 @@ func (m *PreInsertUkCtx) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x58 } if len(m.TargetColumns) > 0 { - dAtA157 := make([]byte, len(m.TargetColumns)*10) - var j156 int + dAtA158 := make([]byte, len(m.TargetColumns)*10) + var j157 int for _, num1 := range m.TargetColumns { num := uint64(num1) for num >= 1<<7 { - dAtA157[j156] = uint8(uint64(num)&0x7f | 0x80) + dAtA158[j157] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j156++ + j157++ } - dAtA157[j156] = uint8(num) - j156++ + dAtA158[j157] = uint8(num) + j157++ } - i -= j156 - copy(dAtA[i:], dAtA157[:j156]) - i = encodeVarintPlan(dAtA, i, uint64(j156)) + i -= j157 + copy(dAtA[i:], dAtA158[:j157]) + i = encodeVarintPlan(dAtA, i, uint64(j157)) i-- dAtA[i] = 0x52 } @@ -25733,40 +26430,40 @@ func (m *PreInsertUkCtx) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x40 } if len(m.ConflictColumns) > 0 { - dAtA159 := make([]byte, len(m.ConflictColumns)*10) - var j158 int + dAtA160 := make([]byte, len(m.ConflictColumns)*10) + var j159 int for _, num1 := range m.ConflictColumns { num := uint64(num1) for num >= 1<<7 { - dAtA159[j158] = uint8(uint64(num)&0x7f | 0x80) + dAtA160[j159] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j158++ + j159++ } - dAtA159[j158] = uint8(num) - j158++ + dAtA160[j159] = uint8(num) + j159++ } - i -= j158 - copy(dAtA[i:], dAtA159[:j158]) - i = encodeVarintPlan(dAtA, i, uint64(j158)) + i -= j159 + copy(dAtA[i:], dAtA160[:j159]) + i = encodeVarintPlan(dAtA, i, uint64(j159)) i-- dAtA[i] = 0x3a } if len(m.KeyColumns) > 0 { - dAtA161 := make([]byte, len(m.KeyColumns)*10) - var j160 int + dAtA162 := make([]byte, len(m.KeyColumns)*10) + var j161 int for _, num1 := range m.KeyColumns { num := uint64(num1) for num >= 1<<7 { - dAtA161[j160] = uint8(uint64(num)&0x7f | 0x80) + dAtA162[j161] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j160++ + j161++ } - dAtA161[j160] = uint8(num) - j160++ + dAtA162[j161] = uint8(num) + j161++ } - i -= j160 - copy(dAtA[i:], dAtA161[:j160]) - i = encodeVarintPlan(dAtA, i, uint64(j160)) + i -= j161 + copy(dAtA[i:], dAtA162[:j161]) + i = encodeVarintPlan(dAtA, i, uint64(j161)) i-- dAtA[i] = 0x32 } @@ -25806,21 +26503,21 @@ func (m *PreInsertUkCtx) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x10 } if len(m.Columns) > 0 { - dAtA165 := make([]byte, len(m.Columns)*10) - var j164 int + dAtA166 := make([]byte, len(m.Columns)*10) + var j165 int for _, num1 := range m.Columns { num := uint64(num1) for num >= 1<<7 { - dAtA165[j164] = uint8(uint64(num)&0x7f | 0x80) + dAtA166[j165] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j164++ + j165++ } - dAtA165[j164] = uint8(num) - j164++ + dAtA166[j165] = uint8(num) + j165++ } - i -= j164 - copy(dAtA[i:], dAtA165[:j164]) - i = encodeVarintPlan(dAtA, i, uint64(j164)) + i -= j165 + copy(dAtA[i:], dAtA166[:j165]) + i = encodeVarintPlan(dAtA, i, uint64(j165)) i-- dAtA[i] = 0xa } @@ -26144,21 +26841,21 @@ func (m *IdList) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.XXX_unrecognized) } if len(m.List) > 0 { - dAtA174 := make([]byte, len(m.List)*10) - var j173 int + dAtA175 := make([]byte, len(m.List)*10) + var j174 int for _, num1 := range m.List { num := uint64(num1) for num >= 1<<7 { - dAtA174[j173] = uint8(uint64(num)&0x7f | 0x80) + dAtA175[j174] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j173++ + j174++ } - dAtA174[j173] = uint8(num) - j173++ + dAtA175[j174] = uint8(num) + j174++ } - i -= j173 - copy(dAtA[i:], dAtA174[:j173]) - i = encodeVarintPlan(dAtA, i, uint64(j173)) + i -= j174 + copy(dAtA[i:], dAtA175[:j174]) + i = encodeVarintPlan(dAtA, i, uint64(j174)) i-- dAtA[i] = 0xa } @@ -26496,6 +27193,22 @@ func (m *Query) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if len(m.RoutineDependencies) > 0 { + for iNdEx := len(m.RoutineDependencies) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.RoutineDependencies[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPlan(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x8a + } + } if len(m.UnresolvedIndexHints) > 0 { for iNdEx := len(m.UnresolvedIndexHints) - 1; iNdEx >= 0; iNdEx-- { { @@ -26647,21 +27360,21 @@ func (m *Query) MarshalToSizedBuffer(dAtA []byte) (int, error) { } } if len(m.Steps) > 0 { - dAtA181 := make([]byte, len(m.Steps)*10) - var j180 int + dAtA182 := make([]byte, len(m.Steps)*10) + var j181 int for _, num1 := range m.Steps { num := uint64(num1) for num >= 1<<7 { - dAtA181[j180] = uint8(uint64(num)&0x7f | 0x80) + dAtA182[j181] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j180++ + j181++ } - dAtA181[j180] = uint8(num) - j180++ + dAtA182[j181] = uint8(num) + j181++ } - i -= j180 - copy(dAtA[i:], dAtA181[:j180]) - i = encodeVarintPlan(dAtA, i, uint64(j180)) + i -= j181 + copy(dAtA[i:], dAtA182[:j181]) + i = encodeVarintPlan(dAtA, i, uint64(j181)) i-- dAtA[i] = 0x12 } @@ -29677,20 +30390,20 @@ func (m *DropTable) MarshalToSizedBuffer(dAtA []byte) (int, error) { } } if len(m.FkChildTblsReferToMe) > 0 { - dAtA247 := make([]byte, len(m.FkChildTblsReferToMe)*10) - var j246 int + dAtA248 := make([]byte, len(m.FkChildTblsReferToMe)*10) + var j247 int for _, num := range m.FkChildTblsReferToMe { for num >= 1<<7 { - dAtA247[j246] = uint8(uint64(num)&0x7f | 0x80) + dAtA248[j247] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j246++ + j247++ } - dAtA247[j246] = uint8(num) - j246++ + dAtA248[j247] = uint8(num) + j247++ } - i -= j246 - copy(dAtA[i:], dAtA247[:j246]) - i = encodeVarintPlan(dAtA, i, uint64(j246)) + i -= j247 + copy(dAtA[i:], dAtA248[:j247]) + i = encodeVarintPlan(dAtA, i, uint64(j247)) i-- dAtA[i] = 0x62 } @@ -29726,20 +30439,20 @@ func (m *DropTable) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x48 } if len(m.ForeignTbl) > 0 { - dAtA250 := make([]byte, len(m.ForeignTbl)*10) - var j249 int + dAtA251 := make([]byte, len(m.ForeignTbl)*10) + var j250 int for _, num := range m.ForeignTbl { for num >= 1<<7 { - dAtA250[j249] = uint8(uint64(num)&0x7f | 0x80) + dAtA251[j250] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j249++ + j250++ } - dAtA250[j249] = uint8(num) - j249++ + dAtA251[j250] = uint8(num) + j250++ } - i -= j249 - copy(dAtA[i:], dAtA250[:j249]) - i = encodeVarintPlan(dAtA, i, uint64(j249)) + i -= j250 + copy(dAtA[i:], dAtA251[:j250]) + i = encodeVarintPlan(dAtA, i, uint64(j250)) i-- dAtA[i] = 0x3a } @@ -30285,20 +30998,20 @@ func (m *TruncateTable) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x40 } if len(m.ForeignTbl) > 0 { - dAtA259 := make([]byte, len(m.ForeignTbl)*10) - var j258 int + dAtA260 := make([]byte, len(m.ForeignTbl)*10) + var j259 int for _, num := range m.ForeignTbl { for num >= 1<<7 { - dAtA259[j258] = uint8(uint64(num)&0x7f | 0x80) + dAtA260[j259] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j258++ + j259++ } - dAtA259[j258] = uint8(num) - j258++ + dAtA260[j259] = uint8(num) + j259++ } - i -= j258 - copy(dAtA[i:], dAtA259[:j258]) - i = encodeVarintPlan(dAtA, i, uint64(j258)) + i -= j259 + copy(dAtA[i:], dAtA260[:j259]) + i = encodeVarintPlan(dAtA, i, uint64(j259)) i-- dAtA[i] = 0x3a } @@ -30375,20 +31088,20 @@ func (m *ClusterTable) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x18 } if len(m.AccountIDs) > 0 { - dAtA262 := make([]byte, len(m.AccountIDs)*10) - var j261 int + dAtA263 := make([]byte, len(m.AccountIDs)*10) + var j262 int for _, num := range m.AccountIDs { for num >= 1<<7 { - dAtA262[j261] = uint8(uint64(num)&0x7f | 0x80) + dAtA263[j262] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j261++ + j262++ } - dAtA262[j261] = uint8(num) - j261++ + dAtA263[j262] = uint8(num) + j262++ } - i -= j261 - copy(dAtA[i:], dAtA262[:j261]) - i = encodeVarintPlan(dAtA, i, uint64(j261)) + i -= j262 + copy(dAtA[i:], dAtA263[:j262]) + i = encodeVarintPlan(dAtA, i, uint64(j262)) i-- dAtA[i] = 0x12 } @@ -30600,21 +31313,21 @@ func (m *Prepare) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.XXX_unrecognized) } if len(m.ParamTypes) > 0 { - dAtA266 := make([]byte, len(m.ParamTypes)*10) - var j265 int + dAtA267 := make([]byte, len(m.ParamTypes)*10) + var j266 int for _, num1 := range m.ParamTypes { num := uint64(num1) for num >= 1<<7 { - dAtA266[j265] = uint8(uint64(num)&0x7f | 0x80) + dAtA267[j266] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j265++ + j266++ } - dAtA266[j265] = uint8(num) - j265++ + dAtA267[j266] = uint8(num) + j266++ } - i -= j265 - copy(dAtA[i:], dAtA266[:j265]) - i = encodeVarintPlan(dAtA, i, uint64(j265)) + i -= j266 + copy(dAtA[i:], dAtA267[:j266]) + i = encodeVarintPlan(dAtA, i, uint64(j266)) i-- dAtA[i] = 0x22 } @@ -30761,21 +31474,21 @@ func (m *OtherDCL) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.XXX_unrecognized) } if len(m.ParamTypes) > 0 { - dAtA269 := make([]byte, len(m.ParamTypes)*10) - var j268 int + dAtA270 := make([]byte, len(m.ParamTypes)*10) + var j269 int for _, num1 := range m.ParamTypes { num := uint64(num1) for num >= 1<<7 { - dAtA269[j268] = uint8(uint64(num)&0x7f | 0x80) + dAtA270[j269] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j268++ + j269++ } - dAtA269[j268] = uint8(num) - j268++ + dAtA270[j269] = uint8(num) + j269++ } - i -= j268 - copy(dAtA[i:], dAtA269[:j268]) - i = encodeVarintPlan(dAtA, i, uint64(j268)) + i -= j269 + copy(dAtA[i:], dAtA270[:j269]) + i = encodeVarintPlan(dAtA, i, uint64(j269)) i-- dAtA[i] = 0xa } @@ -31599,21 +32312,21 @@ func (m *ODKUForeignKeyCheck) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x12 } if len(m.ColIdxList) > 0 { - dAtA277 := make([]byte, len(m.ColIdxList)*10) - var j276 int + dAtA278 := make([]byte, len(m.ColIdxList)*10) + var j277 int for _, num1 := range m.ColIdxList { num := uint64(num1) for num >= 1<<7 { - dAtA277[j276] = uint8(uint64(num)&0x7f | 0x80) + dAtA278[j277] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j276++ + j277++ } - dAtA277[j276] = uint8(num) - j276++ + dAtA278[j277] = uint8(num) + j277++ } - i -= j276 - copy(dAtA[i:], dAtA277[:j276]) - i = encodeVarintPlan(dAtA, i, uint64(j276)) + i -= j277 + copy(dAtA[i:], dAtA278[:j277]) + i = encodeVarintPlan(dAtA, i, uint64(j277)) i-- dAtA[i] = 0xa } @@ -31715,6 +32428,519 @@ func (m *UnresolvedIndexHint) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *FunctionRef) 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 *FunctionRef) MarshalTo(dAtA []byte) (int, error) { + size := m.ProtoSize() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *FunctionRef) 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 m.DatabaseId != 0 { + i = encodeVarintPlan(dAtA, i, uint64(m.DatabaseId)) + i-- + dAtA[i] = 0x28 + } + if m.AccountId != 0 { + i = encodeVarintPlan(dAtA, i, uint64(m.AccountId)) + i-- + dAtA[i] = 0x20 + } + if m.NamespaceVersion != 0 { + i = encodeVarintPlan(dAtA, i, uint64(m.NamespaceVersion)) + i-- + dAtA[i] = 0x18 + } + if m.Revision != 0 { + i = encodeVarintPlan(dAtA, i, uint64(m.Revision)) + i-- + dAtA[i] = 0x10 + } + if m.FunctionId != 0 { + i = encodeVarintPlan(dAtA, i, uint64(m.FunctionId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *SqlRoutineImplementation) 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 *SqlRoutineImplementation) MarshalTo(dAtA []byte) (int, error) { + size := m.ProtoSize() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SqlRoutineImplementation) 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 m.SemanticDefinitionSchemaVersion != 0 { + i = encodeVarintPlan(dAtA, i, uint64(m.SemanticDefinitionSchemaVersion)) + i-- + dAtA[i] = 0x10 + } + if len(m.DefinitionFingerprint) > 0 { + i -= len(m.DefinitionFingerprint) + copy(dAtA[i:], m.DefinitionFingerprint) + i = encodeVarintPlan(dAtA, i, uint64(len(m.DefinitionFingerprint))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *PythonRoutineImplementation) 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 *PythonRoutineImplementation) MarshalTo(dAtA []byte) (int, error) { + size := m.ProtoSize() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PythonRoutineImplementation) 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.DefinitionFingerprint) > 0 { + i -= len(m.DefinitionFingerprint) + copy(dAtA[i:], m.DefinitionFingerprint) + i = encodeVarintPlan(dAtA, i, uint64(len(m.DefinitionFingerprint))) + i-- + dAtA[i] = 0x5a + } + if len(m.NullPolicy) > 0 { + i -= len(m.NullPolicy) + copy(dAtA[i:], m.NullPolicy) + i = encodeVarintPlan(dAtA, i, uint64(len(m.NullPolicy))) + i-- + dAtA[i] = 0x52 + } + 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] = 0x4a + } + if m.DefinitionSchemaVersion != 0 { + i = encodeVarintPlan(dAtA, i, uint64(m.DefinitionSchemaVersion)) + i-- + dAtA[i] = 0x40 + } + if len(m.SdkVersion) > 0 { + i -= len(m.SdkVersion) + copy(dAtA[i:], m.SdkVersion) + i = encodeVarintPlan(dAtA, i, uint64(len(m.SdkVersion))) + i-- + dAtA[i] = 0x3a + } + if len(m.EnvironmentDigest) > 0 { + i -= len(m.EnvironmentDigest) + copy(dAtA[i:], m.EnvironmentDigest) + i = encodeVarintPlan(dAtA, i, uint64(len(m.EnvironmentDigest))) + i-- + dAtA[i] = 0x32 + } + if len(m.ArtifactDigest) > 0 { + i -= len(m.ArtifactDigest) + copy(dAtA[i:], m.ArtifactDigest) + i = encodeVarintPlan(dAtA, i, uint64(len(m.ArtifactDigest))) + i-- + dAtA[i] = 0x2a + } + if len(m.AdapterVersion) > 0 { + i -= len(m.AdapterVersion) + copy(dAtA[i:], m.AdapterVersion) + i = encodeVarintPlan(dAtA, i, uint64(len(m.AdapterVersion))) + i-- + dAtA[i] = 0x22 + } + if len(m.AbiContract) > 0 { + i -= len(m.AbiContract) + copy(dAtA[i:], m.AbiContract) + i = encodeVarintPlan(dAtA, i, uint64(len(m.AbiContract))) + i-- + dAtA[i] = 0x1a + } + if len(m.Source) > 0 { + i -= len(m.Source) + copy(dAtA[i:], m.Source) + i = encodeVarintPlan(dAtA, i, uint64(len(m.Source))) + i-- + dAtA[i] = 0x12 + } + if len(m.Handler) > 0 { + i -= len(m.Handler) + copy(dAtA[i:], m.Handler) + i = encodeVarintPlan(dAtA, i, uint64(len(m.Handler))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RoutineCall) 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 *RoutineCall) MarshalTo(dAtA []byte) (int, error) { + size := m.ProtoSize() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RoutineCall) 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.NamespaceFingerprint) > 0 { + i -= len(m.NamespaceFingerprint) + copy(dAtA[i:], m.NamespaceFingerprint) + i = encodeVarintPlan(dAtA, i, uint64(len(m.NamespaceFingerprint))) + i-- + dAtA[i] = 0x7a + } + if m.Leakproof { + i-- + if m.Leakproof { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x70 + } + if len(m.SecurityMode) > 0 { + i -= len(m.SecurityMode) + copy(dAtA[i:], m.SecurityMode) + i = encodeVarintPlan(dAtA, i, uint64(len(m.SecurityMode))) + i-- + dAtA[i] = 0x6a + } + if m.MayError { + i-- + if m.MayError { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x60 + } + if len(m.CallsiteId) > 0 { + i -= len(m.CallsiteId) + copy(dAtA[i:], m.CallsiteId) + i = encodeVarintPlan(dAtA, i, uint64(len(m.CallsiteId))) + i-- + dAtA[i] = 0x5a + } + if len(m.Context) > 0 { + for k := range m.Context { + v := m.Context[k] + baseI := i + i -= len(v) + copy(dAtA[i:], v) + i = encodeVarintPlan(dAtA, i, uint64(len(v))) + i-- + dAtA[i] = 0x12 + i -= len(k) + copy(dAtA[i:], k) + i = encodeVarintPlan(dAtA, i, uint64(len(k))) + i-- + dAtA[i] = 0xa + i = encodeVarintPlan(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x52 + } + } + if m.Implementation != nil { + { + size := m.Implementation.ProtoSize() + i -= size + if _, err := m.Implementation.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + if len(m.NullPolicy) > 0 { + i -= len(m.NullPolicy) + copy(dAtA[i:], m.NullPolicy) + i = encodeVarintPlan(dAtA, i, uint64(len(m.NullPolicy))) + i-- + dAtA[i] = 0x3a + } + if len(m.Volatility) > 0 { + i -= len(m.Volatility) + copy(dAtA[i:], m.Volatility) + i = encodeVarintPlan(dAtA, i, uint64(len(m.Volatility))) + i-- + dAtA[i] = 0x32 + } + { + size, err := m.ReturnType.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPlan(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + if len(m.ArgumentTypes) > 0 { + for iNdEx := len(m.ArgumentTypes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ArgumentTypes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPlan(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if len(m.Language) > 0 { + i -= len(m.Language) + copy(dAtA[i:], m.Language) + i = encodeVarintPlan(dAtA, i, uint64(len(m.Language))) + i-- + dAtA[i] = 0x1a + } + if m.FunctionRef != nil { + { + size, err := m.FunctionRef.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPlan(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.ContractVersion != 0 { + i = encodeVarintPlan(dAtA, i, uint64(m.ContractVersion)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *RoutineCall_Sql) MarshalTo(dAtA []byte) (int, error) { + size := m.ProtoSize() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RoutineCall_Sql) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Sql != nil { + { + size, err := m.Sql.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPlan(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + return len(dAtA) - i, nil +} +func (m *RoutineCall_Python) MarshalTo(dAtA []byte) (int, error) { + size := m.ProtoSize() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RoutineCall_Python) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Python != nil { + { + size, err := m.Python.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPlan(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a + } + return len(dAtA) - i, nil +} +func (m *RoutinePlanDependency) 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 *RoutinePlanDependency) MarshalTo(dAtA []byte) (int, error) { + size := m.ProtoSize() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RoutinePlanDependency) 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.NamespaceFingerprint) > 0 { + i -= len(m.NamespaceFingerprint) + copy(dAtA[i:], m.NamespaceFingerprint) + i = encodeVarintPlan(dAtA, i, uint64(len(m.NamespaceFingerprint))) + i-- + dAtA[i] = 0x62 + } + if m.Leakproof { + i-- + if m.Leakproof { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x58 + } + if len(m.SecurityMode) > 0 { + i -= len(m.SecurityMode) + copy(dAtA[i:], m.SecurityMode) + i = encodeVarintPlan(dAtA, i, uint64(len(m.SecurityMode))) + i-- + dAtA[i] = 0x52 + } + if m.MayError { + i-- + if m.MayError { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x48 + } + if len(m.NullPolicy) > 0 { + i -= len(m.NullPolicy) + copy(dAtA[i:], m.NullPolicy) + i = encodeVarintPlan(dAtA, i, uint64(len(m.NullPolicy))) + i-- + dAtA[i] = 0x42 + } + if len(m.Volatility) > 0 { + i -= len(m.Volatility) + copy(dAtA[i:], m.Volatility) + i = encodeVarintPlan(dAtA, i, uint64(len(m.Volatility))) + i-- + dAtA[i] = 0x3a + } + if len(m.EnvironmentDigest) > 0 { + i -= len(m.EnvironmentDigest) + copy(dAtA[i:], m.EnvironmentDigest) + i = encodeVarintPlan(dAtA, i, uint64(len(m.EnvironmentDigest))) + i-- + dAtA[i] = 0x32 + } + if len(m.ArtifactDigest) > 0 { + i -= len(m.ArtifactDigest) + copy(dAtA[i:], m.ArtifactDigest) + i = encodeVarintPlan(dAtA, i, uint64(len(m.ArtifactDigest))) + i-- + dAtA[i] = 0x2a + } + if len(m.DefinitionFingerprint) > 0 { + i -= len(m.DefinitionFingerprint) + copy(dAtA[i:], m.DefinitionFingerprint) + i = encodeVarintPlan(dAtA, i, uint64(len(m.DefinitionFingerprint))) + i-- + dAtA[i] = 0x22 + } + if m.ContractVersion != 0 { + i = encodeVarintPlan(dAtA, i, uint64(m.ContractVersion)) + i-- + dAtA[i] = 0x18 + } + if len(m.Language) > 0 { + i -= len(m.Language) + copy(dAtA[i:], m.Language) + i = encodeVarintPlan(dAtA, i, uint64(len(m.Language))) + i-- + dAtA[i] = 0x12 + } + if m.FunctionRef != nil { + { + size, err := m.FunctionRef.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPlan(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintPlan(dAtA []byte, offset int, v uint64) int { offset -= sovPlan(v) base := offset @@ -32386,6 +33612,10 @@ func (m *Function) ProtoSize() (n int) { if m.SyntaxExplicitCast { n += 2 } + if m.RoutineCall != nil { + l = m.RoutineCall.ProtoSize() + n += 1 + l + sovPlan(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -35619,6 +36849,12 @@ func (m *Query) ProtoSize() (n int) { n += 2 + l + sovPlan(uint64(l)) } } + if len(m.RoutineDependencies) > 0 { + for _, e := range m.RoutineDependencies { + l = e.ProtoSize() + n += 2 + l + sovPlan(uint64(l)) + } + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -38014,6 +39250,256 @@ func (m *UnresolvedIndexHint) ProtoSize() (n int) { return n } +func (m *FunctionRef) ProtoSize() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.FunctionId != 0 { + n += 1 + sovPlan(uint64(m.FunctionId)) + } + if m.Revision != 0 { + n += 1 + sovPlan(uint64(m.Revision)) + } + if m.NamespaceVersion != 0 { + n += 1 + sovPlan(uint64(m.NamespaceVersion)) + } + if m.AccountId != 0 { + n += 1 + sovPlan(uint64(m.AccountId)) + } + if m.DatabaseId != 0 { + n += 1 + sovPlan(uint64(m.DatabaseId)) + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + +func (m *SqlRoutineImplementation) ProtoSize() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.DefinitionFingerprint) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + if m.SemanticDefinitionSchemaVersion != 0 { + n += 1 + sovPlan(uint64(m.SemanticDefinitionSchemaVersion)) + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + +func (m *PythonRoutineImplementation) ProtoSize() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Handler) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + l = len(m.Source) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + l = len(m.AbiContract) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + l = len(m.AdapterVersion) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + l = len(m.ArtifactDigest) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + l = len(m.EnvironmentDigest) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + l = len(m.SdkVersion) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + if m.DefinitionSchemaVersion != 0 { + n += 1 + sovPlan(uint64(m.DefinitionSchemaVersion)) + } + l = len(m.Mode) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + l = len(m.NullPolicy) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + l = len(m.DefinitionFingerprint) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + +func (m *RoutineCall) ProtoSize() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ContractVersion != 0 { + n += 1 + sovPlan(uint64(m.ContractVersion)) + } + if m.FunctionRef != nil { + l = m.FunctionRef.ProtoSize() + n += 1 + l + sovPlan(uint64(l)) + } + l = len(m.Language) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + if len(m.ArgumentTypes) > 0 { + for _, e := range m.ArgumentTypes { + l = e.ProtoSize() + n += 1 + l + sovPlan(uint64(l)) + } + } + l = m.ReturnType.ProtoSize() + n += 1 + l + sovPlan(uint64(l)) + l = len(m.Volatility) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + l = len(m.NullPolicy) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + if m.Implementation != nil { + n += m.Implementation.ProtoSize() + } + if len(m.Context) > 0 { + for k, v := range m.Context { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sovPlan(uint64(len(k))) + 1 + len(v) + sovPlan(uint64(len(v))) + n += mapEntrySize + 1 + sovPlan(uint64(mapEntrySize)) + } + } + l = len(m.CallsiteId) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + if m.MayError { + n += 2 + } + l = len(m.SecurityMode) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + if m.Leakproof { + n += 2 + } + l = len(m.NamespaceFingerprint) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + +func (m *RoutineCall_Sql) ProtoSize() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Sql != nil { + l = m.Sql.ProtoSize() + n += 1 + l + sovPlan(uint64(l)) + } + return n +} +func (m *RoutineCall_Python) ProtoSize() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Python != nil { + l = m.Python.ProtoSize() + n += 1 + l + sovPlan(uint64(l)) + } + return n +} +func (m *RoutinePlanDependency) ProtoSize() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.FunctionRef != nil { + l = m.FunctionRef.ProtoSize() + n += 1 + l + sovPlan(uint64(l)) + } + l = len(m.Language) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + if m.ContractVersion != 0 { + n += 1 + sovPlan(uint64(m.ContractVersion)) + } + l = len(m.DefinitionFingerprint) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + l = len(m.ArtifactDigest) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + l = len(m.EnvironmentDigest) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + l = len(m.Volatility) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + l = len(m.NullPolicy) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + if m.MayError { + n += 2 + } + l = len(m.SecurityMode) + if l > 0 { + n += 1 + l + sovPlan(uint64(l)) + } + if m.Leakproof { + n += 2 + } + l = len(m.NamespaceFingerprint) + 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 } @@ -41116,6 +42602,42 @@ func (m *Function) Unmarshal(dAtA []byte) error { } } m.SyntaxExplicitCast = bool(v != 0) + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RoutineCall", 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.RoutineCall == nil { + m.RoutineCall = &RoutineCall{} + } + if err := m.RoutineCall.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipPlan(dAtA[iNdEx:]) @@ -61796,79 +63318,113 @@ func (m *Query) Unmarshal(dAtA []byte) error { return err } 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 (m *TransationControl) 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: TransationControl: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: TransationControl: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TclType", wireType) - } - m.TclType = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPlan - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.TclType |= TransationControl_TclType(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: + case 17: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Begin", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RoutineDependencies", 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 + } + m.RoutineDependencies = append(m.RoutineDependencies, &RoutinePlanDependency{}) + if err := m.RoutineDependencies[len(m.RoutineDependencies)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + 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 (m *TransationControl) 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: TransationControl: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TransationControl: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TclType", wireType) + } + m.TclType = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TclType |= TransationControl_TclType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Begin", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -74439,6 +75995,1650 @@ func (m *UnresolvedIndexHint) Unmarshal(dAtA []byte) error { } return nil } +func (m *FunctionRef) 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: FunctionRef: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: FunctionRef: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field FunctionId", wireType) + } + m.FunctionId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.FunctionId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Revision", wireType) + } + m.Revision = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Revision |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field NamespaceVersion", wireType) + } + m.NamespaceVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.NamespaceVersion |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AccountId", wireType) + } + m.AccountId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.AccountId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DatabaseId", wireType) + } + m.DatabaseId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.DatabaseId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + 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 (m *SqlRoutineImplementation) 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: SqlRoutineImplementation: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SqlRoutineImplementation: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DefinitionFingerprint", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthPlan + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthPlan + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DefinitionFingerprint = append(m.DefinitionFingerprint[:0], dAtA[iNdEx:postIndex]...) + if m.DefinitionFingerprint == nil { + m.DefinitionFingerprint = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SemanticDefinitionSchemaVersion", wireType) + } + m.SemanticDefinitionSchemaVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SemanticDefinitionSchemaVersion |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + 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 (m *PythonRoutineImplementation) 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: PythonRoutineImplementation: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PythonRoutineImplementation: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Handler", 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.Handler = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Source", 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.Source = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AbiContract", 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.AbiContract = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AdapterVersion", 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.AdapterVersion = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ArtifactDigest", 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.ArtifactDigest = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EnvironmentDigest", 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.EnvironmentDigest = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SdkVersion", 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.SdkVersion = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DefinitionSchemaVersion", wireType) + } + m.DefinitionSchemaVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.DefinitionSchemaVersion |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 9: + 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 + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NullPolicy", 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.NullPolicy = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DefinitionFingerprint", 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.DefinitionFingerprint = 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 (m *RoutineCall) 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: RoutineCall: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RoutineCall: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ContractVersion", wireType) + } + m.ContractVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ContractVersion |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FunctionRef", 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.FunctionRef == nil { + m.FunctionRef = &FunctionRef{} + } + if err := m.FunctionRef.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Language", 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.Language = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ArgumentTypes", 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 + } + m.ArgumentTypes = append(m.ArgumentTypes, &Type{}) + if err := m.ArgumentTypes[len(m.ArgumentTypes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ReturnType", 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 err := m.ReturnType.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Volatility", 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.Volatility = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NullPolicy", 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.NullPolicy = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sql", 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 + } + v := &SqlRoutineImplementation{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Implementation = &RoutineCall_Sql{v} + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Python", 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 + } + v := &PythonRoutineImplementation{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Implementation = &RoutineCall_Python{v} + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Context", 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.Context == nil { + m.Context = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthPlan + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLengthPlan + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthPlan + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return ErrInvalidLengthPlan + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipPlan(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPlan + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.Context[mapkey] = mapvalue + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CallsiteId", 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.CallsiteId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 12: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MayError", 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.MayError = bool(v != 0) + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SecurityMode", 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.SecurityMode = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 14: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Leakproof", 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.Leakproof = bool(v != 0) + case 15: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NamespaceFingerprint", 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.NamespaceFingerprint = 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 (m *RoutinePlanDependency) 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: RoutinePlanDependency: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RoutinePlanDependency: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FunctionRef", 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.FunctionRef == nil { + m.FunctionRef = &FunctionRef{} + } + if err := m.FunctionRef.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Language", 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.Language = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ContractVersion", wireType) + } + m.ContractVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ContractVersion |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DefinitionFingerprint", 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.DefinitionFingerprint = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ArtifactDigest", 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.ArtifactDigest = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EnvironmentDigest", 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.EnvironmentDigest = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Volatility", 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.Volatility = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NullPolicy", 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.NullPolicy = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 9: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MayError", 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.MayError = bool(v != 0) + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SecurityMode", 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.SecurityMode = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 11: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Leakproof", 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.Leakproof = bool(v != 0) + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NamespaceFingerprint", 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.NamespaceFingerprint = 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/pb/query/query.pb.go b/pkg/pb/query/query.pb.go index 14b14ebaf5e36..6d79753f0c695 100644 --- a/pkg/pb/query/query.pb.go +++ b/pkg/pb/query/query.pb.go @@ -111,6 +111,9 @@ const ( CmdMethod_MongoDBClientRetire CmdMethod = 39 // RefreshSessionAuth revalidates a cached backend against the current catalog. CmdMethod_RefreshSessionAuth CmdMethod = 40 + // GetPythonUdfStatus returns the bounded, read-only Python runtime status of + // the addressed CN. It is consumed by the Operator for same-Pod workers. + CmdMethod_GetPythonUdfStatus CmdMethod = 41 ) var CmdMethod_name = map[int32]string{ @@ -155,6 +158,7 @@ var CmdMethod_name = map[int32]string{ 38: "IcebergCacheInvalidate", 39: "MongoDBClientRetire", 40: "RefreshSessionAuth", + 41: "GetPythonUdfStatus", } var CmdMethod_value = map[string]int32{ @@ -199,6 +203,7 @@ var CmdMethod_value = map[string]int32{ "IcebergCacheInvalidate": 38, "MongoDBClientRetire": 39, "RefreshSessionAuth": 40, + "GetPythonUdfStatus": 41, } func (x CmdMethod) String() string { @@ -1021,6 +1026,8 @@ type Request struct { MongoDBClientRetireRequest MongoDBClientRetireRequest `protobuf:"bytes,41,opt,name=MongoDBClientRetireRequest,proto3" json:"MongoDBClientRetireRequest"` // RefreshSessionAuthRequest reauthenticates a cached backend for a new login. RefreshSessionAuthRequest *RefreshSessionAuthRequest `protobuf:"bytes,42,opt,name=RefreshSessionAuthRequest,proto3" json:"RefreshSessionAuthRequest,omitempty"` + // GetPythonUdfStatusRequest asks this CN for its local Python runtime state. + GetPythonUdfStatusRequest GetPythonUdfStatusRequest `protobuf:"bytes,43,opt,name=GetPythonUdfStatusRequest,proto3" json:"GetPythonUdfStatusRequest"` } func (m *Request) Reset() { *m = Request{} } @@ -1350,6 +1357,13 @@ func (m *Request) GetRefreshSessionAuthRequest() *RefreshSessionAuthRequest { return nil } +func (m *Request) GetGetPythonUdfStatusRequest() GetPythonUdfStatusRequest { + if m != nil { + return m.GetPythonUdfStatusRequest + } + return GetPythonUdfStatusRequest{} +} + // ShowProcessListResponse is the response of command ShowProcessList. type ShowProcessListResponse struct { Sessions []*status.Session `protobuf:"bytes,1,rep,name=Sessions,proto3" json:"Sessions,omitempty"` @@ -1454,6 +1468,8 @@ type Response struct { MongoDBClientRetireResponse MongoDBClientRetireResponse `protobuf:"bytes,42,opt,name=MongoDBClientRetireResponse,proto3" json:"MongoDBClientRetireResponse"` // RefreshSessionAuthResponse contains the current authentication string. RefreshSessionAuthResponse *RefreshSessionAuthResponse `protobuf:"bytes,43,opt,name=RefreshSessionAuthResponse,proto3" json:"RefreshSessionAuthResponse,omitempty"` + // GetPythonUdfStatus is a bounded summary of the CN-local Python contract. + GetPythonUdfStatus GetPythonUdfStatusResponse `protobuf:"bytes,44,opt,name=GetPythonUdfStatus,proto3" json:"GetPythonUdfStatus"` } func (m *Response) Reset() { *m = Response{} } @@ -1790,6 +1806,277 @@ func (m *Response) GetRefreshSessionAuthResponse() *RefreshSessionAuthResponse { return nil } +func (m *Response) GetGetPythonUdfStatus() GetPythonUdfStatusResponse { + if m != nil { + return m.GetPythonUdfStatus + } + return GetPythonUdfStatusResponse{} +} + +type GetPythonUdfStatusRequest struct { +} + +func (m *GetPythonUdfStatusRequest) Reset() { *m = GetPythonUdfStatusRequest{} } +func (m *GetPythonUdfStatusRequest) String() string { return proto.CompactTextString(m) } +func (*GetPythonUdfStatusRequest) ProtoMessage() {} +func (*GetPythonUdfStatusRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_5c6ac9b241082464, []int{19} +} +func (m *GetPythonUdfStatusRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetPythonUdfStatusRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetPythonUdfStatusRequest.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 *GetPythonUdfStatusRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetPythonUdfStatusRequest.Merge(m, src) +} +func (m *GetPythonUdfStatusRequest) XXX_Size() int { + return m.ProtoSize() +} +func (m *GetPythonUdfStatusRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetPythonUdfStatusRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetPythonUdfStatusRequest proto.InternalMessageInfo + +type GetPythonUdfStatusResponse struct { + CNUUID string `protobuf:"bytes,1,opt,name=CNUUID,proto3" json:"CNUUID,omitempty"` + Language string `protobuf:"bytes,2,opt,name=Language,proto3" json:"Language,omitempty"` + Enabled bool `protobuf:"varint,3,opt,name=Enabled,proto3" json:"Enabled,omitempty"` + AllowUnisolated bool `protobuf:"varint,4,opt,name=AllowUnisolated,proto3" json:"AllowUnisolated,omitempty"` + Ready bool `protobuf:"varint,5,opt,name=Ready,proto3" json:"Ready,omitempty"` + ErrorClass string `protobuf:"bytes,6,opt,name=ErrorClass,proto3" json:"ErrorClass,omitempty"` + Reason string `protobuf:"bytes,7,opt,name=Reason,proto3" json:"Reason,omitempty"` + ProtocolVersion int32 `protobuf:"varint,8,opt,name=ProtocolVersion,proto3" json:"ProtocolVersion,omitempty"` + ABIContract string `protobuf:"bytes,9,opt,name=ABIContract,proto3" json:"ABIContract,omitempty"` + AdapterVersion string `protobuf:"bytes,10,opt,name=AdapterVersion,proto3" json:"AdapterVersion,omitempty"` + SDKVersion string `protobuf:"bytes,11,opt,name=SDKVersion,proto3" json:"SDKVersion,omitempty"` + DefinitionSchemaVersion int32 `protobuf:"varint,12,opt,name=DefinitionSchemaVersion,proto3" json:"DefinitionSchemaVersion,omitempty"` + PlanContractVersion int32 `protobuf:"varint,13,opt,name=PlanContractVersion,proto3" json:"PlanContractVersion,omitempty"` + TypeDescriptorContract string `protobuf:"bytes,14,opt,name=TypeDescriptorContract,proto3" json:"TypeDescriptorContract,omitempty"` + TimezoneDatabaseVersion string `protobuf:"bytes,15,opt,name=TimezoneDatabaseVersion,proto3" json:"TimezoneDatabaseVersion,omitempty"` + WindowBatches int32 `protobuf:"varint,16,opt,name=WindowBatches,proto3" json:"WindowBatches,omitempty"` + CumulativeAck bool `protobuf:"varint,17,opt,name=CumulativeAck,proto3" json:"CumulativeAck,omitempty"` + MaxExecutionFrameBytes int64 `protobuf:"varint,18,opt,name=MaxExecutionFrameBytes,proto3" json:"MaxExecutionFrameBytes,omitempty"` + MaxHandlerProcesses int32 `protobuf:"varint,19,opt,name=MaxHandlerProcesses,proto3" json:"MaxHandlerProcesses,omitempty"` + MaxAccountHandlerProcesses int32 `protobuf:"varint,20,opt,name=MaxAccountHandlerProcesses,proto3" json:"MaxAccountHandlerProcesses,omitempty"` + MaxOwnerHandlerProcesses int32 `protobuf:"varint,21,opt,name=MaxOwnerHandlerProcesses,proto3" json:"MaxOwnerHandlerProcesses,omitempty"` + LeaseEpoch uint64 `protobuf:"varint,22,opt,name=LeaseEpoch,proto3" json:"LeaseEpoch,omitempty"` + Modes []string `protobuf:"bytes,23,rep,name=Modes,proto3" json:"Modes,omitempty"` + NullPolicies []string `protobuf:"bytes,24,rep,name=NullPolicies,proto3" json:"NullPolicies,omitempty"` +} + +func (m *GetPythonUdfStatusResponse) Reset() { *m = GetPythonUdfStatusResponse{} } +func (m *GetPythonUdfStatusResponse) String() string { return proto.CompactTextString(m) } +func (*GetPythonUdfStatusResponse) ProtoMessage() {} +func (*GetPythonUdfStatusResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_5c6ac9b241082464, []int{20} +} +func (m *GetPythonUdfStatusResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetPythonUdfStatusResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetPythonUdfStatusResponse.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 *GetPythonUdfStatusResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetPythonUdfStatusResponse.Merge(m, src) +} +func (m *GetPythonUdfStatusResponse) XXX_Size() int { + return m.ProtoSize() +} +func (m *GetPythonUdfStatusResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetPythonUdfStatusResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetPythonUdfStatusResponse proto.InternalMessageInfo + +func (m *GetPythonUdfStatusResponse) GetCNUUID() string { + if m != nil { + return m.CNUUID + } + return "" +} + +func (m *GetPythonUdfStatusResponse) GetLanguage() string { + if m != nil { + return m.Language + } + return "" +} + +func (m *GetPythonUdfStatusResponse) GetEnabled() bool { + if m != nil { + return m.Enabled + } + return false +} + +func (m *GetPythonUdfStatusResponse) GetAllowUnisolated() bool { + if m != nil { + return m.AllowUnisolated + } + return false +} + +func (m *GetPythonUdfStatusResponse) GetReady() bool { + if m != nil { + return m.Ready + } + return false +} + +func (m *GetPythonUdfStatusResponse) GetErrorClass() string { + if m != nil { + return m.ErrorClass + } + return "" +} + +func (m *GetPythonUdfStatusResponse) GetReason() string { + if m != nil { + return m.Reason + } + return "" +} + +func (m *GetPythonUdfStatusResponse) GetProtocolVersion() int32 { + if m != nil { + return m.ProtocolVersion + } + return 0 +} + +func (m *GetPythonUdfStatusResponse) GetABIContract() string { + if m != nil { + return m.ABIContract + } + return "" +} + +func (m *GetPythonUdfStatusResponse) GetAdapterVersion() string { + if m != nil { + return m.AdapterVersion + } + return "" +} + +func (m *GetPythonUdfStatusResponse) GetSDKVersion() string { + if m != nil { + return m.SDKVersion + } + return "" +} + +func (m *GetPythonUdfStatusResponse) GetDefinitionSchemaVersion() int32 { + if m != nil { + return m.DefinitionSchemaVersion + } + return 0 +} + +func (m *GetPythonUdfStatusResponse) GetPlanContractVersion() int32 { + if m != nil { + return m.PlanContractVersion + } + return 0 +} + +func (m *GetPythonUdfStatusResponse) GetTypeDescriptorContract() string { + if m != nil { + return m.TypeDescriptorContract + } + return "" +} + +func (m *GetPythonUdfStatusResponse) GetTimezoneDatabaseVersion() string { + if m != nil { + return m.TimezoneDatabaseVersion + } + return "" +} + +func (m *GetPythonUdfStatusResponse) GetWindowBatches() int32 { + if m != nil { + return m.WindowBatches + } + return 0 +} + +func (m *GetPythonUdfStatusResponse) GetCumulativeAck() bool { + if m != nil { + return m.CumulativeAck + } + return false +} + +func (m *GetPythonUdfStatusResponse) GetMaxExecutionFrameBytes() int64 { + if m != nil { + return m.MaxExecutionFrameBytes + } + return 0 +} + +func (m *GetPythonUdfStatusResponse) GetMaxHandlerProcesses() int32 { + if m != nil { + return m.MaxHandlerProcesses + } + return 0 +} + +func (m *GetPythonUdfStatusResponse) GetMaxAccountHandlerProcesses() int32 { + if m != nil { + return m.MaxAccountHandlerProcesses + } + return 0 +} + +func (m *GetPythonUdfStatusResponse) GetMaxOwnerHandlerProcesses() int32 { + if m != nil { + return m.MaxOwnerHandlerProcesses + } + return 0 +} + +func (m *GetPythonUdfStatusResponse) GetLeaseEpoch() uint64 { + if m != nil { + return m.LeaseEpoch + } + return 0 +} + +func (m *GetPythonUdfStatusResponse) GetModes() []string { + if m != nil { + return m.Modes + } + return nil +} + +func (m *GetPythonUdfStatusResponse) GetNullPolicies() []string { + if m != nil { + return m.NullPolicies + } + return nil +} + // AlterAccountRequest is the "alter account restricted" query request. type AlterAccountRequest struct { // Tenant is the tenant which to alter. @@ -1802,7 +2089,7 @@ func (m *AlterAccountRequest) Reset() { *m = AlterAccountRequest{} } func (m *AlterAccountRequest) String() string { return proto.CompactTextString(m) } func (*AlterAccountRequest) ProtoMessage() {} func (*AlterAccountRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{19} + return fileDescriptor_5c6ac9b241082464, []int{21} } func (m *AlterAccountRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1854,7 +2141,7 @@ func (m *AlterAccountResponse) Reset() { *m = AlterAccountResponse{} } func (m *AlterAccountResponse) String() string { return proto.CompactTextString(m) } func (*AlterAccountResponse) ProtoMessage() {} func (*AlterAccountResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{20} + return fileDescriptor_5c6ac9b241082464, []int{22} } func (m *AlterAccountResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1901,7 +2188,7 @@ func (m *KillConnRequest) Reset() { *m = KillConnRequest{} } func (m *KillConnRequest) String() string { return proto.CompactTextString(m) } func (*KillConnRequest) ProtoMessage() {} func (*KillConnRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{21} + return fileDescriptor_5c6ac9b241082464, []int{23} } func (m *KillConnRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1953,7 +2240,7 @@ func (m *KillConnResponse) Reset() { *m = KillConnResponse{} } func (m *KillConnResponse) String() string { return proto.CompactTextString(m) } func (*KillConnResponse) ProtoMessage() {} func (*KillConnResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{22} + return fileDescriptor_5c6ac9b241082464, []int{24} } func (m *KillConnResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1999,7 +2286,7 @@ func (m *CtlReaderRequest) Reset() { *m = CtlReaderRequest{} } func (m *CtlReaderRequest) String() string { return proto.CompactTextString(m) } func (*CtlReaderRequest) ProtoMessage() {} func (*CtlReaderRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{23} + return fileDescriptor_5c6ac9b241082464, []int{25} } func (m *CtlReaderRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2057,7 +2344,7 @@ func (m *CtlReaderResponse) Reset() { *m = CtlReaderResponse{} } func (m *CtlReaderResponse) String() string { return proto.CompactTextString(m) } func (*CtlReaderResponse) ProtoMessage() {} func (*CtlReaderResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{24} + return fileDescriptor_5c6ac9b241082464, []int{26} } func (m *CtlReaderResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2101,7 +2388,7 @@ func (m *CtlPrefetchOnSubscribedRequest) Reset() { *m = CtlPrefetchOnSub func (m *CtlPrefetchOnSubscribedRequest) String() string { return proto.CompactTextString(m) } func (*CtlPrefetchOnSubscribedRequest) ProtoMessage() {} func (*CtlPrefetchOnSubscribedRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{25} + return fileDescriptor_5c6ac9b241082464, []int{27} } func (m *CtlPrefetchOnSubscribedRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2145,7 +2432,7 @@ func (m *CtlPrefetchOnSubscribedResponse) Reset() { *m = CtlPrefetchOnSu func (m *CtlPrefetchOnSubscribedResponse) String() string { return proto.CompactTextString(m) } func (*CtlPrefetchOnSubscribedResponse) ProtoMessage() {} func (*CtlPrefetchOnSubscribedResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{26} + return fileDescriptor_5c6ac9b241082464, []int{28} } func (m *CtlPrefetchOnSubscribedResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2194,7 +2481,7 @@ func (m *ISCPDrainConsumerRequest) Reset() { *m = ISCPDrainConsumerReque func (m *ISCPDrainConsumerRequest) String() string { return proto.CompactTextString(m) } func (*ISCPDrainConsumerRequest) ProtoMessage() {} func (*ISCPDrainConsumerRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{27} + return fileDescriptor_5c6ac9b241082464, []int{29} } func (m *ISCPDrainConsumerRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2273,7 +2560,7 @@ func (m *ISCPDrainConsumerResponse) Reset() { *m = ISCPDrainConsumerResp func (m *ISCPDrainConsumerResponse) String() string { return proto.CompactTextString(m) } func (*ISCPDrainConsumerResponse) ProtoMessage() {} func (*ISCPDrainConsumerResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{28} + return fileDescriptor_5c6ac9b241082464, []int{30} } func (m *ISCPDrainConsumerResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2319,7 +2606,7 @@ func (m *TraceSpanRequest) Reset() { *m = TraceSpanRequest{} } func (m *TraceSpanRequest) String() string { return proto.CompactTextString(m) } func (*TraceSpanRequest) ProtoMessage() {} func (*TraceSpanRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{29} + return fileDescriptor_5c6ac9b241082464, []int{31} } func (m *TraceSpanRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2377,7 +2664,7 @@ func (m *TraceSpanResponse) Reset() { *m = TraceSpanResponse{} } func (m *TraceSpanResponse) String() string { return proto.CompactTextString(m) } func (*TraceSpanResponse) ProtoMessage() {} func (*TraceSpanResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{30} + return fileDescriptor_5c6ac9b241082464, []int{32} } func (m *TraceSpanResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2420,7 +2707,7 @@ func (m *GetLockInfoRequest) Reset() { *m = GetLockInfoRequest{} } func (m *GetLockInfoRequest) String() string { return proto.CompactTextString(m) } func (*GetLockInfoRequest) ProtoMessage() {} func (*GetLockInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{31} + return fileDescriptor_5c6ac9b241082464, []int{33} } func (m *GetLockInfoRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2462,7 +2749,7 @@ func (m *LockInfo) Reset() { *m = LockInfo{} } func (m *LockInfo) String() string { return proto.CompactTextString(m) } func (*LockInfo) ProtoMessage() {} func (*LockInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{32} + return fileDescriptor_5c6ac9b241082464, []int{34} } func (m *LockInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2542,7 +2829,7 @@ func (m *GetLockInfoResponse) Reset() { *m = GetLockInfoResponse{} } func (m *GetLockInfoResponse) String() string { return proto.CompactTextString(m) } func (*GetLockInfoResponse) ProtoMessage() {} func (*GetLockInfoResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{33} + return fileDescriptor_5c6ac9b241082464, []int{35} } func (m *GetLockInfoResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2592,7 +2879,7 @@ func (m *GetTxnInfoRequest) Reset() { *m = GetTxnInfoRequest{} } func (m *GetTxnInfoRequest) String() string { return proto.CompactTextString(m) } func (*GetTxnInfoRequest) ProtoMessage() {} func (*GetTxnInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{34} + return fileDescriptor_5c6ac9b241082464, []int{36} } func (m *GetTxnInfoRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2638,7 +2925,7 @@ func (m *TxnLockInfo) Reset() { *m = TxnLockInfo{} } func (m *TxnLockInfo) String() string { return proto.CompactTextString(m) } func (*TxnLockInfo) ProtoMessage() {} func (*TxnLockInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{35} + return fileDescriptor_5c6ac9b241082464, []int{37} } func (m *TxnLockInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2705,7 +2992,7 @@ func (m *TxnInfo) Reset() { *m = TxnInfo{} } func (m *TxnInfo) String() string { return proto.CompactTextString(m) } func (*TxnInfo) ProtoMessage() {} func (*TxnInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{36} + return fileDescriptor_5c6ac9b241082464, []int{38} } func (m *TxnInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2778,7 +3065,7 @@ func (m *GetTxnInfoResponse) Reset() { *m = GetTxnInfoResponse{} } func (m *GetTxnInfoResponse) String() string { return proto.CompactTextString(m) } func (*GetTxnInfoResponse) ProtoMessage() {} func (*GetTxnInfoResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{37} + return fileDescriptor_5c6ac9b241082464, []int{39} } func (m *GetTxnInfoResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2828,7 +3115,7 @@ func (m *GetCacheInfoRequest) Reset() { *m = GetCacheInfoRequest{} } func (m *GetCacheInfoRequest) String() string { return proto.CompactTextString(m) } func (*GetCacheInfoRequest) ProtoMessage() {} func (*GetCacheInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{38} + return fileDescriptor_5c6ac9b241082464, []int{40} } func (m *GetCacheInfoRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2876,7 +3163,7 @@ func (m *CacheInfo) Reset() { *m = CacheInfo{} } func (m *CacheInfo) String() string { return proto.CompactTextString(m) } func (*CacheInfo) ProtoMessage() {} func (*CacheInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{39} + return fileDescriptor_5c6ac9b241082464, []int{41} } func (m *CacheInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2955,7 +3242,7 @@ func (m *GetCacheInfoResponse) Reset() { *m = GetCacheInfoResponse{} } func (m *GetCacheInfoResponse) String() string { return proto.CompactTextString(m) } func (*GetCacheInfoResponse) ProtoMessage() {} func (*GetCacheInfoResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{40} + return fileDescriptor_5c6ac9b241082464, []int{42} } func (m *GetCacheInfoResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3001,7 +3288,7 @@ func (m *RemoveRemoteLockTableRequest) Reset() { *m = RemoveRemoteLockTa func (m *RemoveRemoteLockTableRequest) String() string { return proto.CompactTextString(m) } func (*RemoveRemoteLockTableRequest) ProtoMessage() {} func (*RemoveRemoteLockTableRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{41} + return fileDescriptor_5c6ac9b241082464, []int{43} } func (m *RemoveRemoteLockTableRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3059,7 +3346,7 @@ func (m *RemoveRemoteLockTableResponse) Reset() { *m = RemoveRemoteLockT func (m *RemoveRemoteLockTableResponse) String() string { return proto.CompactTextString(m) } func (*RemoveRemoteLockTableResponse) ProtoMessage() {} func (*RemoveRemoteLockTableResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{42} + return fileDescriptor_5c6ac9b241082464, []int{44} } func (m *RemoveRemoteLockTableResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3104,7 +3391,7 @@ func (m *GetLatestBindRequest) Reset() { *m = GetLatestBindRequest{} } func (m *GetLatestBindRequest) String() string { return proto.CompactTextString(m) } func (*GetLatestBindRequest) ProtoMessage() {} func (*GetLatestBindRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{43} + return fileDescriptor_5c6ac9b241082464, []int{45} } func (m *GetLatestBindRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3155,7 +3442,7 @@ func (m *GetLatestBindResponse) Reset() { *m = GetLatestBindResponse{} } func (m *GetLatestBindResponse) String() string { return proto.CompactTextString(m) } func (*GetLatestBindResponse) ProtoMessage() {} func (*GetLatestBindResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{44} + return fileDescriptor_5c6ac9b241082464, []int{46} } func (m *GetLatestBindResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3204,7 +3491,7 @@ func (m *UnsubscribeTableRequest) Reset() { *m = UnsubscribeTableRequest func (m *UnsubscribeTableRequest) String() string { return proto.CompactTextString(m) } func (*UnsubscribeTableRequest) ProtoMessage() {} func (*UnsubscribeTableRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{45} + return fileDescriptor_5c6ac9b241082464, []int{47} } func (m *UnsubscribeTableRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3256,7 +3543,7 @@ func (m *UnsubscribeTableResponse) Reset() { *m = UnsubscribeTableRespon func (m *UnsubscribeTableResponse) String() string { return proto.CompactTextString(m) } func (*UnsubscribeTableResponse) ProtoMessage() {} func (*UnsubscribeTableResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{46} + return fileDescriptor_5c6ac9b241082464, []int{48} } func (m *UnsubscribeTableResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3302,7 +3589,7 @@ func (m *CacheKey) Reset() { *m = CacheKey{} } func (m *CacheKey) String() string { return proto.CompactTextString(m) } func (*CacheKey) ProtoMessage() {} func (*CacheKey) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{47} + return fileDescriptor_5c6ac9b241082464, []int{49} } func (m *CacheKey) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3360,7 +3647,7 @@ func (m *CacheKeys) Reset() { *m = CacheKeys{} } func (m *CacheKeys) String() string { return proto.CompactTextString(m) } func (*CacheKeys) ProtoMessage() {} func (*CacheKeys) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{48} + return fileDescriptor_5c6ac9b241082464, []int{50} } func (m *CacheKeys) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3405,7 +3692,7 @@ func (m *RequestCacheKey) Reset() { *m = RequestCacheKey{} } func (m *RequestCacheKey) String() string { return proto.CompactTextString(m) } func (*RequestCacheKey) ProtoMessage() {} func (*RequestCacheKey) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{49} + return fileDescriptor_5c6ac9b241082464, []int{51} } func (m *RequestCacheKey) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3458,7 +3745,7 @@ func (m *GetCacheDataRequest) Reset() { *m = GetCacheDataRequest{} } func (m *GetCacheDataRequest) String() string { return proto.CompactTextString(m) } func (*GetCacheDataRequest) ProtoMessage() {} func (*GetCacheDataRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{50} + return fileDescriptor_5c6ac9b241082464, []int{52} } func (m *GetCacheDataRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3505,7 +3792,7 @@ func (m *ResponseCacheData) Reset() { *m = ResponseCacheData{} } func (m *ResponseCacheData) String() string { return proto.CompactTextString(m) } func (*ResponseCacheData) ProtoMessage() {} func (*ResponseCacheData) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{51} + return fileDescriptor_5c6ac9b241082464, []int{53} } func (m *ResponseCacheData) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3564,7 +3851,7 @@ func (m *GetCacheDataResponse) Reset() { *m = GetCacheDataResponse{} } func (m *GetCacheDataResponse) String() string { return proto.CompactTextString(m) } func (*GetCacheDataResponse) ProtoMessage() {} func (*GetCacheDataResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{52} + return fileDescriptor_5c6ac9b241082464, []int{54} } func (m *GetCacheDataResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3608,7 +3895,7 @@ func (m *GetStatsInfoRequest) Reset() { *m = GetStatsInfoRequest{} } func (m *GetStatsInfoRequest) String() string { return proto.CompactTextString(m) } func (*GetStatsInfoRequest) ProtoMessage() {} func (*GetStatsInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{53} + return fileDescriptor_5c6ac9b241082464, []int{55} } func (m *GetStatsInfoRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3652,7 +3939,7 @@ func (m *GetStatsInfoResponse) Reset() { *m = GetStatsInfoResponse{} } func (m *GetStatsInfoResponse) String() string { return proto.CompactTextString(m) } func (*GetStatsInfoResponse) ProtoMessage() {} func (*GetStatsInfoResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{54} + return fileDescriptor_5c6ac9b241082464, []int{56} } func (m *GetStatsInfoResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3698,7 +3985,7 @@ func (m *PrepareStmt) Reset() { *m = PrepareStmt{} } func (m *PrepareStmt) String() string { return proto.CompactTextString(m) } func (*PrepareStmt) ProtoMessage() {} func (*PrepareStmt) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{55} + return fileDescriptor_5c6ac9b241082464, []int{57} } func (m *PrepareStmt) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3758,7 +4045,7 @@ func (m *MigrateTempTable) Reset() { *m = MigrateTempTable{} } func (m *MigrateTempTable) String() string { return proto.CompactTextString(m) } func (*MigrateTempTable) ProtoMessage() {} func (*MigrateTempTable) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{56} + return fileDescriptor_5c6ac9b241082464, []int{58} } func (m *MigrateTempTable) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3823,7 +4110,7 @@ func (m *MigrateConnFromRequest) Reset() { *m = MigrateConnFromRequest{} func (m *MigrateConnFromRequest) String() string { return proto.CompactTextString(m) } func (*MigrateConnFromRequest) ProtoMessage() {} func (*MigrateConnFromRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{57} + return fileDescriptor_5c6ac9b241082464, []int{59} } func (m *MigrateConnFromRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3921,7 +4208,7 @@ func (m *MigrateConnFromResponse) Reset() { *m = MigrateConnFromResponse func (m *MigrateConnFromResponse) String() string { return proto.CompactTextString(m) } func (*MigrateConnFromResponse) ProtoMessage() {} func (*MigrateConnFromResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{58} + return fileDescriptor_5c6ac9b241082464, []int{60} } func (m *MigrateConnFromResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4111,7 +4398,7 @@ func (m *MigrateConnToRequest) Reset() { *m = MigrateConnToRequest{} } func (m *MigrateConnToRequest) String() string { return proto.CompactTextString(m) } func (*MigrateConnToRequest) ProtoMessage() {} func (*MigrateConnToRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{59} + return fileDescriptor_5c6ac9b241082464, []int{61} } func (m *MigrateConnToRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4266,7 +4553,7 @@ func (m *MigrateUserDefinedVar) Reset() { *m = MigrateUserDefinedVar{} } func (m *MigrateUserDefinedVar) String() string { return proto.CompactTextString(m) } func (*MigrateUserDefinedVar) ProtoMessage() {} func (*MigrateUserDefinedVar) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{60} + return fileDescriptor_5c6ac9b241082464, []int{62} } func (m *MigrateUserDefinedVar) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4354,7 +4641,7 @@ func (m *UserLevelLock) Reset() { *m = UserLevelLock{} } func (m *UserLevelLock) String() string { return proto.CompactTextString(m) } func (*UserLevelLock) ProtoMessage() {} func (*UserLevelLock) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{61} + return fileDescriptor_5c6ac9b241082464, []int{63} } func (m *UserLevelLock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4412,7 +4699,7 @@ func (m *MigrateConnToResponse) Reset() { *m = MigrateConnToResponse{} } func (m *MigrateConnToResponse) String() string { return proto.CompactTextString(m) } func (*MigrateConnToResponse) ProtoMessage() {} func (*MigrateConnToResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{62} + return fileDescriptor_5c6ac9b241082464, []int{64} } func (m *MigrateConnToResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4457,7 +4744,7 @@ func (m *ReloadAutoIncrementCacheRequest) Reset() { *m = ReloadAutoIncre func (m *ReloadAutoIncrementCacheRequest) String() string { return proto.CompactTextString(m) } func (*ReloadAutoIncrementCacheRequest) ProtoMessage() {} func (*ReloadAutoIncrementCacheRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{63} + return fileDescriptor_5c6ac9b241082464, []int{65} } func (m *ReloadAutoIncrementCacheRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4501,7 +4788,7 @@ func (m *ReloadAutoIncrementCacheResponse) Reset() { *m = ReloadAutoIncr func (m *ReloadAutoIncrementCacheResponse) String() string { return proto.CompactTextString(m) } func (*ReloadAutoIncrementCacheResponse) ProtoMessage() {} func (*ReloadAutoIncrementCacheResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{64} + return fileDescriptor_5c6ac9b241082464, []int{66} } func (m *ReloadAutoIncrementCacheResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4538,7 +4825,7 @@ func (m *GetReplicaCountRequest) Reset() { *m = GetReplicaCountRequest{} func (m *GetReplicaCountRequest) String() string { return proto.CompactTextString(m) } func (*GetReplicaCountRequest) ProtoMessage() {} func (*GetReplicaCountRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{65} + return fileDescriptor_5c6ac9b241082464, []int{67} } func (m *GetReplicaCountRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4582,7 +4869,7 @@ func (m *GetReplicaCountResponse) Reset() { *m = GetReplicaCountResponse func (m *GetReplicaCountResponse) String() string { return proto.CompactTextString(m) } func (*GetReplicaCountResponse) ProtoMessage() {} func (*GetReplicaCountResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{66} + return fileDescriptor_5c6ac9b241082464, []int{68} } func (m *GetReplicaCountResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4628,7 +4915,7 @@ func (m *ResetSessionRequest) Reset() { *m = ResetSessionRequest{} } func (m *ResetSessionRequest) String() string { return proto.CompactTextString(m) } func (*ResetSessionRequest) ProtoMessage() {} func (*ResetSessionRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{67} + return fileDescriptor_5c6ac9b241082464, []int{69} } func (m *ResetSessionRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4676,7 +4963,7 @@ func (m *ResetSessionResponse) Reset() { *m = ResetSessionResponse{} } func (m *ResetSessionResponse) String() string { return proto.CompactTextString(m) } func (*ResetSessionResponse) ProtoMessage() {} func (*ResetSessionResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{68} + return fileDescriptor_5c6ac9b241082464, []int{70} } func (m *ResetSessionResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4730,7 +5017,7 @@ func (m *GoMaxProcsRequest) Reset() { *m = GoMaxProcsRequest{} } func (m *GoMaxProcsRequest) String() string { return proto.CompactTextString(m) } func (*GoMaxProcsRequest) ProtoMessage() {} func (*GoMaxProcsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{69} + return fileDescriptor_5c6ac9b241082464, []int{71} } func (m *GoMaxProcsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4777,7 +5064,7 @@ func (m *GoMaxProcsResponse) Reset() { *m = GoMaxProcsResponse{} } func (m *GoMaxProcsResponse) String() string { return proto.CompactTextString(m) } func (*GoMaxProcsResponse) ProtoMessage() {} func (*GoMaxProcsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{70} + return fileDescriptor_5c6ac9b241082464, []int{72} } func (m *GoMaxProcsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4821,7 +5108,7 @@ func (m *GoMemLimitRequest) Reset() { *m = GoMemLimitRequest{} } func (m *GoMemLimitRequest) String() string { return proto.CompactTextString(m) } func (*GoMemLimitRequest) ProtoMessage() {} func (*GoMemLimitRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{71} + return fileDescriptor_5c6ac9b241082464, []int{73} } func (m *GoMemLimitRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4868,7 +5155,7 @@ func (m *GoMemLimitResponse) Reset() { *m = GoMemLimitResponse{} } func (m *GoMemLimitResponse) String() string { return proto.CompactTextString(m) } func (*GoMemLimitResponse) ProtoMessage() {} func (*GoMemLimitResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{72} + return fileDescriptor_5c6ac9b241082464, []int{74} } func (m *GoMemLimitResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4915,7 +5202,7 @@ func (m *FileServiceCacheRequest) Reset() { *m = FileServiceCacheRequest func (m *FileServiceCacheRequest) String() string { return proto.CompactTextString(m) } func (*FileServiceCacheRequest) ProtoMessage() {} func (*FileServiceCacheRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{73} + return fileDescriptor_5c6ac9b241082464, []int{75} } func (m *FileServiceCacheRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4969,7 +5256,7 @@ func (m *FileServiceCacheResponse) Reset() { *m = FileServiceCacheRespon func (m *FileServiceCacheResponse) String() string { return proto.CompactTextString(m) } func (*FileServiceCacheResponse) ProtoMessage() {} func (*FileServiceCacheResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{74} + return fileDescriptor_5c6ac9b241082464, []int{76} } func (m *FileServiceCacheResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5027,7 +5314,7 @@ func (m *FileServiceCacheEvictRequest) Reset() { *m = FileServiceCacheEv func (m *FileServiceCacheEvictRequest) String() string { return proto.CompactTextString(m) } func (*FileServiceCacheEvictRequest) ProtoMessage() {} func (*FileServiceCacheEvictRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{75} + return fileDescriptor_5c6ac9b241082464, []int{77} } func (m *FileServiceCacheEvictRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5073,7 +5360,7 @@ func (m *FileServiceCacheEvictResponse) Reset() { *m = FileServiceCacheE func (m *FileServiceCacheEvictResponse) String() string { return proto.CompactTextString(m) } func (*FileServiceCacheEvictResponse) ProtoMessage() {} func (*FileServiceCacheEvictResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{76} + return fileDescriptor_5c6ac9b241082464, []int{78} } func (m *FileServiceCacheEvictResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5131,7 +5418,7 @@ func (m *MetadataCacheRequest) Reset() { *m = MetadataCacheRequest{} } func (m *MetadataCacheRequest) String() string { return proto.CompactTextString(m) } func (*MetadataCacheRequest) ProtoMessage() {} func (*MetadataCacheRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{77} + return fileDescriptor_5c6ac9b241082464, []int{79} } func (m *MetadataCacheRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5175,7 +5462,7 @@ func (m *MetadataCacheResponse) Reset() { *m = MetadataCacheResponse{} } func (m *MetadataCacheResponse) String() string { return proto.CompactTextString(m) } func (*MetadataCacheResponse) ProtoMessage() {} func (*MetadataCacheResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{78} + return fileDescriptor_5c6ac9b241082464, []int{80} } func (m *MetadataCacheResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5225,7 +5512,7 @@ func (m *IcebergCacheInvalidateRequest) Reset() { *m = IcebergCacheInval func (m *IcebergCacheInvalidateRequest) String() string { return proto.CompactTextString(m) } func (*IcebergCacheInvalidateRequest) ProtoMessage() {} func (*IcebergCacheInvalidateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{79} + return fileDescriptor_5c6ac9b241082464, []int{81} } func (m *IcebergCacheInvalidateRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5311,7 +5598,7 @@ func (m *IcebergCacheInvalidateResponse) Reset() { *m = IcebergCacheInva func (m *IcebergCacheInvalidateResponse) String() string { return proto.CompactTextString(m) } func (*IcebergCacheInvalidateResponse) ProtoMessage() {} func (*IcebergCacheInvalidateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{80} + return fileDescriptor_5c6ac9b241082464, []int{82} } func (m *IcebergCacheInvalidateResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5355,7 +5642,7 @@ func (m *GoGCPercentRequest) Reset() { *m = GoGCPercentRequest{} } func (m *GoGCPercentRequest) String() string { return proto.CompactTextString(m) } func (*GoGCPercentRequest) ProtoMessage() {} func (*GoGCPercentRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{81} + return fileDescriptor_5c6ac9b241082464, []int{83} } func (m *GoGCPercentRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5402,7 +5689,7 @@ func (m *GoGCPercentResponse) Reset() { *m = GoGCPercentResponse{} } func (m *GoGCPercentResponse) String() string { return proto.CompactTextString(m) } func (*GoGCPercentResponse) ProtoMessage() {} func (*GoGCPercentResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{82} + return fileDescriptor_5c6ac9b241082464, []int{84} } func (m *GoGCPercentResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5447,7 +5734,7 @@ func (m *FaultInjectRequest) Reset() { *m = FaultInjectRequest{} } func (m *FaultInjectRequest) String() string { return proto.CompactTextString(m) } func (*FaultInjectRequest) ProtoMessage() {} func (*FaultInjectRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{83} + return fileDescriptor_5c6ac9b241082464, []int{85} } func (m *FaultInjectRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5498,7 +5785,7 @@ func (m *FaultInjectResponse) Reset() { *m = FaultInjectResponse{} } func (m *FaultInjectResponse) String() string { return proto.CompactTextString(m) } func (*FaultInjectResponse) ProtoMessage() {} func (*FaultInjectResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{84} + return fileDescriptor_5c6ac9b241082464, []int{86} } func (m *FaultInjectResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5542,7 +5829,7 @@ func (m *CtlMoTableStatsRequest) Reset() { *m = CtlMoTableStatsRequest{} func (m *CtlMoTableStatsRequest) String() string { return proto.CompactTextString(m) } func (*CtlMoTableStatsRequest) ProtoMessage() {} func (*CtlMoTableStatsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{85} + return fileDescriptor_5c6ac9b241082464, []int{87} } func (m *CtlMoTableStatsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5586,7 +5873,7 @@ func (m *CtlMoTableStatsResponse) Reset() { *m = CtlMoTableStatsResponse func (m *CtlMoTableStatsResponse) String() string { return proto.CompactTextString(m) } func (*CtlMoTableStatsResponse) ProtoMessage() {} func (*CtlMoTableStatsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{86} + return fileDescriptor_5c6ac9b241082464, []int{88} } func (m *CtlMoTableStatsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5631,7 +5918,7 @@ func (m *WorkspaceThresholdRequest) Reset() { *m = WorkspaceThresholdReq func (m *WorkspaceThresholdRequest) String() string { return proto.CompactTextString(m) } func (*WorkspaceThresholdRequest) ProtoMessage() {} func (*WorkspaceThresholdRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{87} + return fileDescriptor_5c6ac9b241082464, []int{89} } func (m *WorkspaceThresholdRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5683,7 +5970,7 @@ func (m *WorkspaceThresholdResponse) Reset() { *m = WorkspaceThresholdRe func (m *WorkspaceThresholdResponse) String() string { return proto.CompactTextString(m) } func (*WorkspaceThresholdResponse) ProtoMessage() {} func (*WorkspaceThresholdResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{88} + return fileDescriptor_5c6ac9b241082464, []int{90} } func (m *WorkspaceThresholdResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5735,7 +6022,7 @@ func (m *MinTimestampResponse) Reset() { *m = MinTimestampResponse{} } func (m *MinTimestampResponse) String() string { return proto.CompactTextString(m) } func (*MinTimestampResponse) ProtoMessage() {} func (*MinTimestampResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{89} + return fileDescriptor_5c6ac9b241082464, []int{91} } func (m *MinTimestampResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5783,7 +6070,7 @@ func (m *MongoDBClientRetireRequest) Reset() { *m = MongoDBClientRetireR func (m *MongoDBClientRetireRequest) String() string { return proto.CompactTextString(m) } func (*MongoDBClientRetireRequest) ProtoMessage() {} func (*MongoDBClientRetireRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{90} + return fileDescriptor_5c6ac9b241082464, []int{92} } func (m *MongoDBClientRetireRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5841,7 +6128,7 @@ func (m *MongoDBClientRetireResponse) Reset() { *m = MongoDBClientRetire func (m *MongoDBClientRetireResponse) String() string { return proto.CompactTextString(m) } func (*MongoDBClientRetireResponse) ProtoMessage() {} func (*MongoDBClientRetireResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{91} + return fileDescriptor_5c6ac9b241082464, []int{93} } func (m *MongoDBClientRetireResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5892,7 +6179,7 @@ func (m *MigrateSystemVariable) Reset() { *m = MigrateSystemVariable{} } func (m *MigrateSystemVariable) String() string { return proto.CompactTextString(m) } func (*MigrateSystemVariable) ProtoMessage() {} func (*MigrateSystemVariable) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{92} + return fileDescriptor_5c6ac9b241082464, []int{94} } func (m *MigrateSystemVariable) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5964,7 +6251,7 @@ func (m *RefreshSessionAuthRequest) Reset() { *m = RefreshSessionAuthReq func (m *RefreshSessionAuthRequest) String() string { return proto.CompactTextString(m) } func (*RefreshSessionAuthRequest) ProtoMessage() {} func (*RefreshSessionAuthRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{93} + return fileDescriptor_5c6ac9b241082464, []int{95} } func (m *RefreshSessionAuthRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6056,7 +6343,7 @@ func (m *RefreshSessionAuthResponse) Reset() { *m = RefreshSessionAuthRe func (m *RefreshSessionAuthResponse) String() string { return proto.CompactTextString(m) } func (*RefreshSessionAuthResponse) ProtoMessage() {} func (*RefreshSessionAuthResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5c6ac9b241082464, []int{94} + return fileDescriptor_5c6ac9b241082464, []int{96} } func (m *RefreshSessionAuthResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6136,6 +6423,8 @@ func init() { proto.RegisterType((*Request)(nil), "query.Request") proto.RegisterType((*ShowProcessListResponse)(nil), "query.ShowProcessListResponse") proto.RegisterType((*Response)(nil), "query.Response") + proto.RegisterType((*GetPythonUdfStatusRequest)(nil), "query.GetPythonUdfStatusRequest") + proto.RegisterType((*GetPythonUdfStatusResponse)(nil), "query.GetPythonUdfStatusResponse") proto.RegisterType((*AlterAccountRequest)(nil), "query.AlterAccountRequest") proto.RegisterType((*AlterAccountResponse)(nil), "query.AlterAccountResponse") proto.RegisterType((*KillConnRequest)(nil), "query.KillConnRequest") @@ -6217,298 +6506,327 @@ func init() { func init() { proto.RegisterFile("query.proto", fileDescriptor_5c6ac9b241082464) } var fileDescriptor_5c6ac9b241082464 = []byte{ - // 4651 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x5c, 0xdd, 0x6f, 0xdc, 0xc6, - 0x76, 0xf7, 0x4a, 0x2b, 0x69, 0xf7, 0x68, 0x25, 0x51, 0xa3, 0x2f, 0x5a, 0x96, 0x25, 0x99, 0x71, - 0x62, 0xd9, 0xbe, 0x91, 0x5c, 0xdf, 0xc4, 0xb9, 0x1f, 0x69, 0x11, 0x69, 0x65, 0xd9, 0x6b, 0x4b, - 0x96, 0x3c, 0x2b, 0xdb, 0xb9, 0xb9, 0x40, 0x00, 0x6a, 0x77, 0xb4, 0x62, 0xbc, 0x4b, 0x6e, 0x48, - 0xae, 0x23, 0x05, 0xe8, 0x3f, 0xd0, 0x87, 0xe2, 0x3e, 0xf5, 0xb9, 0x05, 0x0a, 0xf4, 0xb9, 0x40, - 0x1f, 0xfb, 0x07, 0x5c, 0xa0, 0x40, 0x71, 0x1f, 0x0a, 0xf4, 0x3e, 0xb5, 0x45, 0xf2, 0x27, 0x14, - 0xe8, 0x6b, 0x2f, 0xce, 0x70, 0xc8, 0xe5, 0x0c, 0x87, 0x94, 0x9d, 0xe4, 0xbe, 0x08, 0x9c, 0x33, - 0xe7, 0xfc, 0x66, 0x38, 0x1f, 0x87, 0xe7, 0x6b, 0x05, 0x93, 0x5f, 0x0f, 0x98, 0x7f, 0xb1, 0xd9, - 0xf7, 0xbd, 0xd0, 0x23, 0x63, 0xbc, 0xb1, 0x5c, 0x0b, 0x42, 0x3b, 0x1c, 0x04, 0x11, 0x71, 0x19, - 0xba, 0x5e, 0xeb, 0xb5, 0x78, 0xae, 0x86, 0xe7, 0xae, 0x78, 0x9c, 0x09, 0x9d, 0x1e, 0x0b, 0x42, - 0xbb, 0xd7, 0x8f, 0x09, 0x28, 0x15, 0x38, 0xee, 0xa9, 0x17, 0x0b, 0xf6, 0xbb, 0x76, 0xcc, 0xfd, - 0x61, 0xc7, 0x09, 0xcf, 0x06, 0x27, 0x9b, 0x2d, 0xaf, 0xb7, 0xd5, 0xf1, 0x3a, 0xde, 0x16, 0x27, - 0x9f, 0x0c, 0x4e, 0x79, 0x8b, 0x37, 0xf8, 0x93, 0x60, 0x5f, 0xeb, 0x78, 0x5e, 0xa7, 0xcb, 0x86, - 0x5c, 0xca, 0x60, 0xd6, 0x4d, 0xa8, 0x3d, 0xc7, 0xb9, 0x52, 0xf6, 0xf5, 0x80, 0x05, 0x21, 0x99, - 0x87, 0x31, 0xde, 0x36, 0x4b, 0xeb, 0xa5, 0x8d, 0x2a, 0x8d, 0x1a, 0xd6, 0x33, 0x58, 0x6c, 0x9e, - 0x79, 0xdf, 0x1c, 0xf9, 0x5e, 0x8b, 0x05, 0xc1, 0xbe, 0x13, 0x84, 0x31, 0xff, 0x22, 0x8c, 0x1f, - 0x33, 0xd7, 0x76, 0x43, 0x21, 0x20, 0x5a, 0x64, 0x05, 0xaa, 0xcd, 0x8b, 0x40, 0x74, 0x8d, 0xac, - 0x97, 0x36, 0x2a, 0x74, 0x48, 0xb0, 0x5e, 0xc1, 0x6c, 0xf3, 0xc2, 0x6d, 0xd5, 0xbd, 0x5e, 0xcf, - 0x49, 0xa0, 0x76, 0x60, 0x7a, 0xdf, 0x0e, 0x59, 0x10, 0x46, 0xe4, 0xe3, 0x26, 0x87, 0x9c, 0xbc, - 0x3f, 0xbf, 0x39, 0x9c, 0xf4, 0x71, 0xfc, 0xb4, 0x53, 0xfe, 0xfd, 0x7f, 0xad, 0x5d, 0xa1, 0x8a, - 0x84, 0xf5, 0x05, 0x90, 0x34, 0x70, 0xd0, 0xf7, 0xdc, 0x80, 0x91, 0x5d, 0x98, 0xa9, 0x0f, 0x7c, - 0x9f, 0xb9, 0xef, 0x02, 0xad, 0x8a, 0x58, 0x04, 0x8c, 0x47, 0x2c, 0x94, 0xe6, 0x6c, 0xfd, 0x06, - 0x66, 0x53, 0xb4, 0x9f, 0x74, 0xb8, 0x2d, 0x58, 0xa8, 0x7b, 0x3e, 0xdb, 0x1d, 0xf4, 0xfa, 0x75, - 0xcf, 0x3d, 0x75, 0x3a, 0xa9, 0x25, 0xdf, 0x6e, 0x85, 0x8e, 0xe7, 0xc6, 0x4b, 0x1e, 0xb5, 0x2c, - 0x13, 0x16, 0x55, 0x81, 0x68, 0x42, 0xd6, 0x35, 0xb8, 0xfa, 0x88, 0x85, 0x47, 0xb8, 0xe1, 0x2d, - 0xaf, 0xfb, 0x92, 0xf9, 0x81, 0xe3, 0xb9, 0xf1, 0x2b, 0x3c, 0x80, 0x65, 0x5d, 0xa7, 0x78, 0x17, - 0x13, 0x26, 0x04, 0x89, 0x8f, 0x36, 0x4a, 0xe3, 0xa6, 0xf5, 0x31, 0x5c, 0x6d, 0xe6, 0x81, 0x16, - 0x88, 0x3d, 0x80, 0xe5, 0xe6, 0x0f, 0x19, 0xee, 0x67, 0x30, 0x4d, 0x07, 0xee, 0xb1, 0x1d, 0xbc, - 0x8e, 0xc7, 0x58, 0x86, 0x0a, 0x36, 0xeb, 0x5e, 0x9b, 0x71, 0xe6, 0x31, 0x9a, 0xb4, 0xad, 0xdb, - 0x30, 0x93, 0x70, 0x0b, 0xe8, 0x45, 0x18, 0xa7, 0x2c, 0x18, 0x74, 0x93, 0x93, 0x1a, 0xb5, 0x70, - 0xd9, 0xf0, 0xfd, 0x9d, 0x3e, 0xeb, 0x3a, 0x2e, 0x6b, 0xb8, 0xa7, 0x5e, 0xbc, 0x32, 0x5b, 0xb0, - 0x94, 0xe9, 0x11, 0x60, 0xf3, 0x30, 0x56, 0xf7, 0x06, 0xe2, 0xd4, 0x8f, 0xd2, 0xa8, 0x61, 0xfd, - 0xdd, 0x32, 0x4c, 0xc4, 0xb3, 0x5b, 0x81, 0xaa, 0x78, 0x6c, 0xec, 0x72, 0xae, 0x32, 0x1d, 0x12, - 0xc8, 0x26, 0x54, 0xeb, 0xbd, 0xf6, 0x01, 0x0b, 0xcf, 0xbc, 0x36, 0xbf, 0x1e, 0xd3, 0xf7, 0x8d, - 0xcd, 0x48, 0x83, 0x24, 0x74, 0x3a, 0x64, 0x21, 0x9f, 0xc8, 0xd7, 0xd4, 0x1c, 0xe5, 0xe7, 0x69, - 0x4e, 0x88, 0xa4, 0xbb, 0xa8, 0x7c, 0x9f, 0x5f, 0xe4, 0xdd, 0x5c, 0xb3, 0xcc, 0x21, 0xae, 0x0b, - 0x08, 0x3d, 0x13, 0xcd, 0xbb, 0xf6, 0xfb, 0x30, 0xb7, 0xdd, 0x0d, 0x99, 0xbf, 0xdd, 0x6a, 0xe1, - 0x9b, 0xc7, 0x98, 0x63, 0x1c, 0x73, 0x59, 0x60, 0x6a, 0x38, 0xa8, 0x4e, 0x8c, 0x7c, 0x06, 0x33, - 0x4f, 0x9d, 0x6e, 0xb7, 0xee, 0xb9, 0xf1, 0x01, 0x32, 0xc7, 0x39, 0xd2, 0xa2, 0x40, 0x52, 0x7a, - 0xa9, 0xca, 0x4e, 0xea, 0x60, 0x1c, 0xfb, 0x76, 0x8b, 0x35, 0xfb, 0x76, 0x02, 0x31, 0xc1, 0x21, - 0x96, 0x04, 0x84, 0xda, 0x4d, 0x33, 0x02, 0xa4, 0x01, 0xe4, 0x11, 0x0b, 0xf7, 0xbd, 0xd6, 0xeb, - 0xd4, 0x29, 0x30, 0x2b, 0x1c, 0xe6, 0xaa, 0x80, 0xc9, 0x32, 0x50, 0x8d, 0x10, 0xd9, 0xe3, 0x7a, - 0xe1, 0xf8, 0xdc, 0x4d, 0x23, 0x55, 0x39, 0x92, 0x39, 0x44, 0x92, 0xfb, 0x69, 0x56, 0x04, 0xd7, - 0x19, 0xf5, 0x8b, 0xdd, 0x3a, 0x4b, 0x9f, 0x4c, 0x13, 0xa4, 0x75, 0xd6, 0x70, 0x50, 0x9d, 0x18, - 0xf9, 0x05, 0x40, 0xf3, 0xa2, 0xe5, 0x46, 0x2a, 0xc6, 0x9c, 0x94, 0xa6, 0x93, 0xd1, 0xc7, 0x34, - 0xc5, 0x4b, 0x3e, 0x86, 0x6a, 0xa2, 0xe7, 0xcc, 0x9a, 0xb4, 0xb0, 0xaa, 0x4e, 0xa4, 0x43, 0x4e, - 0x72, 0xc4, 0x57, 0x54, 0xb9, 0xec, 0xe6, 0x14, 0x97, 0x5f, 0x1f, 0xca, 0xeb, 0x95, 0x08, 0xd5, - 0xc8, 0x22, 0x62, 0x56, 0x7d, 0x98, 0xd3, 0x12, 0x62, 0x33, 0x1f, 0x31, 0xdb, 0x45, 0x76, 0x61, - 0x5a, 0x56, 0x9b, 0xe6, 0x0c, 0x47, 0x5b, 0x89, 0xef, 0xa3, 0x4e, 0x09, 0x53, 0x45, 0x86, 0x6c, - 0xc1, 0x84, 0x50, 0x38, 0xa6, 0xc1, 0xc5, 0x17, 0x84, 0xb8, 0xac, 0xb4, 0x68, 0xcc, 0x45, 0x7e, - 0x03, 0x0b, 0x94, 0xf5, 0xbc, 0x37, 0x0c, 0xff, 0x86, 0x0c, 0x0f, 0xd0, 0xb1, 0x7d, 0xd2, 0x65, - 0xe6, 0x2c, 0x17, 0x7f, 0x2f, 0x16, 0xd7, 0xf1, 0xc4, 0x60, 0x7a, 0x04, 0xb2, 0x0d, 0x53, 0x78, - 0x24, 0xf9, 0x97, 0x71, 0xc7, 0x71, 0xdb, 0x26, 0xe1, 0x90, 0xd7, 0x52, 0x47, 0x38, 0xe9, 0x8b, - 0xa1, 0x64, 0x09, 0xf2, 0x04, 0x8c, 0x17, 0x6e, 0x30, 0x38, 0x09, 0x5a, 0xbe, 0x73, 0xc2, 0xa2, - 0x89, 0xcd, 0x71, 0x94, 0x55, 0x81, 0xa2, 0x76, 0x27, 0xd7, 0x4a, 0xed, 0x48, 0x9f, 0xe1, 0x5d, - 0x3b, 0xb4, 0xe3, 0x33, 0x3c, 0xaf, 0x3d, 0xc3, 0x29, 0x0e, 0xaa, 0x13, 0x13, 0x68, 0xcd, 0xd0, - 0x0e, 0x83, 0xf4, 0x8d, 0x58, 0x50, 0xd1, 0x54, 0x0e, 0xaa, 0x13, 0x43, 0xf5, 0xa8, 0x57, 0xfe, - 0xe6, 0xa2, 0xa4, 0x1e, 0xf5, 0x4c, 0x34, 0x47, 0x18, 0x61, 0x0f, 0x9c, 0x8e, 0x6f, 0x87, 0x0c, - 0x95, 0xd4, 0x9e, 0xef, 0xf5, 0x62, 0xd8, 0x25, 0x09, 0x56, 0xcf, 0x44, 0x73, 0x84, 0xc9, 0x21, - 0xcc, 0xa7, 0x7a, 0x8e, 0x93, 0xb9, 0x9a, 0xd2, 0xfe, 0xea, 0x58, 0xa8, 0x56, 0x90, 0x9c, 0x80, - 0x49, 0x59, 0xd7, 0xb3, 0xdb, 0xdb, 0x83, 0xd0, 0x6b, 0xb8, 0x2d, 0x9f, 0xf5, 0x98, 0x1b, 0xad, - 0xb9, 0x79, 0x95, 0x83, 0x7e, 0x90, 0x9c, 0x43, 0x3d, 0x5b, 0x8c, 0x9f, 0x8b, 0x83, 0xaa, 0xb9, - 0x1e, 0x76, 0x29, 0xb3, 0xdb, 0xcc, 0x8f, 0x27, 0xbc, 0x2c, 0x69, 0x10, 0xb5, 0x9b, 0x66, 0x04, - 0xc8, 0x01, 0xcc, 0x3c, 0x62, 0x21, 0x65, 0xfd, 0xae, 0xd3, 0xb2, 0xa3, 0x2f, 0xef, 0x35, 0x75, - 0x83, 0xd2, 0xbd, 0x42, 0x2e, 0xb6, 0xad, 0x94, 0x5e, 0x3c, 0x44, 0x94, 0x05, 0x2c, 0x6c, 0xb2, - 0x20, 0xa5, 0x1e, 0xcc, 0x15, 0xe9, 0x10, 0x69, 0x38, 0xa8, 0x4e, 0x8c, 0xec, 0xc3, 0xec, 0x23, - 0xef, 0xc0, 0x3e, 0xc7, 0xef, 0x64, 0x10, 0x63, 0x5d, 0x97, 0x95, 0xbd, 0xda, 0x2f, 0x66, 0x96, - 0x15, 0x14, 0x68, 0xac, 0xb7, 0xef, 0x0c, 0x75, 0xaa, 0xb9, 0xaa, 0xa2, 0xc9, 0xfd, 0x29, 0x34, - 0xb9, 0x83, 0x7c, 0x09, 0x4b, 0x7b, 0x4e, 0x97, 0x35, 0x99, 0xff, 0xc6, 0x69, 0xb1, 0xf4, 0x96, - 0x99, 0x6b, 0xd2, 0x7d, 0xce, 0xe1, 0x12, 0xc8, 0x79, 0x20, 0xa4, 0x07, 0x2b, 0x6a, 0xd7, 0xc3, - 0x37, 0x4e, 0x2b, 0x99, 0xf8, 0xba, 0xa4, 0xcd, 0x8a, 0x58, 0xc5, 0x48, 0x85, 0x70, 0xe4, 0x05, - 0xcc, 0x1f, 0xb0, 0xd0, 0x6e, 0xdb, 0xa1, 0x2d, 0xbd, 0xcb, 0x0d, 0xf9, 0x06, 0x68, 0x58, 0x04, - 0xbc, 0x56, 0x9c, 0x1c, 0x02, 0x79, 0xe4, 0x3d, 0xaa, 0x1f, 0x31, 0xbf, 0xc5, 0x86, 0xd6, 0x8c, - 0x25, 0x7f, 0xf9, 0x33, 0x0c, 0x02, 0x52, 0x23, 0x8a, 0xa6, 0xc4, 0x9e, 0x3d, 0xe8, 0x86, 0x0d, - 0xf7, 0x2b, 0x36, 0x5c, 0x8c, 0xf7, 0x24, 0xc0, 0x2c, 0x03, 0xd5, 0x08, 0x91, 0xdf, 0xc2, 0x62, - 0x3d, 0xec, 0x1e, 0x78, 0x5c, 0x99, 0x72, 0x05, 0x16, 0xc3, 0xdd, 0x94, 0x6e, 0x80, 0x9e, 0x49, - 0xcc, 0x31, 0x07, 0x82, 0x7c, 0x09, 0x57, 0x5f, 0x79, 0xfe, 0xeb, 0xa0, 0x6f, 0xb7, 0xd8, 0xf1, - 0x99, 0xcf, 0x82, 0x33, 0xaf, 0x1b, 0x7f, 0x13, 0xcc, 0xf7, 0xa5, 0xaf, 0x6a, 0x2e, 0x1f, 0xcd, - 0x87, 0x20, 0x3d, 0x58, 0xad, 0x87, 0xdd, 0x23, 0x9f, 0x9d, 0xb2, 0xb0, 0x75, 0x76, 0xe8, 0x36, - 0xe3, 0x4f, 0x43, 0x32, 0xc8, 0x07, 0x7c, 0x90, 0xf7, 0x87, 0x2f, 0x51, 0xc0, 0x4c, 0x2f, 0x01, - 0x23, 0xbf, 0x05, 0xb3, 0xd1, 0xac, 0x1f, 0xed, 0xfa, 0xb6, 0xe3, 0xd6, 0x3d, 0x37, 0x18, 0xf4, - 0x86, 0x3a, 0xe7, 0x16, 0x1f, 0x68, 0x4d, 0x0c, 0x94, 0xc7, 0x46, 0x73, 0x01, 0x48, 0x1f, 0xae, - 0x37, 0x5a, 0xec, 0x84, 0xf9, 0x1d, 0x61, 0x58, 0xbd, 0xb1, 0xbb, 0x4e, 0xdb, 0x0e, 0x93, 0x43, - 0xb8, 0xc1, 0x47, 0xb8, 0x19, 0x8f, 0x50, 0xc4, 0x2b, 0xb6, 0xa5, 0x18, 0x90, 0x74, 0x60, 0xf9, - 0xc0, 0x73, 0x3b, 0xde, 0xee, 0x4e, 0xbd, 0xeb, 0xf0, 0xd3, 0x15, 0x3a, 0x7e, 0x32, 0xdc, 0x6d, - 0x3e, 0xdc, 0x8d, 0xf8, 0xcc, 0xe7, 0x32, 0x8a, 0xb1, 0x0a, 0xa0, 0xf0, 0x18, 0x50, 0x76, 0x8a, - 0x7b, 0x27, 0x54, 0xdb, 0xf6, 0x20, 0x3c, 0x8b, 0xc7, 0xb9, 0x23, 0x1d, 0x83, 0x5c, 0x3e, 0x9a, - 0x0f, 0x61, 0xed, 0xc1, 0x52, 0xc6, 0x91, 0x10, 0x9e, 0xd4, 0x5d, 0xa8, 0x08, 0x81, 0xc0, 0x2c, - 0xad, 0x8f, 0x6e, 0x4c, 0xde, 0x9f, 0xd9, 0x14, 0x61, 0x13, 0x41, 0xa7, 0x09, 0x83, 0xf5, 0x8f, - 0xd7, 0xa0, 0x92, 0x48, 0xfe, 0xb4, 0x1e, 0xd6, 0x3c, 0x8c, 0x3d, 0xf4, 0x7d, 0xcf, 0xe7, 0xae, - 0x55, 0x8d, 0x46, 0x0d, 0xf2, 0x79, 0xee, 0xc4, 0xcd, 0xb2, 0xa4, 0x3e, 0x73, 0xb8, 0x68, 0xee, - 0x7b, 0x1f, 0xc2, 0xbc, 0xec, 0x0a, 0x09, 0xd8, 0x31, 0x49, 0x93, 0xe9, 0x58, 0xa8, 0x56, 0x10, - 0xbf, 0xb3, 0x43, 0xaf, 0x48, 0x80, 0x8d, 0x4b, 0xdf, 0x59, 0xb5, 0x9b, 0x66, 0x04, 0xd0, 0x6f, - 0x49, 0xb9, 0x45, 0x02, 0x65, 0x42, 0xfa, 0xf8, 0x64, 0xfa, 0x69, 0x56, 0x44, 0x58, 0x69, 0x43, - 0xaf, 0x48, 0x20, 0x55, 0x54, 0x2b, 0x4d, 0xe5, 0xa0, 0x3a, 0x31, 0xe1, 0x98, 0x25, 0xae, 0x91, - 0x00, 0xab, 0xaa, 0x8e, 0x99, 0xc2, 0x40, 0x35, 0x42, 0xb8, 0xec, 0xb2, 0x67, 0x24, 0xc0, 0x40, - 0x35, 0x91, 0x33, 0x2c, 0x54, 0x2b, 0x48, 0x7e, 0x09, 0x30, 0x74, 0x9d, 0xcc, 0x49, 0x69, 0x4e, - 0xd9, 0x50, 0x14, 0x4d, 0x31, 0x93, 0x07, 0x59, 0xa7, 0xca, 0xcc, 0x3a, 0x55, 0x42, 0x70, 0xc8, - 0x4a, 0x9e, 0x17, 0x78, 0x55, 0x37, 0x0a, 0xbc, 0xaa, 0xd4, 0xb2, 0x28, 0x7d, 0x08, 0x99, 0xeb, - 0x56, 0xdd, 0x28, 0x70, 0xab, 0x62, 0xc8, 0x6c, 0x1f, 0x79, 0x98, 0xe3, 0x57, 0x5d, 0xcf, 0xf1, - 0xab, 0x04, 0x94, 0x22, 0x44, 0xee, 0xa9, 0x8e, 0xd5, 0xa2, 0xea, 0x58, 0x09, 0xc1, 0x98, 0x8d, - 0x7c, 0x51, 0xec, 0x59, 0xdd, 0x2c, 0xf6, 0xac, 0x04, 0x5a, 0x8e, 0x6b, 0xb5, 0xa3, 0x77, 0xad, - 0x56, 0xf4, 0xae, 0x95, 0xc0, 0x92, 0x45, 0xc8, 0xd3, 0x5c, 0xdf, 0x6a, 0x2d, 0xd7, 0xb7, 0x8a, - 0x2f, 0xac, 0xda, 0x93, 0x3e, 0xcf, 0x91, 0x97, 0x24, 0xce, 0xf3, 0xbc, 0xf6, 0x3c, 0xa7, 0x59, - 0xa8, 0x56, 0x50, 0x00, 0xa6, 0x1c, 0x25, 0x01, 0xb8, 0xa0, 0x02, 0x66, 0x58, 0xa8, 0x56, 0x10, - 0x55, 0x68, 0x4e, 0x14, 0xcd, 0x5c, 0x94, 0x54, 0x68, 0x0e, 0x17, 0xcd, 0x13, 0x47, 0xe4, 0x8c, - 0xa3, 0x24, 0x90, 0x97, 0x24, 0xe4, 0x1c, 0x2e, 0x9a, 0x27, 0x4e, 0x28, 0x2c, 0x28, 0xfe, 0x92, - 0xc0, 0x35, 0xa5, 0xed, 0xd6, 0xf2, 0x50, 0xbd, 0x28, 0x69, 0x5d, 0xea, 0x6b, 0xdd, 0xba, 0xd4, - 0xd7, 0x12, 0x23, 0xe4, 0x3b, 0x5b, 0x7b, 0x30, 0x9b, 0xf2, 0x9d, 0xc4, 0xa4, 0x97, 0x25, 0xd5, - 0x92, 0xe9, 0xa7, 0x59, 0x11, 0xf2, 0x2c, 0xcf, 0xdf, 0x5a, 0xcd, 0xf3, 0xb7, 0x22, 0xc1, 0x3c, - 0x87, 0xeb, 0x10, 0xe6, 0x65, 0xcf, 0x49, 0x4c, 0x6d, 0x45, 0x3a, 0x55, 0x3a, 0x16, 0xaa, 0x15, - 0x8c, 0x2c, 0xf6, 0xa1, 0xeb, 0x24, 0xe0, 0xae, 0x2b, 0x16, 0xbb, 0xca, 0x30, 0xb4, 0xd8, 0xd5, - 0x1e, 0x01, 0x98, 0x78, 0x4f, 0x02, 0x70, 0x55, 0x05, 0x54, 0x18, 0x52, 0x80, 0x4a, 0x0f, 0xb1, - 0xc1, 0xcc, 0x3a, 0x4d, 0x02, 0x76, 0x4d, 0xba, 0xee, 0x79, 0x6c, 0x02, 0x3c, 0x17, 0x06, 0x2d, - 0xd2, 0x1c, 0x6f, 0x49, 0x8c, 0xb3, 0x2e, 0x69, 0xbc, 0x42, 0xde, 0xd8, 0x22, 0x2d, 0x64, 0x22, - 0x9f, 0xc3, 0x82, 0xe2, 0x40, 0x89, 0x91, 0x6e, 0xc8, 0x17, 0x43, 0xc7, 0x23, 0x46, 0xd0, 0x03, - 0x10, 0x0a, 0x73, 0x92, 0x1f, 0x25, 0x70, 0x2d, 0xd9, 0x62, 0xc8, 0x72, 0x08, 0x54, 0x9d, 0x30, - 0x5a, 0x21, 0x92, 0x43, 0x25, 0x30, 0xdf, 0x93, 0x30, 0x35, 0x1c, 0x54, 0x27, 0x86, 0xae, 0x74, - 0xc6, 0x8b, 0x12, 0x88, 0x37, 0xa5, 0xbb, 0x91, 0xc3, 0x15, 0xbb, 0xd2, 0x39, 0xdd, 0xc4, 0x86, - 0x65, 0x9d, 0x23, 0x25, 0x86, 0x78, 0x5f, 0xfa, 0x16, 0xe7, 0x33, 0xd2, 0x02, 0x90, 0x28, 0x80, - 0xe4, 0x26, 0xa9, 0xa7, 0x04, 0xfc, 0x03, 0x25, 0x80, 0x94, 0x65, 0xa1, 0x5a, 0x41, 0xd2, 0x87, - 0xb5, 0x5c, 0x97, 0x4c, 0x60, 0xdf, 0x92, 0xe2, 0x48, 0x97, 0x70, 0xd3, 0xcb, 0xe0, 0xd0, 0x55, - 0xd1, 0x78, 0x68, 0x62, 0xac, 0x0d, 0xc9, 0x55, 0xc9, 0xe5, 0xa3, 0xf9, 0x10, 0x24, 0x80, 0xd5, - 0x3c, 0xa7, 0x4c, 0x0c, 0x72, 0x5b, 0xf2, 0x58, 0x8b, 0x99, 0xc5, 0x9e, 0x5f, 0x02, 0x49, 0xbe, - 0x82, 0x6b, 0x5a, 0xef, 0x4c, 0x8c, 0x18, 0x79, 0x60, 0x56, 0x91, 0xa7, 0x27, 0x0d, 0x57, 0x04, - 0x86, 0xc7, 0x4c, 0xe7, 0xa8, 0x89, 0xa1, 0xee, 0x4a, 0xc7, 0x2c, 0x9f, 0x91, 0x16, 0x80, 0x58, - 0x0d, 0x6d, 0x76, 0x88, 0x27, 0xec, 0x78, 0xfe, 0xb7, 0xd1, 0x16, 0x79, 0xb3, 0xa4, 0x8d, 0xd9, - 0xb9, 0x26, 0xf7, 0xfa, 0xb8, 0xff, 0x55, 0xa5, 0xa2, 0x65, 0xfd, 0x4a, 0xef, 0x26, 0x11, 0x0b, - 0x6a, 0x36, 0xd2, 0x9b, 0x83, 0x56, 0x8b, 0x05, 0x01, 0xc7, 0xab, 0x50, 0x89, 0x66, 0x35, 0x32, - 0x69, 0x25, 0xf4, 0x19, 0x05, 0x92, 0xf0, 0x19, 0x47, 0xe9, 0x90, 0x90, 0xce, 0x3e, 0x8e, 0x70, - 0x7f, 0x32, 0x95, 0x7d, 0xcc, 0xfa, 0x4a, 0x26, 0x4c, 0xc8, 0xa3, 0xc7, 0x4d, 0x6b, 0x3f, 0x1b, - 0xf2, 0x24, 0x06, 0x8c, 0xd6, 0x7b, 0x6d, 0x91, 0x7b, 0xc4, 0x47, 0x4e, 0x39, 0xed, 0x98, 0x23, - 0x82, 0x72, 0xda, 0xe1, 0x3e, 0xe8, 0x79, 0xe8, 0xdb, 0x89, 0x0f, 0x8a, 0x0d, 0xeb, 0x96, 0xe6, - 0x9b, 0x4e, 0x08, 0x94, 0xf1, 0x59, 0xe0, 0xf1, 0x67, 0xeb, 0xd3, 0xcb, 0x82, 0x2d, 0xb8, 0x03, - 0x47, 0x76, 0x18, 0x32, 0x5f, 0x38, 0xdb, 0x55, 0x9a, 0xb4, 0xad, 0x8f, 0x2f, 0xbd, 0xca, 0xda, - 0x41, 0xff, 0xa3, 0x94, 0x1f, 0x73, 0xc9, 0x2e, 0xf7, 0x94, 0xb2, 0xdc, 0x5c, 0x0d, 0x36, 0x76, - 0xe3, 0xe5, 0x16, 0x4d, 0xec, 0x79, 0xe2, 0x9d, 0x3c, 0xb3, 0x7b, 0x4c, 0x1c, 0x87, 0xb8, 0x89, - 0x4b, 0xf4, 0xc4, 0x3b, 0x69, 0xec, 0x72, 0xf7, 0xbb, 0x4c, 0xa3, 0x06, 0xd9, 0x80, 0x99, 0xc8, - 0x5e, 0xdf, 0x63, 0x6e, 0x8b, 0x1d, 0xba, 0xdd, 0x0b, 0xee, 0x47, 0x57, 0xa8, 0x4a, 0x26, 0x1f, - 0xc0, 0x34, 0x65, 0x2e, 0xfb, 0x66, 0xc8, 0x38, 0xce, 0x19, 0x15, 0x2a, 0x66, 0xb7, 0xf3, 0x75, - 0x44, 0xfe, 0xce, 0x7f, 0x9e, 0xcd, 0x43, 0x6a, 0x76, 0x7e, 0x1e, 0xc6, 0x90, 0x21, 0x10, 0x7b, - 0x1f, 0x35, 0x70, 0xb1, 0x12, 0x8d, 0xcd, 0x5f, 0x7b, 0x94, 0x0e, 0x09, 0x78, 0x0a, 0xb2, 0x6e, - 0xb6, 0x6e, 0x43, 0xe6, 0x75, 0x59, 0x4c, 0xeb, 0x8f, 0x25, 0xa8, 0xc4, 0xb4, 0xe1, 0xc2, 0xb7, - 0x45, 0xdc, 0x24, 0x6e, 0x22, 0xe0, 0x53, 0x76, 0x81, 0x13, 0x1b, 0xdd, 0xa8, 0x51, 0xfe, 0x4c, - 0xee, 0x44, 0x92, 0x07, 0x98, 0x67, 0x1f, 0xe5, 0x81, 0x94, 0xe9, 0x4d, 0x5e, 0xca, 0x12, 0x53, - 0x69, 0xd2, 0x4f, 0xd6, 0x61, 0xd2, 0x09, 0xa8, 0xed, 0x76, 0xb8, 0xcf, 0xc4, 0x37, 0xa9, 0x42, - 0xd3, 0x24, 0x72, 0x0b, 0x26, 0x1e, 0x7b, 0xdd, 0x36, 0xf3, 0x03, 0x73, 0x8c, 0x87, 0x7b, 0xa6, - 0x22, 0xb0, 0x57, 0xb6, 0x83, 0xce, 0x3a, 0x8d, 0x7b, 0x91, 0x11, 0x69, 0xc8, 0x38, 0xae, 0x65, - 0x14, 0xbd, 0xd6, 0x97, 0xda, 0x58, 0x03, 0xbe, 0x4a, 0xdd, 0x6d, 0xc4, 0xeb, 0xce, 0x9f, 0xc9, - 0xcf, 0xa1, 0x16, 0xf3, 0x61, 0x30, 0xc6, 0x1c, 0x11, 0x01, 0xa7, 0x48, 0xdb, 0x25, 0x10, 0x12, - 0x93, 0x35, 0xa7, 0xc9, 0xe5, 0x5a, 0x67, 0x30, 0x79, 0x7c, 0xee, 0xbe, 0xdd, 0x8a, 0x52, 0xef, - 0x9b, 0x64, 0x45, 0xf1, 0x99, 0xdc, 0x85, 0x89, 0xc3, 0x7e, 0xc8, 0x43, 0x5e, 0x51, 0x22, 0x7f, - 0x76, 0xb8, 0xa0, 0xa2, 0x83, 0xc6, 0x1c, 0xd6, 0x7f, 0x96, 0x60, 0x42, 0x0c, 0x4e, 0x3e, 0x83, - 0x4a, 0xdd, 0x67, 0x76, 0xc8, 0xb6, 0x43, 0x51, 0x52, 0xb2, 0xbc, 0x19, 0x55, 0xf8, 0x6c, 0xc6, - 0x15, 0x3e, 0xa9, 0xc2, 0x92, 0x0a, 0x7e, 0x0c, 0x7e, 0xf7, 0xdf, 0x6b, 0x25, 0x9a, 0x48, 0x91, - 0x75, 0x28, 0xa3, 0xfd, 0xc5, 0x4f, 0xde, 0xe4, 0xfd, 0xda, 0x26, 0xd6, 0x21, 0x1d, 0x9f, 0xbb, - 0x48, 0xa3, 0xbc, 0x07, 0x5f, 0xe5, 0x45, 0xc0, 0xfc, 0xe3, 0x73, 0x97, 0x4f, 0xae, 0x42, 0xe3, - 0x26, 0xb9, 0x07, 0x55, 0x5c, 0x73, 0x9c, 0x65, 0x60, 0x96, 0xf9, 0xd2, 0x91, 0x38, 0x28, 0x34, - 0x5c, 0x0b, 0x3a, 0x64, 0x92, 0xef, 0xff, 0x98, 0x72, 0xff, 0xb1, 0x58, 0x47, 0x13, 0xa1, 0xd1, - 0xed, 0xdb, 0x3d, 0x98, 0x14, 0x6c, 0xa9, 0x6d, 0x9b, 0x1e, 0x8e, 0xcd, 0x01, 0xd2, 0x2c, 0xd6, - 0x82, 0x36, 0x71, 0x6e, 0xfd, 0x43, 0x09, 0xaa, 0x09, 0x11, 0xd5, 0xe1, 0x33, 0xaf, 0xcd, 0x8e, - 0x2f, 0xfa, 0x4c, 0x0c, 0x97, 0xb4, 0xf1, 0x83, 0x84, 0xcf, 0x8d, 0xb6, 0xb8, 0xa4, 0xa2, 0x45, - 0x56, 0x04, 0x00, 0x17, 0x8a, 0x94, 0xd3, 0x90, 0x80, 0x93, 0x7f, 0x11, 0xb0, 0xb6, 0xd0, 0x4e, - 0xfc, 0x19, 0x69, 0x7b, 0x3e, 0x8b, 0x22, 0x7b, 0x65, 0xca, 0x9f, 0x71, 0xe4, 0xc7, 0x4e, 0x48, - 0xed, 0xd0, 0xf1, 0xb8, 0x02, 0x1a, 0xa1, 0x49, 0xdb, 0x7a, 0xa6, 0x0f, 0x51, 0x91, 0x07, 0x30, - 0x95, 0x10, 0xf9, 0x32, 0x44, 0xe1, 0xd2, 0x24, 0xaa, 0x99, 0x08, 0xc8, 0x6c, 0x56, 0x17, 0x56, - 0x8a, 0xb2, 0xc8, 0xb8, 0xe1, 0x8f, 0x7c, 0x6f, 0xd0, 0x4f, 0x54, 0x74, 0xdc, 0x2c, 0x56, 0xd0, - 0xf1, 0x97, 0x72, 0x54, 0xfe, 0x52, 0x7e, 0x0c, 0xd7, 0x0b, 0x23, 0x2b, 0x72, 0xe9, 0xcc, 0x58, - 0x5c, 0x3a, 0xf3, 0x04, 0xe6, 0xa5, 0x28, 0xc9, 0x8f, 0x98, 0x9c, 0x75, 0x17, 0x16, 0xb4, 0x81, - 0x18, 0xdc, 0x09, 0x6c, 0xc7, 0x47, 0x0b, 0x9f, 0xad, 0x26, 0x2c, 0xe5, 0xa4, 0xb2, 0xc9, 0x2a, - 0x00, 0x86, 0x46, 0x4e, 0xec, 0x80, 0x25, 0x11, 0xe6, 0x14, 0xa5, 0x60, 0x06, 0x1f, 0x81, 0x99, - 0x17, 0xc3, 0x29, 0xf8, 0x78, 0xec, 0x41, 0x85, 0xef, 0xdc, 0x53, 0x76, 0x81, 0x53, 0x3d, 0xb2, - 0xc3, 0xb3, 0x78, 0xaa, 0xf8, 0x8c, 0x47, 0xf2, 0xf0, 0xf4, 0x34, 0x60, 0x51, 0x41, 0xdd, 0x28, - 0x15, 0x2d, 0x32, 0x0d, 0x23, 0xcd, 0x6f, 0xc5, 0x17, 0x63, 0xa4, 0xf9, 0xad, 0xf5, 0x40, 0x1c, - 0x51, 0xae, 0xbd, 0x6f, 0x43, 0xf9, 0x35, 0x6a, 0xf4, 0x92, 0xa4, 0xea, 0xe2, 0x7e, 0x61, 0x30, - 0x72, 0x16, 0xeb, 0x18, 0x66, 0xc4, 0xab, 0x27, 0xd3, 0x98, 0x87, 0xb1, 0x86, 0xdb, 0x66, 0xe7, - 0xf1, 0x66, 0xf1, 0x06, 0xc6, 0xec, 0x63, 0x0e, 0xa1, 0x48, 0x54, 0x5c, 0x9a, 0x30, 0x58, 0xaf, - 0xb4, 0xe9, 0x7f, 0xac, 0xf9, 0x51, 0x06, 0x13, 0x53, 0x4c, 0xe2, 0x7b, 0x72, 0x2f, 0x55, 0xd9, - 0xad, 0x43, 0x98, 0x8d, 0x17, 0x35, 0x41, 0xcf, 0x99, 0xb0, 0x01, 0xa3, 0x8f, 0x9d, 0xb8, 0x0e, - 0x11, 0x1f, 0x71, 0x7d, 0x91, 0x5f, 0x58, 0x5a, 0xfc, 0xd9, 0xfa, 0x52, 0x1f, 0x4b, 0xc3, 0xa0, - 0x4a, 0x66, 0x20, 0x31, 0x59, 0x33, 0x99, 0xac, 0xd2, 0x4f, 0xb3, 0x22, 0x16, 0xd5, 0x96, 0x2e, - 0x90, 0x5f, 0x43, 0x2d, 0xa1, 0x45, 0xcb, 0x10, 0x05, 0xed, 0x87, 0x65, 0xa0, 0xe9, 0x6e, 0x2a, - 0x31, 0x8b, 0x7b, 0x93, 0x8d, 0xba, 0xdd, 0x87, 0x6a, 0x42, 0x4c, 0xaa, 0x0f, 0x35, 0x88, 0x74, - 0xc8, 0x66, 0x35, 0x61, 0xf2, 0xc8, 0x67, 0x7d, 0xdb, 0x67, 0xcd, 0xb0, 0xc7, 0x97, 0x88, 0x5b, - 0x60, 0xe2, 0x08, 0xe2, 0x33, 0x2e, 0x64, 0xf3, 0xf9, 0x7e, 0x6c, 0xb3, 0x36, 0x9f, 0xef, 0xe3, - 0x25, 0x39, 0xb2, 0x7d, 0xbb, 0x87, 0xea, 0x2f, 0x10, 0xcb, 0x99, 0xa2, 0x58, 0x67, 0x60, 0x88, - 0x78, 0xd8, 0x31, 0xeb, 0xf5, 0xa3, 0xa0, 0xe5, 0x32, 0x54, 0xe2, 0x6b, 0x14, 0xeb, 0xdd, 0xb8, - 0x8d, 0x1b, 0xb8, 0xdd, 0x75, 0xec, 0xc4, 0x36, 0xe2, 0x0d, 0x34, 0xf7, 0x8f, 0xce, 0x2e, 0x02, - 0xa7, 0x65, 0x77, 0x53, 0x56, 0xa1, 0x44, 0xb3, 0xfe, 0xaf, 0x94, 0x57, 0x75, 0x81, 0x37, 0x07, - 0x49, 0x89, 0x12, 0x11, 0x2d, 0xf2, 0x51, 0x52, 0x4a, 0x19, 0x65, 0x88, 0x56, 0xf4, 0x01, 0xc3, - 0x88, 0x27, 0x2e, 0xb4, 0x24, 0x9f, 0xc1, 0xb5, 0xe4, 0x5d, 0x22, 0x4e, 0xc7, 0x73, 0x9b, 0x83, - 0x7e, 0xdf, 0xf3, 0x43, 0xa1, 0xfb, 0x2b, 0xb4, 0x88, 0x85, 0xec, 0xc1, 0xea, 0xbe, 0x1d, 0x84, - 0x0d, 0x37, 0x60, 0x7e, 0xd8, 0xd8, 0xd5, 0x80, 0x44, 0xe6, 0xeb, 0x25, 0x5c, 0x4f, 0xca, 0x95, - 0x51, 0xa3, 0x6c, 0xfd, 0x7b, 0x25, 0x37, 0x10, 0x8a, 0xba, 0x61, 0x77, 0x47, 0x2c, 0xf2, 0xc8, - 0xee, 0x0e, 0x79, 0x00, 0xb5, 0xd4, 0x1e, 0x07, 0xe6, 0x88, 0xf4, 0x19, 0x4f, 0x75, 0x51, 0x89, - 0x8f, 0xdc, 0x01, 0x03, 0xe7, 0xb2, 0x7d, 0x7a, 0xca, 0x5a, 0x21, 0x6b, 0x73, 0x93, 0x26, 0xd2, - 0x38, 0x19, 0x3a, 0xf9, 0x14, 0xa6, 0xd1, 0x64, 0xd8, 0x67, 0x6f, 0x58, 0x37, 0x6d, 0x2c, 0xcc, - 0xc7, 0xe1, 0xed, 0x74, 0x27, 0x55, 0x78, 0xc9, 0x2e, 0x5c, 0x97, 0x19, 0x58, 0x97, 0xd9, 0x01, - 0x53, 0x97, 0xa6, 0x98, 0x89, 0xec, 0xc1, 0x0c, 0x32, 0xec, 0xb2, 0x53, 0xc7, 0x65, 0xed, 0x97, - 0x76, 0x62, 0x45, 0x2a, 0x5b, 0x2c, 0x33, 0x51, 0x55, 0x88, 0xfc, 0x02, 0x96, 0x14, 0xd2, 0xc3, - 0x73, 0x31, 0x8f, 0x09, 0x3e, 0x8f, 0xbc, 0x6e, 0x9c, 0x41, 0xf3, 0x22, 0x08, 0x59, 0xef, 0xa5, - 0xed, 0x3b, 0x78, 0x0e, 0x02, 0xb3, 0xa2, 0x9b, 0x81, 0xcc, 0x44, 0x55, 0x21, 0x9c, 0x81, 0x42, - 0x4a, 0x66, 0x50, 0x8d, 0x66, 0x90, 0xd3, 0x4d, 0x3e, 0x85, 0xab, 0xca, 0xe4, 0x30, 0x26, 0x6b, - 0x5f, 0x20, 0x17, 0x4f, 0x78, 0x55, 0x68, 0x3e, 0x03, 0x4a, 0x2b, 0xc0, 0x29, 0xe9, 0xc9, 0x48, - 0x3a, 0x97, 0x81, 0x3c, 0x86, 0x35, 0xa5, 0xb3, 0xe9, 0xda, 0xfd, 0xe0, 0xcc, 0x0b, 0x8f, 0x3d, - 0x6f, 0xdf, 0xf6, 0x3b, 0x8c, 0x67, 0xbc, 0x2a, 0xf4, 0x32, 0x36, 0x44, 0x52, 0x26, 0x99, 0x41, - 0x9a, 0x8a, 0x90, 0x2e, 0x61, 0xc3, 0x7b, 0x2b, 0xce, 0x74, 0x1b, 0x0f, 0xf5, 0xbe, 0xe7, 0x76, - 0x50, 0xed, 0xd4, 0xcf, 0x58, 0xeb, 0x35, 0x6b, 0xf3, 0x6c, 0x57, 0x85, 0x16, 0xb1, 0xa0, 0xf1, - 0xb7, 0xe7, 0x0d, 0xdc, 0xe8, 0xf8, 0xcf, 0x44, 0x29, 0xe7, 0x84, 0x40, 0x3e, 0x01, 0x48, 0x2e, - 0x7d, 0x60, 0x1a, 0xeb, 0xa3, 0xa9, 0xdc, 0xab, 0xaa, 0x03, 0x69, 0x8a, 0x95, 0x3c, 0x80, 0xc5, - 0xa4, 0x85, 0xea, 0x98, 0x25, 0x3b, 0x3c, 0xcb, 0xe7, 0x94, 0xd3, 0x8b, 0x5a, 0x31, 0xad, 0x20, - 0x78, 0x32, 0xaa, 0x4c, 0x25, 0x1a, 0xb9, 0x0f, 0xf3, 0xe9, 0x76, 0x82, 0x3c, 0xc7, 0x91, 0xb5, - 0x7d, 0xd6, 0x3f, 0x8f, 0xeb, 0x0b, 0xcd, 0x72, 0xf5, 0x68, 0xa4, 0x65, 0x46, 0x12, 0x2d, 0xb3, - 0x0e, 0x93, 0x4d, 0x16, 0xbe, 0xb4, 0xfd, 0x48, 0xc9, 0x8c, 0xf2, 0x50, 0x43, 0x9a, 0x94, 0xd1, - 0x43, 0xe5, 0x1f, 0xa1, 0x87, 0xc6, 0xde, 0x5a, 0x0f, 0x8d, 0xbf, 0x83, 0x1e, 0xd2, 0x68, 0x90, - 0x89, 0x9f, 0x58, 0x83, 0x54, 0xde, 0x59, 0x83, 0x54, 0x7f, 0x62, 0x0d, 0x02, 0x3f, 0x42, 0x83, - 0x4c, 0xfe, 0x28, 0x0d, 0x52, 0xbb, 0x4c, 0x83, 0x48, 0x77, 0x6d, 0xaa, 0xf8, 0xae, 0x4d, 0xbf, - 0xfd, 0x5d, 0x53, 0xef, 0xcc, 0xcc, 0x3b, 0xdc, 0x19, 0xa3, 0xe0, 0xce, 0xfc, 0x6f, 0x29, 0xc9, - 0x19, 0xca, 0x2b, 0xa2, 0xb5, 0xa3, 0xd6, 0x61, 0xec, 0xa5, 0xdd, 0x1d, 0x30, 0x61, 0x3e, 0xc3, - 0x26, 0xff, 0x89, 0xcf, 0xc3, 0xf3, 0xbe, 0x4f, 0xa3, 0x0e, 0x6e, 0x69, 0x7d, 0xdd, 0x15, 0x86, - 0x0e, 0x3e, 0x72, 0xd3, 0x36, 0xd8, 0x71, 0x5c, 0x61, 0x60, 0x44, 0x0d, 0xbc, 0x10, 0xe2, 0x82, - 0x70, 0xa3, 0xeb, 0x29, 0xfa, 0x37, 0x91, 0xa7, 0x9d, 0xa1, 0x93, 0x55, 0x28, 0x73, 0xb7, 0x75, - 0x3c, 0x3d, 0x28, 0x52, 0x28, 0xa7, 0x93, 0x7b, 0x30, 0x47, 0x07, 0x6e, 0xe8, 0xf4, 0x58, 0x33, - 0xf4, 0x1d, 0xb7, 0xb3, 0xeb, 0xf5, 0x6c, 0xc7, 0xe5, 0x1f, 0xba, 0x29, 0xaa, 0xeb, 0xb2, 0x9e, - 0xc3, 0x94, 0x74, 0x6d, 0xb4, 0x2f, 0x9b, 0x78, 0x7c, 0x91, 0x97, 0x14, 0x35, 0xf8, 0x2f, 0x87, - 0xce, 0xdd, 0xc6, 0x6e, 0xa4, 0x1e, 0x6a, 0x54, 0xb4, 0xac, 0xbf, 0xc8, 0xc9, 0xbd, 0x16, 0x38, - 0x4e, 0xbf, 0x86, 0xb5, 0x4b, 0xea, 0x53, 0xd3, 0xbe, 0x5a, 0x49, 0xf6, 0xd5, 0x2c, 0x58, 0xbf, - 0x2c, 0xe1, 0x6a, 0x6d, 0xf0, 0x32, 0x61, 0x4d, 0x81, 0x29, 0x6a, 0xbe, 0xfa, 0xb3, 0xd8, 0xbe, - 0xaa, 0x3f, 0x13, 0xbf, 0x19, 0xd1, 0xa5, 0x46, 0x73, 0x7e, 0x33, 0xf2, 0xa1, 0xb6, 0x14, 0x35, - 0x4f, 0xd3, 0x5a, 0x47, 0xfa, 0x44, 0x6a, 0xfe, 0xe2, 0xa0, 0x81, 0x8e, 0xc1, 0xf9, 0x68, 0xdb, - 0xf8, 0x16, 0xd4, 0x68, 0x8a, 0x62, 0x6d, 0x69, 0xaa, 0x57, 0xd1, 0x42, 0x8f, 0x49, 0xf1, 0x6f, - 0x6b, 0xe2, 0xb6, 0x75, 0x4f, 0x97, 0x7a, 0x2d, 0x94, 0xf8, 0xa5, 0xa6, 0xa4, 0x95, 0xdc, 0x84, - 0xa9, 0x98, 0xb4, 0x73, 0x11, 0xb2, 0x40, 0x2c, 0x8b, 0x4c, 0xb4, 0x7e, 0xa5, 0x4b, 0xcb, 0xbe, - 0xa5, 0xec, 0x59, 0x6e, 0xed, 0x2b, 0xd9, 0x12, 0x37, 0xa1, 0xc4, 0xcd, 0xfe, 0x6b, 0x39, 0x09, - 0xd2, 0xd4, 0xd5, 0x88, 0xc3, 0x3e, 0x4d, 0xe7, 0x5b, 0x26, 0xdc, 0xef, 0x21, 0xc1, 0x3a, 0xcf, - 0xcf, 0xf5, 0xca, 0x92, 0x25, 0x45, 0x12, 0xdf, 0x84, 0x37, 0xea, 0x76, 0xdf, 0x6e, 0x39, 0xe1, - 0x85, 0xc0, 0x96, 0x89, 0xb8, 0xbb, 0x07, 0x2c, 0x08, 0xec, 0x4e, 0x12, 0x0f, 0x17, 0x4d, 0xeb, - 0xb0, 0xb8, 0xfe, 0xf6, 0x9d, 0x5f, 0xd4, 0xfa, 0xeb, 0x4b, 0x72, 0xca, 0x7f, 0xe6, 0xf7, 0xf9, - 0x48, 0x5f, 0xe0, 0x5b, 0x3c, 0xaa, 0xf5, 0x97, 0x39, 0x69, 0xe9, 0xec, 0x74, 0x4a, 0x9a, 0xe9, - 0x58, 0xff, 0x5f, 0xba, 0xa4, 0xb4, 0xf3, 0x92, 0x44, 0x06, 0x9f, 0x5c, 0x68, 0x77, 0xbd, 0x4e, - 0x12, 0x0a, 0x1a, 0x12, 0xb0, 0x17, 0xd5, 0x20, 0x4f, 0xc9, 0xc6, 0x11, 0xc3, 0x84, 0x80, 0x5a, - 0x21, 0x2a, 0x01, 0x2a, 0x47, 0xfe, 0x2e, 0x6f, 0xe0, 0xa5, 0x8d, 0xcd, 0x57, 0x11, 0x39, 0x1d, - 0xa5, 0x29, 0x0a, 0x7e, 0xa1, 0xe2, 0x17, 0xde, 0xf7, 0x5a, 0xdc, 0x2b, 0x7c, 0x6c, 0x07, 0x67, - 0x5c, 0xb3, 0x57, 0xa9, 0xb6, 0x0f, 0x6f, 0x68, 0x54, 0x40, 0xd6, 0xd8, 0xe5, 0x2a, 0xbd, 0x4a, - 0x93, 0xb6, 0xf5, 0xf8, 0xb2, 0xac, 0x67, 0x94, 0x38, 0xc1, 0xb8, 0x5e, 0xfb, 0xa1, 0x1b, 0xfa, - 0x4e, 0x72, 0xe7, 0x14, 0xaa, 0xb5, 0xa9, 0x2b, 0xa5, 0xc6, 0x0d, 0x17, 0x14, 0xa1, 0x1c, 0xe2, - 0xa6, 0xb5, 0xa5, 0xcd, 0xfb, 0x17, 0x08, 0xec, 0xeb, 0x4a, 0xab, 0x51, 0x5f, 0x8a, 0x5a, 0x4f, - 0xf1, 0xeb, 0xbe, 0xa8, 0x95, 0x84, 0x27, 0x18, 0x4f, 0x24, 0x44, 0x16, 0x6a, 0x8a, 0x62, 0xdd, - 0xd6, 0x96, 0x08, 0x68, 0x13, 0x2b, 0x77, 0xf2, 0x0a, 0xb1, 0xb3, 0x19, 0x1e, 0xeb, 0xc3, 0xdc, - 0x5a, 0x01, 0x2d, 0x74, 0xaf, 0xa0, 0x0c, 0x1b, 0x93, 0x5b, 0xe2, 0x47, 0xa1, 0x71, 0x8f, 0xf8, - 0x84, 0xa9, 0x64, 0xdc, 0xa3, 0x57, 0xbe, 0x13, 0x0e, 0x21, 0xc4, 0x61, 0x54, 0xa8, 0x96, 0x5b, - 0x54, 0x69, 0xf0, 0x67, 0x18, 0xef, 0xa5, 0xbe, 0xec, 0x80, 0xfc, 0x15, 0xd4, 0xd2, 0xf4, 0xb7, - 0xf8, 0x95, 0xac, 0xc4, 0x6f, 0xfd, 0x4d, 0xa9, 0xa8, 0x40, 0xfa, 0x92, 0x4b, 0x6b, 0x41, 0x0d, - 0xbf, 0xa9, 0x8c, 0xc7, 0x74, 0x92, 0x7b, 0x2b, 0xd1, 0xd0, 0xb8, 0x12, 0x71, 0xed, 0x87, 0xe7, - 0xad, 0xee, 0x20, 0x70, 0xde, 0x30, 0x11, 0xef, 0xce, 0xd0, 0xad, 0x4f, 0x0a, 0x73, 0xf8, 0x05, - 0xd6, 0xcb, 0x3f, 0x0d, 0x2d, 0x47, 0xd9, 0x1a, 0xfe, 0x81, 0x96, 0xe3, 0x06, 0xcc, 0x3c, 0x63, - 0xe7, 0xe1, 0xb1, 0x6f, 0xbb, 0x81, 0x1d, 0x45, 0xb7, 0xa2, 0x44, 0x8e, 0x4a, 0x26, 0x9b, 0x50, - 0x13, 0x46, 0x5d, 0x04, 0x59, 0xce, 0x40, 0x4a, 0xfd, 0xd6, 0xbf, 0x95, 0x0a, 0xea, 0xc4, 0x73, - 0x9d, 0xc3, 0x15, 0xa8, 0xa2, 0x8d, 0xd8, 0x70, 0xfb, 0x83, 0x50, 0xdc, 0xc0, 0x21, 0x41, 0x8a, - 0x05, 0x8e, 0x2a, 0xb1, 0x40, 0x0b, 0x6a, 0x52, 0x71, 0x42, 0x99, 0x1b, 0x2f, 0x12, 0x0d, 0xd7, - 0xa8, 0x69, 0x77, 0xa3, 0x9f, 0x9e, 0xd6, 0x28, 0x7f, 0xe6, 0x5a, 0x9f, 0xef, 0xc1, 0x76, 0xbb, - 0xed, 0xe3, 0x8a, 0x47, 0x6a, 0x51, 0x26, 0x5a, 0xff, 0x52, 0x2a, 0xaa, 0x84, 0xf8, 0xe1, 0x16, - 0x15, 0x2a, 0x67, 0x6c, 0x31, 0x37, 0x74, 0x22, 0xf5, 0xbb, 0x67, 0x3b, 0x5d, 0xd6, 0x16, 0xbb, - 0xa0, 0xed, 0x8b, 0x32, 0xd8, 0x7c, 0x1d, 0x29, 0xfb, 0x8a, 0xbb, 0xb0, 0xc2, 0xcc, 0x57, 0xc9, - 0x77, 0xfe, 0x75, 0x3c, 0x55, 0xd9, 0x4e, 0xaa, 0xe2, 0xf7, 0xfa, 0xc6, 0x15, 0x32, 0x07, 0x33, - 0x4a, 0xb1, 0xb9, 0x51, 0x22, 0x06, 0xd4, 0xd2, 0xf5, 0x13, 0xc6, 0x08, 0xa9, 0x41, 0x25, 0x2e, - 0x65, 0x30, 0x46, 0xc9, 0x14, 0x54, 0x93, 0xb4, 0xb2, 0x51, 0x26, 0x33, 0x30, 0x99, 0xca, 0xa5, - 0x1a, 0x63, 0x64, 0x1a, 0x60, 0x98, 0xa3, 0x33, 0xc6, 0x11, 0x2f, 0x9d, 0x9c, 0x32, 0x26, 0x90, - 0x63, 0x58, 0xd3, 0x6c, 0x54, 0x10, 0x31, 0x29, 0x55, 0x36, 0xaa, 0x64, 0x51, 0x57, 0xac, 0x6c, - 0x00, 0xd2, 0xb3, 0x45, 0xc3, 0xc6, 0x24, 0x21, 0x6a, 0xd9, 0xb0, 0x51, 0x23, 0x93, 0x49, 0x0d, - 0xb0, 0x31, 0x45, 0xae, 0xe6, 0x94, 0xf7, 0x1a, 0xd3, 0x64, 0x56, 0xa9, 0xce, 0x35, 0x66, 0xc8, - 0x7c, 0xb6, 0xd8, 0xd6, 0x30, 0xd2, 0x6f, 0x81, 0x87, 0xcd, 0x98, 0x15, 0x94, 0x24, 0x16, 0x6e, - 0x10, 0x5c, 0x4e, 0xa5, 0xf0, 0xd4, 0x98, 0x43, 0xa2, 0x12, 0x69, 0x35, 0xe6, 0x71, 0x58, 0xc9, - 0x63, 0x31, 0x16, 0xc8, 0x4a, 0x7e, 0xb1, 0xa7, 0xb1, 0x88, 0x4b, 0x94, 0x54, 0x74, 0x18, 0x4b, - 0x62, 0xa4, 0xb4, 0xcf, 0x60, 0x98, 0x38, 0xa1, 0xb4, 0xa1, 0x6f, 0x5c, 0xe5, 0x5b, 0x71, 0x78, - 0xb0, 0xfd, 0xf9, 0x11, 0x3d, 0xac, 0x37, 0x8d, 0x65, 0xd1, 0x7e, 0x78, 0xb0, 0xdf, 0x38, 0x68, - 0x1c, 0x1b, 0xd7, 0xf0, 0x55, 0x55, 0xcb, 0xcd, 0x58, 0xc1, 0xe5, 0xd2, 0xda, 0x73, 0xc6, 0x75, - 0x3e, 0xef, 0xb4, 0xd5, 0x64, 0xac, 0xf2, 0xfd, 0x3f, 0x4c, 0xbe, 0xc6, 0xc6, 0x1a, 0x12, 0x52, - 0xdf, 0x47, 0x63, 0x1d, 0x27, 0xab, 0x7c, 0xd9, 0x8c, 0x1b, 0xb8, 0x99, 0xd9, 0x0f, 0x8a, 0x61, - 0xe1, 0x4b, 0xa4, 0x15, 0xb6, 0xf1, 0x1e, 0xb9, 0x06, 0x4b, 0x39, 0x55, 0x26, 0xc6, 0x4d, 0xb2, - 0x00, 0xb3, 0x99, 0xa2, 0x0b, 0xe3, 0x7d, 0xb2, 0x0c, 0x8b, 0x7a, 0xe3, 0xc4, 0xf8, 0x80, 0x2c, - 0xc1, 0x9c, 0x46, 0xeb, 0x1a, 0xb7, 0x70, 0x4a, 0xd9, 0xcb, 0x6d, 0x6c, 0xdc, 0xf9, 0xdb, 0x12, - 0x2c, 0x28, 0x5b, 0x28, 0xc2, 0xfa, 0x57, 0x33, 0x1d, 0x91, 0x73, 0x6f, 0x5c, 0x21, 0x77, 0xe1, - 0x96, 0xd2, 0xd5, 0x7c, 0xed, 0xf4, 0x75, 0x11, 0x68, 0xa3, 0x44, 0x3e, 0x84, 0xdb, 0x2a, 0x8e, - 0x8b, 0x8b, 0xa5, 0x65, 0x1f, 0xb9, 0xf3, 0x33, 0x98, 0xd7, 0x99, 0xe3, 0x04, 0xd0, 0xa2, 0xe9, - 0x79, 0xfc, 0x6a, 0x57, 0xa0, 0xbc, 0xeb, 0x04, 0xaf, 0x8d, 0xd2, 0xce, 0xfe, 0xef, 0xbf, 0x5b, - 0x2d, 0xfd, 0xe1, 0xbb, 0xd5, 0xd2, 0xff, 0x7c, 0xb7, 0x7a, 0xe5, 0x77, 0xdf, 0xaf, 0x5e, 0xf9, - 0xfb, 0xef, 0x57, 0x4b, 0x7f, 0xf8, 0x7e, 0xf5, 0xca, 0x1f, 0xbf, 0x5f, 0xbd, 0xf2, 0xc5, 0x66, - 0xea, 0xbf, 0x83, 0xf4, 0xec, 0xd0, 0x77, 0xce, 0x3d, 0xdf, 0xe9, 0x38, 0x6e, 0xdc, 0x70, 0xd9, - 0x56, 0xff, 0x75, 0x67, 0xab, 0x7f, 0xb2, 0xc5, 0xfd, 0x80, 0x93, 0x71, 0x5e, 0x35, 0xf0, 0xf3, - 0x3f, 0x0d, 0x00, 0xe0, 0x63, 0x7e, 0xac, 0xbd, 0x44, 0x00, 0x00, + // 5110 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x5c, 0xdd, 0x6e, 0x1c, 0x47, + 0x76, 0xd6, 0x88, 0x43, 0x72, 0xe6, 0x70, 0x48, 0xb6, 0x8a, 0x7f, 0x2d, 0x8a, 0x22, 0xa9, 0xb6, + 0x6c, 0x51, 0x92, 0x4d, 0x2a, 0x5a, 0x5b, 0xf6, 0x7a, 0x9d, 0x85, 0xc9, 0x21, 0x29, 0x8d, 0x45, + 0x8a, 0x54, 0x0d, 0x25, 0x79, 0xbd, 0x80, 0x81, 0xe6, 0x4c, 0x71, 0xa6, 0xcd, 0x9e, 0xee, 0x71, + 0x77, 0x8f, 0x34, 0x34, 0x90, 0x17, 0xc8, 0x45, 0xb0, 0x8f, 0x90, 0x5c, 0xe5, 0x3a, 0x40, 0x1e, + 0x62, 0x81, 0x00, 0xc1, 0x5e, 0x2c, 0x90, 0xbd, 0x4a, 0x16, 0xf6, 0x23, 0x04, 0xc8, 0x55, 0x82, + 0x2c, 0xaa, 0xba, 0xaa, 0xa7, 0xab, 0xba, 0xba, 0xe9, 0xbf, 0xbd, 0x21, 0xa6, 0x4e, 0x9d, 0xf3, + 0x55, 0x75, 0xfd, 0x9c, 0x3e, 0x5f, 0xd5, 0x69, 0xc2, 0xd4, 0xd7, 0x03, 0x12, 0x5c, 0x6c, 0xf6, + 0x03, 0x3f, 0xf2, 0xd1, 0x38, 0x2b, 0x2c, 0xd7, 0xc2, 0xc8, 0x8e, 0x06, 0x61, 0x2c, 0x5c, 0x06, + 0xd7, 0x6f, 0x9d, 0xf3, 0xdf, 0xd5, 0x68, 0xe8, 0xf1, 0x9f, 0xb3, 0x91, 0xd3, 0x23, 0x61, 0x64, + 0xf7, 0xfa, 0x42, 0x40, 0xad, 0x42, 0xc7, 0x3b, 0xf3, 0x85, 0x61, 0xdf, 0xb5, 0x85, 0xf6, 0x7b, + 0x1d, 0x27, 0xea, 0x0e, 0x4e, 0x37, 0x5b, 0x7e, 0x6f, 0xab, 0xe3, 0x77, 0xfc, 0x2d, 0x26, 0x3e, + 0x1d, 0x9c, 0xb1, 0x12, 0x2b, 0xb0, 0x5f, 0x5c, 0x7d, 0xad, 0xe3, 0xfb, 0x1d, 0x97, 0x8c, 0xb4, + 0x94, 0xc6, 0xac, 0xdb, 0x50, 0x7b, 0x4e, 0xfb, 0x8a, 0xc9, 0xd7, 0x03, 0x12, 0x46, 0x68, 0x1e, + 0xc6, 0x59, 0xd9, 0x2c, 0xad, 0x97, 0x36, 0xaa, 0x38, 0x2e, 0x58, 0xcf, 0x60, 0xb1, 0xd9, 0xf5, + 0xdf, 0x1c, 0x07, 0x7e, 0x8b, 0x84, 0xe1, 0x81, 0x13, 0x46, 0x42, 0x7f, 0x11, 0x26, 0x4e, 0x88, + 0x67, 0x7b, 0x11, 0x37, 0xe0, 0x25, 0xb4, 0x02, 0xd5, 0xe6, 0x45, 0xc8, 0xab, 0xae, 0xae, 0x97, + 0x36, 0x2a, 0x78, 0x24, 0xb0, 0x5e, 0xc1, 0xb5, 0xe6, 0x85, 0xd7, 0xaa, 0xfb, 0xbd, 0x9e, 0x93, + 0x40, 0xed, 0xc0, 0xcc, 0x81, 0x1d, 0x91, 0x30, 0x8a, 0xc5, 0x27, 0x4d, 0x06, 0x39, 0xf5, 0x70, + 0x7e, 0x73, 0xd4, 0xe9, 0x13, 0xf1, 0x6b, 0xa7, 0xfc, 0xfb, 0xff, 0x5c, 0xbb, 0x82, 0x15, 0x0b, + 0xeb, 0x0b, 0x40, 0x69, 0xe0, 0xb0, 0xef, 0x7b, 0x21, 0x41, 0xbb, 0x30, 0x5b, 0x1f, 0x04, 0x01, + 0xf1, 0x7e, 0x08, 0xb4, 0x6a, 0x62, 0x21, 0x30, 0x1e, 0x93, 0x48, 0xea, 0xb3, 0xf5, 0x1b, 0xb8, + 0x96, 0x92, 0xfd, 0xac, 0xcd, 0x6d, 0xc1, 0x42, 0xdd, 0x0f, 0xc8, 0xee, 0xa0, 0xd7, 0xaf, 0xfb, + 0xde, 0x99, 0xd3, 0x49, 0x0d, 0xf9, 0x76, 0x2b, 0x72, 0x7c, 0x4f, 0x0c, 0x79, 0x5c, 0xb2, 0x4c, + 0x58, 0x54, 0x0d, 0xe2, 0x0e, 0x59, 0x37, 0xe0, 0xfa, 0x63, 0x12, 0x1d, 0xd3, 0x09, 0x6f, 0xf9, + 0xee, 0x4b, 0x12, 0x84, 0x8e, 0xef, 0x89, 0x47, 0x78, 0x04, 0xcb, 0xba, 0x4a, 0xfe, 0x2c, 0x26, + 0x4c, 0x72, 0x11, 0x6b, 0x6d, 0x0c, 0x8b, 0xa2, 0xf5, 0x01, 0x5c, 0x6f, 0xe6, 0x81, 0x16, 0x98, + 0x3d, 0x82, 0xe5, 0xe6, 0x8f, 0x69, 0xee, 0x5d, 0x98, 0xc1, 0x03, 0xef, 0xc4, 0x0e, 0xcf, 0x45, + 0x1b, 0xcb, 0x50, 0xa1, 0xc5, 0xba, 0xdf, 0x26, 0x4c, 0x79, 0x1c, 0x27, 0x65, 0xeb, 0x2e, 0xcc, + 0x26, 0xda, 0x1c, 0x7a, 0x11, 0x26, 0x30, 0x09, 0x07, 0x6e, 0xb2, 0x52, 0xe3, 0x12, 0x1d, 0x36, + 0xfa, 0xfc, 0x4e, 0x9f, 0xb8, 0x8e, 0x47, 0x1a, 0xde, 0x99, 0x2f, 0x46, 0x66, 0x0b, 0x96, 0x32, + 0x35, 0x1c, 0x6c, 0x1e, 0xc6, 0xeb, 0xfe, 0x80, 0xaf, 0xfa, 0x31, 0x1c, 0x17, 0xac, 0xff, 0x5d, + 0x86, 0x49, 0xd1, 0xbb, 0x15, 0xa8, 0xf2, 0x9f, 0x8d, 0x5d, 0xa6, 0x55, 0xc6, 0x23, 0x01, 0xda, + 0x84, 0x6a, 0xbd, 0xd7, 0x3e, 0x24, 0x51, 0xd7, 0x6f, 0xb3, 0xed, 0x31, 0xf3, 0xd0, 0xd8, 0x8c, + 0x3d, 0x48, 0x22, 0xc7, 0x23, 0x15, 0xf4, 0xa1, 0xbc, 0x4d, 0xcd, 0x31, 0xb6, 0x9e, 0xe6, 0xb8, + 0x49, 0xba, 0x0a, 0xcb, 0xfb, 0xf9, 0x45, 0xde, 0xce, 0x35, 0xcb, 0x0c, 0xe2, 0x26, 0x87, 0xd0, + 0x2b, 0xe1, 0xbc, 0x6d, 0x7f, 0x00, 0x73, 0xdb, 0x6e, 0x44, 0x82, 0xed, 0x56, 0x8b, 0x3e, 0xb9, + 0xc0, 0x1c, 0x67, 0x98, 0xcb, 0x1c, 0x53, 0xa3, 0x81, 0x75, 0x66, 0xe8, 0x53, 0x98, 0x7d, 0xea, + 0xb8, 0x6e, 0xdd, 0xf7, 0xc4, 0x02, 0x32, 0x27, 0x18, 0xd2, 0x22, 0x47, 0x52, 0x6a, 0xb1, 0xaa, + 0x8e, 0xea, 0x60, 0x9c, 0x04, 0x76, 0x8b, 0x34, 0xfb, 0x76, 0x02, 0x31, 0xc9, 0x20, 0x96, 0x38, + 0x84, 0x5a, 0x8d, 0x33, 0x06, 0xa8, 0x01, 0xe8, 0x31, 0x89, 0x0e, 0xfc, 0xd6, 0x79, 0x6a, 0x15, + 0x98, 0x15, 0x06, 0x73, 0x9d, 0xc3, 0x64, 0x15, 0xb0, 0xc6, 0x08, 0xed, 0x33, 0xbf, 0x70, 0x32, + 0xf4, 0xd2, 0x48, 0x55, 0x86, 0x64, 0x8e, 0x90, 0xe4, 0x7a, 0x9c, 0x35, 0xa1, 0xe3, 0x4c, 0xfd, + 0x8b, 0xdd, 0xea, 0xa6, 0x57, 0xa6, 0x09, 0xd2, 0x38, 0x6b, 0x34, 0xb0, 0xce, 0x0c, 0x7d, 0x04, + 0xd0, 0xbc, 0x68, 0x79, 0xb1, 0x8b, 0x31, 0xa7, 0xa4, 0xee, 0x64, 0xfc, 0x31, 0x4e, 0xe9, 0xa2, + 0x0f, 0xa0, 0x9a, 0xf8, 0x39, 0xb3, 0x26, 0x0d, 0xac, 0xea, 0x13, 0xf1, 0x48, 0x13, 0x1d, 0xb3, + 0x11, 0x55, 0x36, 0xbb, 0x39, 0xcd, 0xec, 0xd7, 0x47, 0xf6, 0x7a, 0x27, 0x82, 0x35, 0xb6, 0x14, + 0x31, 0xeb, 0x3e, 0xcc, 0x19, 0x09, 0xb1, 0x99, 0x8f, 0x98, 0xad, 0x42, 0xbb, 0x30, 0x23, 0xbb, + 0x4d, 0x73, 0x96, 0xa1, 0xad, 0x88, 0xfd, 0xa8, 0x73, 0xc2, 0x58, 0xb1, 0x41, 0x5b, 0x30, 0xc9, + 0x1d, 0x8e, 0x69, 0x30, 0xf3, 0x05, 0x6e, 0x2e, 0x3b, 0x2d, 0x2c, 0xb4, 0xd0, 0x6f, 0x60, 0x01, + 0x93, 0x9e, 0xff, 0x9a, 0xd0, 0xbf, 0x11, 0xa1, 0x0b, 0xe8, 0xc4, 0x3e, 0x75, 0x89, 0x79, 0x8d, + 0x99, 0xbf, 0x25, 0xcc, 0x75, 0x3a, 0x02, 0x4c, 0x8f, 0x80, 0xb6, 0x61, 0x9a, 0x2e, 0x49, 0xf6, + 0x66, 0xdc, 0x71, 0xbc, 0xb6, 0x89, 0x18, 0xe4, 0x8d, 0xd4, 0x12, 0x4e, 0xea, 0x04, 0x94, 0x6c, + 0x81, 0x3e, 0x03, 0xe3, 0x85, 0x17, 0x0e, 0x4e, 0xc3, 0x56, 0xe0, 0x9c, 0x92, 0xb8, 0x63, 0x73, + 0x0c, 0x65, 0x95, 0xa3, 0xa8, 0xd5, 0xc9, 0xb6, 0x52, 0x2b, 0xd2, 0x6b, 0x78, 0xd7, 0x8e, 0x6c, + 0xb1, 0x86, 0xe7, 0xb5, 0x6b, 0x38, 0xa5, 0x81, 0x75, 0x66, 0x1c, 0xad, 0x49, 0x43, 0xa4, 0xf4, + 0x8e, 0x58, 0x50, 0xd1, 0x54, 0x0d, 0xac, 0x33, 0xa3, 0xee, 0x51, 0xef, 0xfc, 0xcd, 0x45, 0xc9, + 0x3d, 0xea, 0x95, 0x70, 0x8e, 0x31, 0x85, 0x3d, 0x74, 0x3a, 0x81, 0x1d, 0x11, 0xea, 0xa4, 0xf6, + 0x03, 0xbf, 0x27, 0x60, 0x97, 0x24, 0x58, 0xbd, 0x12, 0xce, 0x31, 0x46, 0x47, 0x30, 0x9f, 0xaa, + 0x39, 0x49, 0xfa, 0x6a, 0x4a, 0xf3, 0xab, 0x53, 0xc1, 0x5a, 0x43, 0x74, 0x0a, 0x26, 0x26, 0xae, + 0x6f, 0xb7, 0xb7, 0x07, 0x91, 0xdf, 0xf0, 0x5a, 0x01, 0xe9, 0xd1, 0x10, 0x84, 0x8e, 0xb9, 0x79, + 0x9d, 0x81, 0xbe, 0x93, 0xac, 0x43, 0xbd, 0x9a, 0xc0, 0xcf, 0xc5, 0xa1, 0xae, 0xb9, 0x1e, 0xb9, + 0x98, 0xd8, 0x6d, 0x12, 0x88, 0x0e, 0x2f, 0x4b, 0x1e, 0x44, 0xad, 0xc6, 0x19, 0x03, 0x74, 0x08, + 0xb3, 0x8f, 0x49, 0x84, 0x49, 0xdf, 0x75, 0x5a, 0x76, 0xfc, 0xe6, 0xbd, 0xa1, 0x4e, 0x50, 0xba, + 0x96, 0xdb, 0x89, 0xd8, 0x4a, 0xa9, 0xa5, 0x8b, 0x08, 0x93, 0x90, 0x44, 0x4d, 0x12, 0xa6, 0xdc, + 0x83, 0xb9, 0x22, 0x2d, 0x22, 0x8d, 0x06, 0xd6, 0x99, 0xa1, 0x03, 0xb8, 0xf6, 0xd8, 0x3f, 0xb4, + 0x87, 0xf4, 0x3d, 0x19, 0x0a, 0xac, 0x9b, 0xb2, 0xb3, 0x57, 0xeb, 0x79, 0xcf, 0xb2, 0x86, 0x1c, + 0x8d, 0xf4, 0x0e, 0x9c, 0x91, 0x4f, 0x35, 0x57, 0x55, 0x34, 0xb9, 0x3e, 0x85, 0x26, 0x57, 0xa0, + 0x2f, 0x61, 0x69, 0xdf, 0x71, 0x49, 0x93, 0x04, 0xaf, 0x9d, 0x16, 0x49, 0x4f, 0x99, 0xb9, 0x26, + 0xed, 0xe7, 0x1c, 0x2d, 0x8e, 0x9c, 0x07, 0x82, 0x7a, 0xb0, 0xa2, 0x56, 0xed, 0xbd, 0x76, 0x5a, + 0x49, 0xc7, 0xd7, 0x25, 0x6f, 0x56, 0xa4, 0xca, 0x5b, 0x2a, 0x84, 0x43, 0x2f, 0x60, 0xfe, 0x90, + 0x44, 0x76, 0xdb, 0x8e, 0x6c, 0xe9, 0x59, 0x6e, 0xc9, 0x3b, 0x40, 0xa3, 0xc2, 0xe1, 0xb5, 0xe6, + 0xe8, 0x08, 0xd0, 0x63, 0xff, 0x71, 0xfd, 0x98, 0x04, 0x2d, 0x32, 0x8a, 0x66, 0x2c, 0xf9, 0xcd, + 0x9f, 0x51, 0xe0, 0x90, 0x1a, 0x53, 0x1a, 0x4a, 0xec, 0xdb, 0x03, 0x37, 0x6a, 0x78, 0x5f, 0x91, + 0xd1, 0x60, 0xbc, 0x25, 0x01, 0x66, 0x15, 0xb0, 0xc6, 0x08, 0xfd, 0x16, 0x16, 0xeb, 0x91, 0x7b, + 0xe8, 0x33, 0x67, 0xca, 0x1c, 0x98, 0x80, 0xbb, 0x2d, 0xed, 0x00, 0xbd, 0x12, 0xef, 0x63, 0x0e, + 0x04, 0xfa, 0x12, 0xae, 0xbf, 0xf2, 0x83, 0xf3, 0xb0, 0x6f, 0xb7, 0xc8, 0x49, 0x37, 0x20, 0x61, + 0xd7, 0x77, 0xc5, 0x3b, 0xc1, 0x7c, 0x5b, 0x7a, 0xab, 0xe6, 0xea, 0xe1, 0x7c, 0x08, 0xd4, 0x83, + 0xd5, 0x7a, 0xe4, 0x1e, 0x07, 0xe4, 0x8c, 0x44, 0xad, 0xee, 0x91, 0xd7, 0x14, 0xaf, 0x86, 0xa4, + 0x91, 0x77, 0x58, 0x23, 0x6f, 0x8f, 0x1e, 0xa2, 0x40, 0x19, 0x5f, 0x02, 0x86, 0x7e, 0x0b, 0x66, + 0xa3, 0x59, 0x3f, 0xde, 0x0d, 0x6c, 0xc7, 0xab, 0xfb, 0x5e, 0x38, 0xe8, 0x8d, 0x7c, 0xce, 0x1d, + 0xd6, 0xd0, 0x1a, 0x6f, 0x28, 0x4f, 0x0d, 0xe7, 0x02, 0xa0, 0x3e, 0xdc, 0x6c, 0xb4, 0xc8, 0x29, + 0x09, 0x3a, 0x3c, 0xb0, 0x7a, 0x6d, 0xbb, 0x4e, 0xdb, 0x8e, 0x92, 0x45, 0xb8, 0xc1, 0x5a, 0xb8, + 0x2d, 0x5a, 0x28, 0xd2, 0xe5, 0xd3, 0x52, 0x0c, 0x88, 0x3a, 0xb0, 0x7c, 0xe8, 0x7b, 0x1d, 0x7f, + 0x77, 0xa7, 0xee, 0x3a, 0x6c, 0x75, 0x45, 0x4e, 0x90, 0x34, 0x77, 0x97, 0x35, 0x77, 0x4b, 0xac, + 0xf9, 0x5c, 0x45, 0xde, 0x56, 0x01, 0x14, 0x5d, 0x06, 0x98, 0x9c, 0xd1, 0xb9, 0xe3, 0xae, 0x6d, + 0x7b, 0x10, 0x75, 0x45, 0x3b, 0xf7, 0xa4, 0x65, 0x90, 0xab, 0x87, 0xf3, 0x21, 0x50, 0x3b, 0x26, + 0xa0, 0x17, 0x51, 0xd7, 0xf7, 0x5e, 0xb4, 0xcf, 0x9a, 0xec, 0x58, 0x44, 0xe0, 0xdf, 0xcf, 0x84, + 0x83, 0x5a, 0x3d, 0xfe, 0x18, 0xf9, 0x40, 0xd6, 0x3e, 0x2c, 0x65, 0xe8, 0x0a, 0xe7, 0x6b, 0xf7, + 0xa1, 0xc2, 0xbb, 0x15, 0x9a, 0xa5, 0xf5, 0xb1, 0x8d, 0xa9, 0x87, 0xb3, 0x9b, 0xfc, 0x70, 0x46, + 0x38, 0xf3, 0x44, 0xc1, 0xfa, 0xbf, 0x1b, 0x50, 0x49, 0x2c, 0x7f, 0x5e, 0x1e, 0x37, 0x0f, 0xe3, + 0x7b, 0x41, 0xe0, 0x07, 0x8c, 0xc0, 0xd5, 0x70, 0x5c, 0x40, 0x9f, 0xe7, 0x76, 0x9c, 0xb3, 0xb4, + 0xd5, 0x3c, 0x96, 0x16, 0x6b, 0xe1, 0xdc, 0xe7, 0x3e, 0x82, 0x79, 0x99, 0x70, 0x71, 0xd8, 0x71, + 0xc9, 0x5f, 0xea, 0x54, 0xb0, 0xd6, 0x90, 0xbe, 0xcd, 0x47, 0xdc, 0x8b, 0x83, 0x4d, 0x48, 0x6f, + 0x73, 0xb5, 0x1a, 0x67, 0x0c, 0x28, 0x3b, 0x4a, 0x91, 0x2f, 0x8e, 0x32, 0x29, 0xbd, 0xe2, 0x32, + 0xf5, 0x38, 0x6b, 0xc2, 0x63, 0xc1, 0x11, 0xf7, 0xe2, 0x48, 0x15, 0x35, 0x16, 0x54, 0x35, 0xb0, + 0xce, 0x8c, 0xd3, 0xbf, 0x84, 0x80, 0x71, 0xb0, 0xaa, 0x4a, 0xff, 0x14, 0x05, 0xac, 0x31, 0xa2, + 0xc3, 0x2e, 0xf3, 0x2f, 0x0e, 0x06, 0x6a, 0x20, 0x9e, 0x51, 0xc1, 0x5a, 0x43, 0xf4, 0x4b, 0xca, + 0xdc, 0x04, 0x41, 0xe3, 0xcc, 0xed, 0xba, 0x86, 0xb9, 0x71, 0x90, 0x94, 0x32, 0x7a, 0x94, 0xa5, + 0x6e, 0x66, 0x96, 0xba, 0x71, 0xc3, 0x14, 0x77, 0x7b, 0x5e, 0xc0, 0xdd, 0x6e, 0x15, 0x70, 0xb7, + 0xd4, 0xb0, 0xa8, 0x54, 0xeb, 0x79, 0x01, 0x79, 0xbb, 0x55, 0x40, 0xde, 0x04, 0xa4, 0x86, 0xbd, + 0xed, 0xe5, 0xb0, 0xb7, 0x9b, 0x39, 0xec, 0x8d, 0x43, 0xa9, 0xf4, 0xed, 0x81, 0x4a, 0xdf, 0x16, + 0x55, 0xfa, 0xc6, 0x0d, 0x13, 0xfe, 0xf6, 0x45, 0x31, 0x7f, 0xbb, 0x5d, 0xcc, 0xdf, 0x38, 0x5a, + 0x0e, 0x81, 0xdb, 0xd1, 0x13, 0xb8, 0x15, 0x3d, 0x81, 0xe3, 0x58, 0x0a, 0x83, 0x7b, 0x9a, 0xcb, + 0xe0, 0xd6, 0x72, 0x19, 0x9c, 0xd8, 0xb0, 0x19, 0x0a, 0x97, 0x5a, 0xcf, 0x31, 0x17, 0xe3, 0xeb, + 0x79, 0x5e, 0xbb, 0x9e, 0xd3, 0x2a, 0x58, 0x6b, 0xc8, 0x01, 0x53, 0x74, 0x8c, 0x03, 0x2e, 0xa8, + 0x80, 0x19, 0x15, 0xac, 0x35, 0xa4, 0x2e, 0x34, 0xe7, 0xac, 0x8e, 0x33, 0xb9, 0xd5, 0x3c, 0x26, + 0x27, 0x5c, 0x68, 0xde, 0x51, 0xdf, 0xe7, 0xb0, 0x94, 0xa1, 0x63, 0x1c, 0x79, 0x49, 0x42, 0xce, + 0xd1, 0xc2, 0x79, 0xe6, 0x08, 0xc3, 0x82, 0xc2, 0xca, 0x38, 0xae, 0x29, 0x4d, 0xb7, 0x56, 0x07, + 0xeb, 0x4d, 0x51, 0xeb, 0x52, 0x46, 0x77, 0xe7, 0x52, 0x46, 0xc7, 0x5b, 0xc8, 0xa7, 0x74, 0xfb, + 0x70, 0x2d, 0xc5, 0xd0, 0x78, 0xa7, 0x97, 0x25, 0xd7, 0x92, 0xa9, 0xc7, 0x59, 0x13, 0xf4, 0x2c, + 0x8f, 0xd5, 0xad, 0xe6, 0xb1, 0xba, 0xd8, 0x30, 0x8f, 0xd6, 0x1d, 0xc1, 0xbc, 0xcc, 0xcf, 0x78, + 0xd7, 0x56, 0xa4, 0x55, 0xa5, 0x53, 0xc1, 0x5a, 0xc3, 0x98, 0x17, 0x8c, 0x08, 0x1a, 0x87, 0xbb, + 0xa9, 0xf0, 0x02, 0x55, 0x61, 0xc4, 0x0b, 0xd4, 0x1a, 0x0e, 0x98, 0x70, 0x34, 0x0e, 0xb8, 0xaa, + 0x02, 0x2a, 0x0a, 0x29, 0x40, 0xa5, 0x06, 0xd9, 0x60, 0x66, 0xa9, 0x19, 0x87, 0x5d, 0x93, 0xb6, + 0x7b, 0x9e, 0x1a, 0x07, 0xcf, 0x85, 0xa1, 0x71, 0x6f, 0x0e, 0x27, 0xe3, 0xed, 0xac, 0x4b, 0x1e, + 0xaf, 0x50, 0x57, 0xc4, 0xbd, 0x85, 0x4a, 0xe8, 0x73, 0x58, 0x50, 0x68, 0x1a, 0x6f, 0xe9, 0x96, + 0xbc, 0x31, 0x74, 0x3a, 0xbc, 0x05, 0x3d, 0x00, 0xc2, 0x30, 0x27, 0xb1, 0x35, 0x8e, 0x6b, 0xc9, + 0x11, 0x43, 0x56, 0x83, 0xa3, 0xea, 0x8c, 0x69, 0x14, 0x22, 0xd1, 0x36, 0x8e, 0xf9, 0x96, 0x84, + 0xa9, 0xd1, 0xc0, 0x3a, 0x33, 0x4a, 0xd8, 0x33, 0x5c, 0x8d, 0x23, 0xde, 0x96, 0xf6, 0x46, 0x8e, + 0x96, 0x20, 0xec, 0x39, 0xd5, 0xc8, 0x86, 0x65, 0x1d, 0x5d, 0xe3, 0x4d, 0xbc, 0x2d, 0xbd, 0x8b, + 0xf3, 0x15, 0x71, 0x01, 0x48, 0x7c, 0x4c, 0xe5, 0x25, 0x17, 0x5c, 0x09, 0xf8, 0x3b, 0xca, 0x31, + 0x55, 0x56, 0x05, 0x6b, 0x0d, 0x51, 0x1f, 0xd6, 0x72, 0x89, 0x1f, 0xc7, 0xbe, 0x23, 0x9d, 0x56, + 0x5d, 0xa2, 0x8d, 0x2f, 0x83, 0xa3, 0x84, 0x48, 0xc3, 0x03, 0x79, 0x5b, 0x1b, 0x12, 0x61, 0xc9, + 0xd5, 0xc3, 0xf9, 0x10, 0x28, 0x84, 0xd5, 0x3c, 0xea, 0xc7, 0x1b, 0xb9, 0x2b, 0xf1, 0xe2, 0x62, + 0x65, 0x3e, 0xe7, 0x97, 0x40, 0xa2, 0xaf, 0xe0, 0x86, 0x96, 0x03, 0xf2, 0x16, 0x63, 0x9e, 0x67, + 0x15, 0xf1, 0x49, 0xa9, 0xb9, 0x22, 0x30, 0xba, 0xcc, 0x74, 0x74, 0x90, 0x37, 0x75, 0x5f, 0x5a, + 0x66, 0xf9, 0x8a, 0xb8, 0x00, 0x04, 0xbd, 0x8a, 0x03, 0x54, 0x99, 0x0b, 0x9a, 0xef, 0x66, 0x02, + 0x54, 0x95, 0x2c, 0x2a, 0x3e, 0x35, 0xa3, 0x21, 0xae, 0x4b, 0xf5, 0x24, 0xf3, 0xcf, 0x93, 0xf1, + 0x7d, 0xa9, 0x1e, 0x15, 0x2d, 0xc2, 0x44, 0xfd, 0xd9, 0x8b, 0x17, 0x9c, 0x2b, 0x56, 0x31, 0x2f, + 0xa1, 0x65, 0xa8, 0x1c, 0xd8, 0x5e, 0x67, 0x60, 0x77, 0x08, 0xe3, 0x89, 0x55, 0x9c, 0x94, 0x91, + 0x09, 0x93, 0x7b, 0x1e, 0xdd, 0xa9, 0x6d, 0x46, 0x0b, 0x2b, 0x58, 0x14, 0xd1, 0x06, 0xcc, 0x6e, + 0xbb, 0xae, 0xff, 0xe6, 0x85, 0xe7, 0x84, 0xbe, 0x6b, 0x47, 0xa4, 0xcd, 0x08, 0x61, 0x05, 0xab, + 0x62, 0x4a, 0x2c, 0xe9, 0xcb, 0xf5, 0x82, 0x31, 0xbb, 0x0a, 0x8e, 0x0b, 0x68, 0x15, 0x80, 0x31, + 0xcc, 0xba, 0x6b, 0x87, 0x21, 0xe3, 0x69, 0x55, 0x9c, 0x92, 0xc4, 0x77, 0xa2, 0x76, 0xe8, 0x7b, + 0x8c, 0x7d, 0xb1, 0x3b, 0x51, 0x5a, 0xa2, 0xed, 0xaa, 0x51, 0x7a, 0x85, 0xdd, 0xb0, 0xaa, 0x62, + 0xb4, 0x0e, 0x53, 0xdb, 0x3b, 0x8d, 0xba, 0xef, 0x45, 0x81, 0xdd, 0x8a, 0xaf, 0xb8, 0xaa, 0x38, + 0x2d, 0x42, 0xef, 0xc0, 0xcc, 0x76, 0xdb, 0xee, 0x47, 0x24, 0x10, 0x50, 0xc0, 0x94, 0x14, 0x29, + 0xed, 0x6b, 0x73, 0xf7, 0xa9, 0xd0, 0x99, 0x8a, 0xfb, 0x3a, 0x92, 0xa0, 0x8f, 0x60, 0x69, 0x97, + 0x9c, 0x39, 0x9e, 0x13, 0x39, 0xbe, 0xd7, 0x6c, 0x75, 0x49, 0xcf, 0x16, 0xca, 0x35, 0xd6, 0xb7, + 0xbc, 0x6a, 0xf4, 0x00, 0xe6, 0x8e, 0x5d, 0xdb, 0x13, 0x3d, 0x4a, 0x53, 0x99, 0x71, 0xac, 0xab, + 0x42, 0x8f, 0x60, 0xf1, 0xe4, 0xa2, 0x4f, 0x76, 0x09, 0xf5, 0x0b, 0xfd, 0xc8, 0x0f, 0x92, 0x07, + 0x9c, 0x61, 0xfd, 0xca, 0xa9, 0xa5, 0x7d, 0xa4, 0xde, 0xeb, 0x1b, 0xdf, 0x63, 0xe1, 0xee, 0xa9, + 0x1d, 0x12, 0xd1, 0xda, 0x2c, 0x33, 0xcc, 0xab, 0x46, 0xb7, 0x61, 0xfa, 0x95, 0xe3, 0xb5, 0xfd, + 0x37, 0x3b, 0x76, 0xd4, 0xea, 0x92, 0x90, 0xd1, 0x90, 0x71, 0x2c, 0x0b, 0xa9, 0x56, 0x7d, 0xd0, + 0x1b, 0xb8, 0x76, 0xe4, 0xbc, 0x26, 0xdb, 0xad, 0x73, 0x46, 0x36, 0x2a, 0x58, 0x16, 0xd2, 0xde, + 0x1f, 0xda, 0xc3, 0xbd, 0x21, 0x69, 0x0d, 0xe8, 0x60, 0xec, 0x07, 0x76, 0x8f, 0xec, 0x5c, 0x44, + 0x24, 0x64, 0x3c, 0x62, 0x0c, 0xe7, 0xd4, 0xd2, 0x71, 0x3a, 0xb4, 0x87, 0x4f, 0x6c, 0xaf, 0xed, + 0x92, 0x80, 0x9f, 0x26, 0x90, 0x90, 0xb1, 0x86, 0x71, 0xac, 0xab, 0x42, 0xbf, 0x86, 0xe5, 0x43, + 0x7b, 0xc8, 0xcf, 0x08, 0x32, 0x86, 0xf3, 0xcc, 0xb0, 0x40, 0x03, 0x7d, 0x0c, 0xe6, 0xa1, 0x3d, + 0x3c, 0x7a, 0xe3, 0x91, 0x20, 0x63, 0xbd, 0xc0, 0xac, 0x73, 0xeb, 0xe9, 0x7a, 0x39, 0x20, 0x76, + 0x48, 0xf6, 0xfa, 0x7e, 0xab, 0xcb, 0x82, 0xfc, 0x32, 0x4e, 0x49, 0xe8, 0x8e, 0x38, 0xf4, 0xdb, + 0x24, 0x34, 0x97, 0xd6, 0xc7, 0x36, 0xaa, 0x38, 0x2e, 0x20, 0x0b, 0x6a, 0xcf, 0x06, 0xae, 0x7b, + 0xec, 0xbb, 0x4e, 0xcb, 0x21, 0xa1, 0x69, 0xb2, 0x4a, 0x49, 0x66, 0x35, 0xb4, 0x97, 0xdb, 0x2c, + 0xdf, 0x80, 0xa5, 0xaf, 0x34, 0xda, 0xfc, 0xda, 0x3f, 0x29, 0xd3, 0x8d, 0xc4, 0xfd, 0xcf, 0x58, + 0xbc, 0x91, 0xb8, 0x2b, 0xf9, 0x58, 0x7f, 0xfe, 0x42, 0xbb, 0x61, 0x53, 0x79, 0x73, 0xd0, 0xa2, + 0x8f, 0xc3, 0xf0, 0x2a, 0x58, 0x92, 0x59, 0x8d, 0xcc, 0xad, 0x38, 0x5a, 0x81, 0x2a, 0x47, 0xe2, + 0x0e, 0x66, 0x0c, 0x8f, 0x04, 0xe9, 0xe4, 0x89, 0xab, 0x6c, 0x38, 0x52, 0xc9, 0x13, 0xd9, 0x43, + 0x18, 0x13, 0x26, 0xe5, 0xd6, 0x45, 0xd1, 0x3a, 0xc8, 0xde, 0xd8, 0x20, 0x03, 0xc6, 0xea, 0xbd, + 0x36, 0x77, 0x6a, 0xf4, 0x27, 0x93, 0x9c, 0x75, 0xb8, 0x33, 0xa3, 0x3f, 0xd9, 0xe1, 0xd6, 0x30, + 0x0a, 0xec, 0xe4, 0x70, 0x8b, 0x16, 0xac, 0x3b, 0x1a, 0xb2, 0x80, 0x10, 0x94, 0xe9, 0x6f, 0x8e, + 0xc7, 0x7e, 0x5b, 0x9f, 0x5c, 0x76, 0x56, 0x4c, 0x67, 0xe0, 0xd8, 0x8e, 0x22, 0x12, 0xf0, 0x53, + 0xbc, 0x2a, 0x4e, 0xca, 0xd6, 0x07, 0x97, 0xc6, 0x08, 0xda, 0x46, 0xff, 0x58, 0xca, 0x3f, 0x32, + 0xce, 0x0e, 0xf7, 0xb4, 0x32, 0xdc, 0x2c, 0xbe, 0x6a, 0xec, 0x8a, 0xe1, 0xe6, 0x45, 0x5a, 0xf3, + 0x99, 0x7f, 0xfa, 0xcc, 0xee, 0x11, 0xbe, 0x1c, 0x44, 0x91, 0x0e, 0xd1, 0x67, 0xfe, 0x69, 0x63, + 0x97, 0xb9, 0xf1, 0x32, 0x8e, 0x0b, 0xd4, 0xdd, 0xc6, 0x07, 0x01, 0xfb, 0xc4, 0x6b, 0x91, 0x23, + 0xcf, 0x15, 0x6e, 0x5c, 0x15, 0x53, 0x67, 0x8a, 0x89, 0x47, 0xde, 0x8c, 0x14, 0x27, 0x98, 0xa2, + 0x22, 0xb5, 0x3e, 0x28, 0x88, 0x5f, 0x0a, 0x66, 0xfe, 0xf3, 0x6c, 0x1a, 0x85, 0x66, 0xe6, 0xe7, + 0x61, 0x9c, 0x2a, 0x84, 0x7c, 0xee, 0xe3, 0x02, 0x1d, 0xac, 0x24, 0x14, 0x64, 0x8f, 0x3d, 0x86, + 0x47, 0x02, 0xba, 0x0a, 0xb2, 0xe7, 0x77, 0xba, 0x09, 0x99, 0xd7, 0x25, 0x61, 0x58, 0x7f, 0x2a, + 0x41, 0x45, 0xc8, 0x46, 0x03, 0xdf, 0xe6, 0x07, 0xb2, 0xa2, 0x48, 0x01, 0x9f, 0x92, 0x0b, 0xda, + 0xb1, 0xb1, 0x8d, 0x1a, 0x66, 0xbf, 0xd1, 0xbd, 0xd8, 0x92, 0x6e, 0x7f, 0xd6, 0xad, 0x99, 0x87, + 0x33, 0x9b, 0x2c, 0x13, 0x4f, 0x48, 0x71, 0x52, 0x4f, 0xdf, 0x66, 0x4e, 0x88, 0x6d, 0xaf, 0xc3, + 0x0e, 0x63, 0xf8, 0xbb, 0x36, 0x2d, 0x42, 0x77, 0x60, 0xf2, 0x89, 0xef, 0xb6, 0x49, 0x10, 0x9a, + 0xe3, 0xec, 0x1c, 0x79, 0x3a, 0x06, 0x7b, 0x65, 0x3b, 0xd1, 0xc9, 0xd0, 0xc3, 0xa2, 0x96, 0x2a, + 0x52, 0x19, 0x55, 0x9c, 0xd0, 0x2a, 0xf2, 0x5a, 0xeb, 0x4b, 0xed, 0x21, 0x26, 0x7d, 0x94, 0xba, + 0xd7, 0x10, 0xe3, 0xce, 0x7e, 0xa3, 0x5f, 0x40, 0x4d, 0xe8, 0x1d, 0x38, 0x61, 0xc4, 0x1e, 0x73, + 0xea, 0xe1, 0x2c, 0x8f, 0x75, 0x12, 0x08, 0x49, 0xc9, 0x9a, 0xd3, 0xa4, 0xa2, 0x58, 0x5d, 0x98, + 0x3a, 0x19, 0x7a, 0xdf, 0x6f, 0x44, 0xb1, 0xff, 0x26, 0x19, 0x51, 0xfa, 0x1b, 0xdd, 0x87, 0xc9, + 0xa3, 0x7e, 0xc4, 0xce, 0xd2, 0xe3, 0x3c, 0xa4, 0x6b, 0xa3, 0x01, 0xe5, 0x15, 0x58, 0x68, 0x58, + 0xff, 0x51, 0x82, 0x49, 0xde, 0x38, 0xfa, 0x14, 0x2a, 0xf5, 0x80, 0xd8, 0x11, 0xd9, 0x8e, 0x78, + 0x46, 0xdc, 0xf2, 0x66, 0x9c, 0xa0, 0xb8, 0x29, 0x12, 0x14, 0x53, 0x79, 0x71, 0x15, 0x1a, 0xa0, + 0xfd, 0xee, 0xbf, 0xd6, 0x4a, 0x38, 0xb1, 0x42, 0xeb, 0x50, 0xa6, 0xc4, 0x8e, 0xad, 0xbc, 0xa9, + 0x87, 0xb5, 0xcd, 0x68, 0xe8, 0x6d, 0x9e, 0x0c, 0x3d, 0x2a, 0xc3, 0xac, 0x86, 0x3e, 0xca, 0x8b, + 0x90, 0x04, 0x27, 0x43, 0x4f, 0x04, 0x53, 0xbc, 0x88, 0x1e, 0x40, 0x95, 0x8e, 0x39, 0xed, 0x65, + 0x68, 0x96, 0xd9, 0xd0, 0x21, 0x71, 0xda, 0x3c, 0x1a, 0x0b, 0x3c, 0x52, 0x92, 0xf7, 0xff, 0xb8, + 0xb2, 0xff, 0xad, 0x2f, 0x74, 0xe7, 0xc5, 0xda, 0x79, 0x7b, 0xc0, 0x46, 0x5b, 0x99, 0xb6, 0x99, + 0x51, 0xdb, 0x0c, 0x20, 0xad, 0x62, 0x2d, 0x68, 0xf3, 0x7e, 0xac, 0x7f, 0x2a, 0x41, 0x35, 0x11, + 0x52, 0x77, 0xf8, 0xcc, 0x6f, 0x13, 0x1a, 0x8b, 0xf0, 0xe6, 0x92, 0x32, 0x7d, 0x21, 0xd1, 0xdf, + 0x8d, 0x36, 0xdf, 0xa4, 0xbc, 0x44, 0x1f, 0x89, 0x01, 0x30, 0xa3, 0xd8, 0x39, 0x8d, 0x04, 0xb4, + 0xf3, 0x2f, 0x42, 0x1e, 0x64, 0x96, 0x31, 0xfb, 0x4d, 0x65, 0xfb, 0x01, 0x89, 0xaf, 0x0c, 0xca, + 0x98, 0xfd, 0xa6, 0x2d, 0x3f, 0x71, 0x22, 0x6c, 0x47, 0x8e, 0xcf, 0x1c, 0xd0, 0x55, 0x9c, 0x94, + 0xad, 0x67, 0xfa, 0xb3, 0x6f, 0xf4, 0x08, 0xa6, 0x13, 0x21, 0x1b, 0x86, 0xf8, 0x1e, 0x26, 0xb9, + 0x2e, 0x49, 0x0c, 0x64, 0x35, 0xcb, 0x85, 0x95, 0xa2, 0x24, 0x18, 0x3a, 0xe1, 0x8f, 0x03, 0x7f, + 0xd0, 0x4f, 0x5c, 0xb4, 0x28, 0x16, 0x3b, 0x68, 0xf1, 0xa6, 0x1c, 0x93, 0xdf, 0x94, 0x1f, 0xc0, + 0xcd, 0xc2, 0x23, 0x5b, 0x39, 0xf3, 0x6f, 0x5c, 0x64, 0xfe, 0x7d, 0xc6, 0x1e, 0x3a, 0x93, 0x56, + 0xf3, 0x63, 0x3a, 0x67, 0xdd, 0x87, 0x05, 0xed, 0x09, 0x2f, 0x9d, 0x09, 0x76, 0x1a, 0xcc, 0x97, + 0x16, 0xfd, 0x6d, 0x35, 0x61, 0x29, 0x27, 0x13, 0x87, 0x06, 0x48, 0x22, 0xca, 0x4c, 0xae, 0xae, + 0x52, 0x92, 0x82, 0x1e, 0xbc, 0x0f, 0x66, 0xde, 0xe1, 0x70, 0xc1, 0xcb, 0x63, 0x1f, 0x2a, 0x6c, + 0xe6, 0x9e, 0x92, 0x0b, 0xda, 0xd5, 0x63, 0x3b, 0xea, 0x8a, 0xae, 0xd2, 0xdf, 0x74, 0x49, 0x1e, + 0x9d, 0x9d, 0x85, 0x24, 0xce, 0x07, 0x1e, 0xc3, 0xbc, 0x84, 0x66, 0xe0, 0x6a, 0xf3, 0x1b, 0xfe, + 0xc6, 0xb8, 0xda, 0xfc, 0xc6, 0x7a, 0xc4, 0x97, 0x28, 0xf3, 0xde, 0x77, 0xa1, 0x7c, 0x4e, 0x3d, + 0x7a, 0x49, 0x72, 0x75, 0xa2, 0x9e, 0x93, 0x38, 0xa6, 0x62, 0x9d, 0xd0, 0xb7, 0x28, 0x7b, 0xf4, + 0xa4, 0x1b, 0xf3, 0x30, 0xde, 0xf0, 0xda, 0x64, 0x28, 0x26, 0x8b, 0x15, 0xd0, 0xfd, 0x51, 0x47, + 0xb9, 0x23, 0x51, 0x71, 0x71, 0xa2, 0x60, 0xbd, 0xd2, 0x66, 0x2f, 0xa1, 0x4f, 0x33, 0x8d, 0xf1, + 0x2e, 0x26, 0x17, 0x07, 0x72, 0x2d, 0x56, 0xd5, 0xad, 0x23, 0xb8, 0x26, 0x06, 0x35, 0x41, 0xcf, + 0xe9, 0xb0, 0x01, 0x63, 0x4f, 0x1c, 0x91, 0x46, 0x4d, 0x7f, 0xd2, 0xf1, 0xa5, 0xfa, 0x3c, 0xd2, + 0x62, 0xbf, 0xad, 0x2f, 0xf5, 0x87, 0xf4, 0x68, 0x5f, 0xd3, 0x10, 0xef, 0xac, 0x39, 0x3a, 0x12, + 0x95, 0xeb, 0x71, 0xd6, 0xc4, 0xc2, 0xda, 0xcc, 0x2b, 0xf4, 0x2b, 0xa8, 0x25, 0xb2, 0x78, 0x18, + 0xe2, 0xdb, 0xc0, 0x51, 0x16, 0x7b, 0xba, 0x1a, 0x4b, 0xca, 0x7c, 0xdf, 0x64, 0x8f, 0xf3, 0x1f, + 0x42, 0x35, 0x11, 0x26, 0xc9, 0xd3, 0x1a, 0x44, 0x3c, 0x52, 0xb3, 0x9a, 0x30, 0x75, 0x1c, 0x90, + 0xbe, 0x1d, 0x90, 0x66, 0xd4, 0x63, 0x43, 0xc4, 0x22, 0x30, 0xbe, 0x04, 0x59, 0xf8, 0x65, 0xc0, + 0x58, 0xf3, 0xf9, 0x81, 0x88, 0x59, 0x9b, 0xcf, 0x0f, 0xe8, 0x26, 0x39, 0xb6, 0x03, 0xbb, 0x47, + 0xdd, 0x5f, 0xc8, 0x87, 0x33, 0x25, 0xb1, 0xba, 0x60, 0xf0, 0x83, 0xf6, 0x13, 0xd2, 0xeb, 0xc7, + 0xb7, 0x21, 0xcb, 0x50, 0x11, 0xdb, 0x48, 0xf8, 0x5d, 0x51, 0xa6, 0x13, 0xb8, 0xed, 0x3a, 0x76, + 0x12, 0x1b, 0xb1, 0x02, 0x0d, 0xf7, 0x8f, 0xbb, 0x17, 0xa1, 0xd3, 0xb2, 0xdd, 0x54, 0x54, 0x28, + 0xc9, 0xac, 0xff, 0x29, 0xe5, 0x25, 0x8d, 0xb1, 0x43, 0x05, 0xdf, 0xf3, 0x12, 0x27, 0xc2, 0x4b, + 0xe8, 0xfd, 0x24, 0x13, 0x3c, 0xbe, 0x7a, 0x5e, 0xd1, 0xdf, 0x44, 0xc4, 0x3a, 0x22, 0x4f, 0x1c, + 0x7d, 0x0a, 0x37, 0x92, 0x67, 0x89, 0x35, 0x29, 0x63, 0x1e, 0xf4, 0xfb, 0x7e, 0x30, 0x3a, 0x60, + 0x28, 0x52, 0x41, 0xfb, 0xb0, 0x7a, 0x60, 0x87, 0x51, 0xc3, 0x0b, 0x49, 0x10, 0x35, 0x76, 0x35, + 0x20, 0x71, 0xf8, 0x7a, 0x89, 0xd6, 0x67, 0xe5, 0xca, 0x98, 0x51, 0xb6, 0xfe, 0xbd, 0x92, 0x7b, + 0xc3, 0x42, 0x7d, 0xc3, 0xee, 0x0e, 0x1f, 0xe4, 0xab, 0xbb, 0x3b, 0xe8, 0x11, 0xd4, 0x52, 0x73, + 0x1c, 0xf2, 0x57, 0xa9, 0x78, 0x8d, 0xa7, 0xaa, 0xb0, 0xa4, 0x87, 0xee, 0x81, 0x41, 0xfb, 0xb2, + 0x7d, 0x76, 0x46, 0x5a, 0x11, 0x69, 0xb3, 0x90, 0x26, 0xf6, 0x38, 0x19, 0x39, 0xfa, 0x04, 0x66, + 0x68, 0xc8, 0x70, 0x40, 0x5e, 0x13, 0x37, 0x1d, 0x2c, 0xcc, 0x8b, 0x7b, 0xb3, 0x74, 0x25, 0x56, + 0x74, 0xd1, 0x2e, 0xdc, 0x94, 0x15, 0x88, 0x4b, 0x39, 0xa9, 0x3a, 0x34, 0xc5, 0x4a, 0x68, 0x1f, + 0x66, 0xa9, 0x02, 0x3b, 0xd1, 0x20, 0xed, 0x97, 0x76, 0x12, 0x45, 0x2a, 0x53, 0x2c, 0x2b, 0x61, + 0xd5, 0x08, 0x7d, 0x04, 0x4b, 0x8a, 0x68, 0x6f, 0xc8, 0xfb, 0x31, 0xc9, 0xfa, 0x91, 0x57, 0x4d, + 0x7b, 0xd0, 0xbc, 0x08, 0x23, 0xd2, 0x7b, 0x69, 0x07, 0x0e, 0x5d, 0x07, 0xa1, 0x59, 0xd1, 0xf5, + 0x40, 0x56, 0xc2, 0xaa, 0x11, 0xed, 0x81, 0x22, 0x4a, 0x7a, 0x50, 0x8d, 0x7b, 0x90, 0x53, 0x8d, + 0x3e, 0x81, 0xeb, 0x4a, 0xe7, 0x30, 0xe9, 0xbb, 0xf6, 0x05, 0xbb, 0xca, 0x04, 0x66, 0x9b, 0xaf, + 0x40, 0xad, 0x15, 0xe0, 0x94, 0xf5, 0x54, 0x6c, 0x9d, 0xab, 0x80, 0x9e, 0xc0, 0x9a, 0x52, 0xd9, + 0xf4, 0xec, 0x7e, 0xd8, 0xf5, 0xa3, 0x13, 0xdf, 0x3f, 0xb0, 0x83, 0x0e, 0x61, 0x87, 0x4e, 0x15, + 0x7c, 0x99, 0x1a, 0x45, 0x52, 0x3a, 0x99, 0x41, 0x9a, 0x8e, 0x91, 0x2e, 0x51, 0xa3, 0xfb, 0x96, + 0xaf, 0xe9, 0x36, 0x5d, 0xd4, 0x07, 0xbe, 0xd7, 0xa1, 0x6e, 0xa7, 0xde, 0x25, 0xad, 0x73, 0xd2, + 0x66, 0x27, 0x53, 0x15, 0x5c, 0xa4, 0x42, 0x83, 0xbf, 0x7d, 0x7f, 0xe0, 0xc5, 0xcb, 0x7f, 0x36, + 0xce, 0x65, 0x49, 0x04, 0xe8, 0x43, 0x80, 0x64, 0xd3, 0x87, 0xa6, 0xc1, 0x26, 0x7b, 0x49, 0x9e, + 0xec, 0xa4, 0x1e, 0xa7, 0x54, 0xd9, 0x69, 0x99, 0x28, 0x51, 0x77, 0x4c, 0x92, 0x19, 0x8e, 0x8f, + 0xa7, 0x72, 0x6a, 0xa9, 0x57, 0x4c, 0x3b, 0x08, 0x76, 0x3a, 0x55, 0xc6, 0x92, 0x0c, 0x3d, 0x84, + 0xf9, 0x74, 0x39, 0x41, 0x9e, 0x63, 0xc8, 0xda, 0x3a, 0xeb, 0x5f, 0x26, 0xf4, 0x79, 0xb2, 0xb9, + 0x7e, 0x34, 0xf6, 0x32, 0x57, 0x13, 0x2f, 0xb3, 0x0e, 0x53, 0x4d, 0x12, 0xbd, 0xb4, 0x83, 0xd8, + 0xc9, 0x8c, 0xb1, 0xa3, 0x86, 0xb4, 0x28, 0xe3, 0x87, 0xca, 0x3f, 0xc1, 0x0f, 0x8d, 0x7f, 0x6f, + 0x3f, 0x34, 0xf1, 0x03, 0xfc, 0x90, 0xc6, 0x83, 0x4c, 0xfe, 0xcc, 0x1e, 0xa4, 0xf2, 0x83, 0x3d, + 0x48, 0xf5, 0x67, 0xf6, 0x20, 0xf0, 0x13, 0x3c, 0xc8, 0xd4, 0x4f, 0xf2, 0x20, 0xb5, 0xcb, 0x3c, + 0x88, 0xb4, 0xd7, 0xa6, 0x8b, 0xf7, 0xda, 0xcc, 0xf7, 0xdf, 0x6b, 0xea, 0x9e, 0x99, 0xfd, 0x01, + 0x7b, 0xc6, 0x28, 0xd8, 0x33, 0xff, 0x5d, 0x4a, 0x92, 0x11, 0xe4, 0x11, 0xd1, 0xc6, 0x51, 0xeb, + 0x30, 0xfe, 0xd2, 0x76, 0x07, 0x84, 0x87, 0xcf, 0xb0, 0xc9, 0xbe, 0x50, 0xdc, 0x1b, 0xf6, 0x03, + 0x1c, 0x57, 0xb0, 0x48, 0xeb, 0x6b, 0x97, 0x07, 0x3a, 0xf4, 0x27, 0x0b, 0x6d, 0xc3, 0x1d, 0xc7, + 0xe3, 0x01, 0x46, 0x5c, 0xa0, 0x1b, 0x82, 0x6f, 0x10, 0x16, 0x74, 0x3d, 0xa5, 0xfc, 0x26, 0x66, + 0xda, 0x19, 0x39, 0x5a, 0x85, 0x32, 0xa3, 0xad, 0x13, 0xe9, 0x46, 0xa9, 0x04, 0x33, 0x39, 0x7a, + 0x00, 0x73, 0x78, 0xe0, 0x45, 0x4e, 0x8f, 0x34, 0xa3, 0xc0, 0xf1, 0x3a, 0xbb, 0x7e, 0xcf, 0x76, + 0xe2, 0xab, 0x8d, 0x69, 0xac, 0xab, 0xb2, 0x9e, 0xc3, 0xb4, 0xb4, 0x6d, 0xb4, 0x0f, 0x9b, 0x30, + 0xbe, 0x98, 0x25, 0xc5, 0x05, 0xf6, 0xe1, 0xe3, 0xd0, 0x6b, 0xec, 0xc6, 0xee, 0xa1, 0x86, 0x79, + 0xc9, 0xfa, 0x9b, 0x9c, 0xa4, 0x8e, 0x02, 0xe2, 0xf4, 0x2b, 0x58, 0xbb, 0x24, 0xbd, 0x3e, 0xcd, + 0xd5, 0x4a, 0x32, 0x57, 0xb3, 0x60, 0xfd, 0xb2, 0x4c, 0x0e, 0x6b, 0x83, 0x7d, 0xe5, 0xa0, 0xc9, + 0x8f, 0xa7, 0x9e, 0xaf, 0xfe, 0x4c, 0xc4, 0x57, 0xf5, 0x67, 0xfc, 0x93, 0x37, 0x5d, 0xce, 0x45, + 0xce, 0x27, 0x6f, 0xef, 0x69, 0x33, 0xe9, 0xf3, 0x3c, 0xad, 0x75, 0xac, 0xcf, 0xd0, 0xc8, 0x1f, + 0x1c, 0x1a, 0xa0, 0x6f, 0x0f, 0xa2, 0x6e, 0x3c, 0x6d, 0x6c, 0x0a, 0x6a, 0x38, 0x25, 0xb1, 0xb6, + 0x34, 0xc9, 0xf7, 0x34, 0x42, 0x17, 0x22, 0xf1, 0x69, 0xa0, 0x28, 0x5b, 0x0f, 0x74, 0x39, 0x1d, + 0x85, 0x16, 0xbf, 0xd4, 0x64, 0xe4, 0xa3, 0xdb, 0x30, 0x2d, 0x44, 0xf1, 0xdd, 0x4a, 0x3c, 0x2c, + 0xb2, 0xd0, 0xfa, 0x58, 0x97, 0xef, 0xf1, 0x3d, 0x6d, 0xbb, 0xb9, 0xa9, 0xfb, 0x68, 0x8b, 0xef, + 0x84, 0x12, 0x0b, 0xfb, 0x6f, 0xe4, 0x64, 0x5e, 0xa4, 0xb6, 0x86, 0x38, 0xf6, 0x69, 0x3a, 0xdf, + 0x10, 0x4e, 0xbf, 0x47, 0x02, 0x6b, 0x98, 0x9f, 0x44, 0x22, 0x5b, 0x96, 0x14, 0x4b, 0x76, 0x21, + 0x45, 0x0b, 0x75, 0xbb, 0x6f, 0xb7, 0x9c, 0xe8, 0x82, 0x63, 0xcb, 0x42, 0x3a, 0xbb, 0x87, 0x24, + 0x0c, 0xed, 0x4e, 0x72, 0x1e, 0xce, 0x8b, 0xd6, 0x51, 0xf1, 0xe7, 0x03, 0x3f, 0xf8, 0x41, 0xad, + 0xbf, 0xbb, 0x24, 0x59, 0xe5, 0xaf, 0xfc, 0x3c, 0xef, 0xeb, 0xbf, 0x4f, 0x28, 0x6e, 0xd5, 0xfa, + 0xdb, 0x9c, 0x7c, 0x97, 0x6c, 0x77, 0x4a, 0x9a, 0xee, 0x58, 0xff, 0x5f, 0xba, 0x24, 0x33, 0xfd, + 0x92, 0x8b, 0x0c, 0xd6, 0xb9, 0xc8, 0x76, 0xfd, 0x4e, 0x72, 0x14, 0x34, 0x12, 0xd0, 0x5a, 0xea, + 0x06, 0x59, 0xae, 0x87, 0x38, 0x31, 0x4c, 0x04, 0xd4, 0x2b, 0xc4, 0xb9, 0x85, 0xe5, 0x98, 0xef, + 0xc6, 0x0c, 0x79, 0x15, 0x40, 0x84, 0xaf, 0xfc, 0xe4, 0x74, 0x0c, 0xa7, 0x24, 0xf4, 0x0d, 0x25, + 0x1e, 0xf8, 0xc0, 0x6f, 0x31, 0x56, 0xf8, 0xc4, 0x0e, 0xbb, 0xfc, 0x86, 0x5a, 0x5b, 0x47, 0x77, + 0x68, 0x9c, 0x99, 0xda, 0xd8, 0xe5, 0xb7, 0xd5, 0x49, 0xd9, 0x7a, 0x72, 0x59, 0x3a, 0x45, 0x7c, + 0x71, 0xd2, 0xf3, 0x5f, 0x93, 0xf6, 0x9e, 0x17, 0x05, 0x4e, 0xb2, 0xe7, 0x14, 0xa9, 0xb5, 0xa9, + 0xfb, 0x12, 0x84, 0x4e, 0x38, 0x97, 0x70, 0xe7, 0x20, 0x8a, 0xd6, 0x96, 0x36, 0xa1, 0xa8, 0xc0, + 0xe0, 0x40, 0xf7, 0x65, 0x08, 0xf5, 0x97, 0x3c, 0x89, 0x9c, 0xa7, 0x0d, 0xf0, 0x7c, 0x71, 0x71, + 0x3c, 0x41, 0xd8, 0x45, 0x42, 0x1c, 0xa1, 0xa6, 0x24, 0xd6, 0x5d, 0x6d, 0xee, 0x91, 0xf6, 0x62, + 0xe5, 0x5e, 0xde, 0x77, 0x24, 0xd9, 0x1b, 0x1e, 0xeb, 0xbd, 0xdc, 0x24, 0x24, 0x2d, 0x74, 0xaf, + 0xe0, 0x2b, 0x12, 0xb4, 0x01, 0xb3, 0xfc, 0x9b, 0xf6, 0xe4, 0x76, 0x28, 0x7e, 0x85, 0xa9, 0x62, + 0x3a, 0x47, 0xaf, 0x02, 0x27, 0x1a, 0x41, 0xf0, 0xc5, 0xa8, 0x48, 0x2d, 0xaf, 0x28, 0x85, 0xe9, + 0xaf, 0xd0, 0xde, 0x4b, 0x7d, 0x3e, 0x13, 0xfa, 0x35, 0xd4, 0xd2, 0xf2, 0xef, 0xf1, 0x91, 0xbf, + 0xa4, 0x6f, 0xfd, 0x7d, 0xa9, 0xe8, 0xfb, 0x8e, 0x4b, 0x36, 0xad, 0x05, 0x35, 0xfa, 0x4e, 0x25, + 0xec, 0x4c, 0x27, 0xd9, 0xb7, 0x92, 0x8c, 0x06, 0x57, 0xfc, 0x5c, 0x7b, 0x6f, 0xd8, 0x72, 0x07, + 0xa1, 0xf3, 0x9a, 0xf0, 0xf3, 0xee, 0x8c, 0xdc, 0xfa, 0xb0, 0x30, 0x39, 0xa8, 0x20, 0x7a, 0xf9, + 0xe7, 0x51, 0xe4, 0x28, 0x47, 0xc3, 0x3f, 0x32, 0x72, 0xdc, 0x80, 0xd9, 0x67, 0x64, 0x18, 0x9d, + 0x04, 0xb6, 0x17, 0xda, 0xf1, 0xe9, 0x56, 0x7c, 0x91, 0xa3, 0x8a, 0xd1, 0x26, 0xd4, 0x78, 0x50, + 0x17, 0x43, 0x96, 0x33, 0x90, 0x52, 0xbd, 0xf5, 0x6f, 0xa5, 0x82, 0xcf, 0x5c, 0x72, 0xc9, 0xe1, + 0x0a, 0x54, 0x69, 0x8c, 0xd8, 0xf0, 0xfa, 0x83, 0x88, 0xef, 0xc0, 0x91, 0x40, 0x3a, 0x0b, 0x1c, + 0x53, 0xce, 0x02, 0x2d, 0xa8, 0x49, 0x59, 0x4f, 0x65, 0x16, 0xbc, 0x48, 0x32, 0x3a, 0x46, 0x4d, + 0xdb, 0x8d, 0xbf, 0x9c, 0xaf, 0x61, 0xf6, 0x9b, 0x79, 0x7d, 0x36, 0x07, 0xdb, 0xed, 0x76, 0x40, + 0x92, 0xc4, 0x1d, 0x59, 0x68, 0xfd, 0x6b, 0xa9, 0x28, 0xc5, 0xea, 0xc7, 0x47, 0x54, 0xd4, 0x39, + 0xd3, 0x12, 0xf1, 0x22, 0x27, 0x76, 0xbf, 0xfb, 0xb6, 0x33, 0xca, 0x4d, 0xd2, 0xd6, 0xc5, 0x37, + 0xd8, 0xf1, 0x67, 0x40, 0xe4, 0x2b, 0x46, 0x61, 0x45, 0xa2, 0x92, 0x22, 0xbe, 0xf7, 0xc7, 0x89, + 0xd4, 0x27, 0x33, 0xa8, 0xca, 0xff, 0xdd, 0x88, 0x71, 0x05, 0xcd, 0xc1, 0xac, 0xf2, 0x15, 0x8b, + 0x51, 0x42, 0x06, 0xd4, 0xd2, 0xf9, 0x13, 0xc6, 0x55, 0x54, 0x83, 0x8a, 0x48, 0x65, 0x30, 0xc6, + 0xd0, 0x34, 0x54, 0x93, 0x6b, 0x65, 0xa3, 0x8c, 0x66, 0x61, 0x2a, 0x75, 0x97, 0x6a, 0x8c, 0xa3, + 0x19, 0x80, 0xd1, 0x1d, 0x9d, 0x31, 0x41, 0xf1, 0xd2, 0x97, 0x53, 0xc6, 0x24, 0xd5, 0x18, 0x7d, + 0x2c, 0x61, 0x54, 0x28, 0x62, 0xf2, 0x0d, 0x84, 0x51, 0x45, 0x8b, 0xba, 0xaf, 0x20, 0x0c, 0xa0, + 0xf2, 0xec, 0xd7, 0x08, 0xc6, 0x14, 0x42, 0xea, 0xf7, 0x08, 0x46, 0x0d, 0x4d, 0x25, 0x1f, 0x17, + 0x18, 0xd3, 0xe8, 0x7a, 0xce, 0x77, 0x03, 0xc6, 0x0c, 0xba, 0xa6, 0xa4, 0xfd, 0x1b, 0xb3, 0x68, + 0x3e, 0x9b, 0xc5, 0x6f, 0x18, 0xe9, 0xa7, 0xa0, 0x8b, 0xcd, 0xb8, 0xc6, 0x25, 0xc9, 0x59, 0xb8, + 0x81, 0xe8, 0x70, 0x2a, 0x19, 0xed, 0xc6, 0x1c, 0x15, 0x2a, 0x27, 0xad, 0xc6, 0x3c, 0x6d, 0x56, + 0x62, 0x2c, 0xc6, 0x02, 0x5a, 0xc9, 0xcf, 0x22, 0x37, 0x16, 0xe9, 0x10, 0x25, 0x19, 0x1d, 0xc6, + 0x12, 0x6f, 0x29, 0xcd, 0x19, 0x0c, 0x93, 0x76, 0x28, 0x1d, 0xe8, 0x1b, 0xd7, 0xd9, 0x54, 0x1c, + 0x1d, 0x6e, 0x7f, 0x7e, 0x8c, 0x8f, 0xea, 0x4d, 0x63, 0x99, 0x97, 0xf7, 0x0e, 0x0f, 0x1a, 0x87, + 0x8d, 0x13, 0xe3, 0x06, 0x7d, 0x54, 0x35, 0x72, 0x33, 0x56, 0xe8, 0x70, 0x69, 0xe3, 0x39, 0xe3, + 0x26, 0xeb, 0x77, 0x3a, 0x6a, 0x32, 0x56, 0xd9, 0xfc, 0x1f, 0x25, 0x6f, 0x63, 0x63, 0x8d, 0x0a, + 0x52, 0xef, 0x47, 0x63, 0x9d, 0x76, 0x56, 0x79, 0xb3, 0x19, 0xb7, 0xe8, 0x64, 0x66, 0x5f, 0x28, + 0x86, 0x45, 0x1f, 0x22, 0xed, 0xb0, 0x8d, 0xb7, 0xd0, 0x0d, 0xf6, 0x62, 0xd4, 0x65, 0x99, 0x18, + 0xb7, 0xd1, 0x02, 0x5c, 0xcb, 0x24, 0x5d, 0x18, 0x6f, 0xa3, 0x65, 0x58, 0xd4, 0x07, 0x27, 0xc6, + 0x3b, 0x68, 0x09, 0xe6, 0x34, 0x5e, 0xd7, 0xb8, 0x43, 0xbb, 0x94, 0xdd, 0xdc, 0xc6, 0x86, 0x58, + 0x8f, 0x72, 0xf6, 0xa1, 0x71, 0xf7, 0xde, 0x3f, 0x94, 0x24, 0xde, 0x39, 0x3a, 0xf6, 0xa7, 0x23, + 0xa8, 0x54, 0xc4, 0xa4, 0xdf, 0xb8, 0x82, 0xee, 0xc3, 0x1d, 0xa5, 0xaa, 0x79, 0xee, 0xf4, 0x75, + 0x27, 0xd3, 0x46, 0x09, 0xbd, 0x07, 0x77, 0x55, 0x1c, 0x96, 0xa5, 0xa8, 0x55, 0xbf, 0x7a, 0xef, + 0x5d, 0x98, 0xd7, 0x85, 0xe9, 0x08, 0x68, 0xa4, 0xd3, 0xf3, 0xd9, 0x96, 0xaf, 0x40, 0x79, 0xd7, + 0x09, 0xcf, 0x8d, 0xd2, 0xce, 0xc1, 0xef, 0xbf, 0x5d, 0x2d, 0xfd, 0xe1, 0xdb, 0xd5, 0xd2, 0x9f, + 0xbf, 0x5d, 0xbd, 0xf2, 0xbb, 0xef, 0x56, 0xaf, 0xfc, 0xe3, 0x77, 0xab, 0xa5, 0x3f, 0x7c, 0xb7, + 0x7a, 0xe5, 0x4f, 0xdf, 0xad, 0x5e, 0xf9, 0x62, 0x33, 0xf5, 0x4f, 0x8f, 0x7a, 0x76, 0x14, 0x38, + 0x43, 0x3f, 0x70, 0x3a, 0x8e, 0x27, 0x0a, 0x1e, 0xd9, 0xea, 0x9f, 0x77, 0xb6, 0xfa, 0xa7, 0x5b, + 0x8c, 0x1f, 0x9c, 0x4e, 0xb0, 0x6c, 0x82, 0x5f, 0xfc, 0x25, 0x00, 0x00, 0xff, 0xff, 0x0b, 0x43, + 0x9c, 0xb4, 0x94, 0x49, 0x00, 0x00, } func (m *QueryRequest) Marshal() (dAtA []byte, err error) { @@ -6992,6 +7310,18 @@ func (m *Request) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size, err := m.GetPythonUdfStatusRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2 + i-- + dAtA[i] = 0xda if m.RefreshSessionAuthRequest != nil { { size, err := m.RefreshSessionAuthRequest.MarshalToSizedBuffer(dAtA[:i]) @@ -7576,6 +7906,18 @@ func (m *Response) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size, err := m.GetPythonUdfStatus.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2 + i-- + dAtA[i] = 0xe2 if m.RefreshSessionAuthResponse != nil { { size, err := m.RefreshSessionAuthResponse.MarshalToSizedBuffer(dAtA[:i]) @@ -8112,6 +8454,236 @@ func (m *Response) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *GetPythonUdfStatusRequest) 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 *GetPythonUdfStatusRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.ProtoSize() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetPythonUdfStatusRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *GetPythonUdfStatusResponse) 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 *GetPythonUdfStatusResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.ProtoSize() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetPythonUdfStatusResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.NullPolicies) > 0 { + for iNdEx := len(m.NullPolicies) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.NullPolicies[iNdEx]) + copy(dAtA[i:], m.NullPolicies[iNdEx]) + i = encodeVarintQuery(dAtA, i, uint64(len(m.NullPolicies[iNdEx]))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xc2 + } + } + if len(m.Modes) > 0 { + for iNdEx := len(m.Modes) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Modes[iNdEx]) + copy(dAtA[i:], m.Modes[iNdEx]) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Modes[iNdEx]))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xba + } + } + if m.LeaseEpoch != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.LeaseEpoch)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xb0 + } + if m.MaxOwnerHandlerProcesses != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.MaxOwnerHandlerProcesses)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xa8 + } + if m.MaxAccountHandlerProcesses != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.MaxAccountHandlerProcesses)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xa0 + } + if m.MaxHandlerProcesses != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.MaxHandlerProcesses)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x98 + } + if m.MaxExecutionFrameBytes != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.MaxExecutionFrameBytes)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x90 + } + if m.CumulativeAck { + i-- + if m.CumulativeAck { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x88 + } + if m.WindowBatches != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.WindowBatches)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x80 + } + if len(m.TimezoneDatabaseVersion) > 0 { + i -= len(m.TimezoneDatabaseVersion) + copy(dAtA[i:], m.TimezoneDatabaseVersion) + i = encodeVarintQuery(dAtA, i, uint64(len(m.TimezoneDatabaseVersion))) + i-- + dAtA[i] = 0x7a + } + if len(m.TypeDescriptorContract) > 0 { + i -= len(m.TypeDescriptorContract) + copy(dAtA[i:], m.TypeDescriptorContract) + i = encodeVarintQuery(dAtA, i, uint64(len(m.TypeDescriptorContract))) + i-- + dAtA[i] = 0x72 + } + if m.PlanContractVersion != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.PlanContractVersion)) + i-- + dAtA[i] = 0x68 + } + if m.DefinitionSchemaVersion != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.DefinitionSchemaVersion)) + i-- + dAtA[i] = 0x60 + } + if len(m.SDKVersion) > 0 { + i -= len(m.SDKVersion) + copy(dAtA[i:], m.SDKVersion) + i = encodeVarintQuery(dAtA, i, uint64(len(m.SDKVersion))) + i-- + dAtA[i] = 0x5a + } + if len(m.AdapterVersion) > 0 { + i -= len(m.AdapterVersion) + copy(dAtA[i:], m.AdapterVersion) + i = encodeVarintQuery(dAtA, i, uint64(len(m.AdapterVersion))) + i-- + dAtA[i] = 0x52 + } + if len(m.ABIContract) > 0 { + i -= len(m.ABIContract) + copy(dAtA[i:], m.ABIContract) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ABIContract))) + i-- + dAtA[i] = 0x4a + } + if m.ProtocolVersion != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.ProtocolVersion)) + i-- + dAtA[i] = 0x40 + } + if len(m.Reason) > 0 { + i -= len(m.Reason) + copy(dAtA[i:], m.Reason) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Reason))) + i-- + dAtA[i] = 0x3a + } + if len(m.ErrorClass) > 0 { + i -= len(m.ErrorClass) + copy(dAtA[i:], m.ErrorClass) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ErrorClass))) + i-- + dAtA[i] = 0x32 + } + if m.Ready { + i-- + if m.Ready { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x28 + } + if m.AllowUnisolated { + i-- + if m.AllowUnisolated { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x20 + } + if m.Enabled { + i-- + if m.Enabled { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x18 + } + if len(m.Language) > 0 { + i -= len(m.Language) + copy(dAtA[i:], m.Language) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Language))) + i-- + dAtA[i] = 0x12 + } + if len(m.CNUUID) > 0 { + i -= len(m.CNUUID) + copy(dAtA[i:], m.CNUUID) + i = encodeVarintQuery(dAtA, i, uint64(len(m.CNUUID))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *AlterAccountRequest) Marshal() (dAtA []byte, err error) { size := m.ProtoSize() dAtA = make([]byte, size) @@ -8832,12 +9404,12 @@ func (m *TxnInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x12 } - n86, err86 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.CreateAt, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.CreateAt):]) - if err86 != nil { - return 0, err86 + n88, err88 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.CreateAt, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.CreateAt):]) + if err88 != nil { + return 0, err88 } - i -= n86 - i = encodeVarintQuery(dAtA, i, uint64(n86)) + i -= n88 + i = encodeVarintQuery(dAtA, i, uint64(n88)) i-- dAtA[i] = 0xa return len(dAtA) - i, nil @@ -11678,6 +12250,8 @@ func (m *Request) ProtoSize() (n int) { l = m.RefreshSessionAuthRequest.ProtoSize() n += 2 + l + sovQuery(uint64(l)) } + l = m.GetPythonUdfStatusRequest.ProtoSize() + n += 2 + l + sovQuery(uint64(l)) return n } @@ -11852,43 +12426,150 @@ func (m *Response) ProtoSize() (n int) { l = m.RefreshSessionAuthResponse.ProtoSize() n += 2 + l + sovQuery(uint64(l)) } + l = m.GetPythonUdfStatus.ProtoSize() + n += 2 + l + sovQuery(uint64(l)) return n } -func (m *AlterAccountRequest) ProtoSize() (n int) { +func (m *GetPythonUdfStatusRequest) ProtoSize() (n int) { if m == nil { return 0 } var l int _ = l - if m.TenantId != 0 { - n += 1 + sovQuery(uint64(m.TenantId)) - } - l = len(m.Status) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } return n } -func (m *AlterAccountResponse) ProtoSize() (n int) { +func (m *GetPythonUdfStatusResponse) ProtoSize() (n int) { if m == nil { return 0 } var l int _ = l - if m.AlterSuccess { + l = len(m.CNUUID) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Language) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Enabled { n += 2 } - return n -} - -func (m *KillConnRequest) ProtoSize() (n int) { - if m == nil { - return 0 + if m.AllowUnisolated { + n += 2 } - var l int - _ = l + if m.Ready { + n += 2 + } + l = len(m.ErrorClass) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Reason) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.ProtocolVersion != 0 { + n += 1 + sovQuery(uint64(m.ProtocolVersion)) + } + l = len(m.ABIContract) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.AdapterVersion) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.SDKVersion) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.DefinitionSchemaVersion != 0 { + n += 1 + sovQuery(uint64(m.DefinitionSchemaVersion)) + } + if m.PlanContractVersion != 0 { + n += 1 + sovQuery(uint64(m.PlanContractVersion)) + } + l = len(m.TypeDescriptorContract) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.TimezoneDatabaseVersion) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.WindowBatches != 0 { + n += 2 + sovQuery(uint64(m.WindowBatches)) + } + if m.CumulativeAck { + n += 3 + } + if m.MaxExecutionFrameBytes != 0 { + n += 2 + sovQuery(uint64(m.MaxExecutionFrameBytes)) + } + if m.MaxHandlerProcesses != 0 { + n += 2 + sovQuery(uint64(m.MaxHandlerProcesses)) + } + if m.MaxAccountHandlerProcesses != 0 { + n += 2 + sovQuery(uint64(m.MaxAccountHandlerProcesses)) + } + if m.MaxOwnerHandlerProcesses != 0 { + n += 2 + sovQuery(uint64(m.MaxOwnerHandlerProcesses)) + } + if m.LeaseEpoch != 0 { + n += 2 + sovQuery(uint64(m.LeaseEpoch)) + } + if len(m.Modes) > 0 { + for _, s := range m.Modes { + l = len(s) + n += 2 + l + sovQuery(uint64(l)) + } + } + if len(m.NullPolicies) > 0 { + for _, s := range m.NullPolicies { + l = len(s) + n += 2 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *AlterAccountRequest) ProtoSize() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.TenantId != 0 { + n += 1 + sovQuery(uint64(m.TenantId)) + } + l = len(m.Status) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *AlterAccountResponse) ProtoSize() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.AlterSuccess { + n += 2 + } + return n +} + +func (m *KillConnRequest) ProtoSize() (n int) { + if m == nil { + return 0 + } + var l int + _ = l if m.AccountID != 0 { n += 1 + sovQuery(uint64(m.AccountID)) } @@ -15850,6 +16531,39 @@ func (m *Request) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 43: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GetPythonUdfStatusRequest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.GetPythonUdfStatusRequest.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) @@ -17466,6 +18180,742 @@ func (m *Response) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 44: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GetPythonUdfStatus", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.GetPythonUdfStatus.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetPythonUdfStatusRequest) 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 ErrIntOverflowQuery + } + 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: GetPythonUdfStatusRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetPythonUdfStatusRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetPythonUdfStatusResponse) 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 ErrIntOverflowQuery + } + 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: GetPythonUdfStatusResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetPythonUdfStatusResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CNUUID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CNUUID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Language", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Language = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Enabled", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Enabled = bool(v != 0) + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowUnisolated", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.AllowUnisolated = bool(v != 0) + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Ready", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Ready = bool(v != 0) + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ErrorClass", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ErrorClass = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Reason", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Reason = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProtocolVersion", wireType) + } + m.ProtocolVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProtocolVersion |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ABIContract", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ABIContract = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AdapterVersion", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AdapterVersion = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SDKVersion", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SDKVersion = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 12: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DefinitionSchemaVersion", wireType) + } + m.DefinitionSchemaVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.DefinitionSchemaVersion |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 13: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PlanContractVersion", wireType) + } + m.PlanContractVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PlanContractVersion |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 14: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TypeDescriptorContract", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TypeDescriptorContract = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 15: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TimezoneDatabaseVersion", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TimezoneDatabaseVersion = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 16: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field WindowBatches", wireType) + } + m.WindowBatches = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.WindowBatches |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 17: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CumulativeAck", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.CumulativeAck = bool(v != 0) + case 18: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxExecutionFrameBytes", wireType) + } + m.MaxExecutionFrameBytes = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxExecutionFrameBytes |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 19: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxHandlerProcesses", wireType) + } + m.MaxHandlerProcesses = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxHandlerProcesses |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 20: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxAccountHandlerProcesses", wireType) + } + m.MaxAccountHandlerProcesses = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxAccountHandlerProcesses |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 21: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxOwnerHandlerProcesses", wireType) + } + m.MaxOwnerHandlerProcesses = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxOwnerHandlerProcesses |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 22: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LeaseEpoch", wireType) + } + m.LeaseEpoch = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LeaseEpoch |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 23: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Modes", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Modes = append(m.Modes, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 24: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NullPolicies", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NullPolicies = append(m.NullPolicies, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) diff --git a/pkg/queryservice/client/query_client.go b/pkg/queryservice/client/query_client.go index eaec510a185fe..4ff2dd104e8be 100644 --- a/pkg/queryservice/client/query_client.go +++ b/pkg/queryservice/client/query_client.go @@ -66,6 +66,7 @@ var methodVersions = map[pb.CmdMethod]int64{ pb.CmdMethod_ISCPDrainConsumer: defines.MORPCVersion4, pb.CmdMethod_IcebergCacheInvalidate: defines.MORPCVersion4, pb.CmdMethod_MongoDBClientRetire: defines.MORPCVersion5, + pb.CmdMethod_GetPythonUdfStatus: defines.MORPCVersion72, } type queryClient struct { diff --git a/pkg/sql/colexec/evalExpression.go b/pkg/sql/colexec/evalExpression.go index d55a77bce14ae..3f5ed40c5a95b 100644 --- a/pkg/sql/colexec/evalExpression.go +++ b/pkg/sql/colexec/evalExpression.go @@ -350,6 +350,29 @@ func newExpressionExecutorWithAllocation( return executor, nil case *plan.Expr_F: + if routineCall := t.F.GetRoutineCall(); routineCall != nil { + parameters := make([]ExpressionExecutor, len(t.F.Args)) + for i := range parameters { + child, childErr := newExpressionExecutorWithAllocation(proc, t.F.Args[i], selection, buildCtx) + if childErr != nil { + for j := 0; j < i; j++ { + parameters[j].Free() + } + return nil, childErr + } + parameters[i] = child + } + external, externalErr := newExternalRoutineEval(proc, routineCall, parameters, selection) + if externalErr != nil { + for _, parameter := range parameters { + if parameter != nil { + parameter.Free() + } + } + return nil, externalErr + } + return external, nil + } overloadID := t.F.GetFunc().GetObj() overload, err := function.GetFunctionById(proc.Ctx, overloadID) if err != nil { @@ -1417,15 +1440,10 @@ func (expr *FunctionExpressionExecutor) evalSelectedRows( } for i, parameter := range expr.parameterResults { // Constants, folded vectors, and list/vector literals are not row-aligned. - // They must be passed through unchanged; only column and non-folded - // function results map one-to-one to the input batch rows. - rowAligned := false - switch executor := expr.parameterExecutor[i].(type) { - case *ColumnExpressionExecutor: - rowAligned = true - case *FunctionExpressionExecutor: - rowAligned = !executor.folded.canFold - } + // They must be passed through unchanged. ExternalRoutineEval is included + // in the row-aligned set because it owns selection compaction and scatters + // its result back to the caller's row domain before returning. + rowAligned := expressionExecutorIsRowAligned(expr.parameterExecutor[i]) if rowAligned && !parameter.IsConst() { selected := expr.selectedParameterVectors[i] if selected == nil { @@ -1535,6 +1553,29 @@ func (expr *FunctionExpressionExecutor) evalSelectedRows( return result, nil } +// expressionExecutorIsRowAligned reports whether Eval returns one physical +// value for every input row, even when it was called with a partial selection. +// ExternalRoutineEval owns selection itself and scatters its result back to +// the original row domain. Treating it as a constant here would pass the +// un-compacted vector to a surrounding expression and make a masked nested +// call read values from the wrong rows. +func expressionExecutorIsRowAligned(executor ExpressionExecutor) bool { + switch executor := executor.(type) { + case *ColumnExpressionExecutor: + return true + case *ExternalRoutineEval: + return true + case *FunctionExpressionExecutor: + return !executor.folded.canFold + case *memoExpressionExecutor: + return expressionExecutorIsRowAligned(executor.state.executor) + case *memoRootExpressionExecutor: + return expressionExecutorIsRowAligned(executor.executor) + default: + return false + } +} + func (expr *FunctionExpressionExecutor) Eval(proc *process.Process, batches []*batch.Batch, selectList []bool) (*vector.Vector, error) { if len(batches) == 0 { batches = []*batch.Batch{batch.EmptyForConstFoldBatch} diff --git a/pkg/sql/colexec/external_routine_eval.go b/pkg/sql/colexec/external_routine_eval.go new file mode 100644 index 0000000000000..242dd13eb38d7 --- /dev/null +++ b/pkg/sql/colexec/external_routine_eval.go @@ -0,0 +1,764 @@ +// Copyright 2026 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 ( + "encoding/json" + "os" + "sort" + "strconv" + "strings" + "sync" + "time" + + "github.com/matrixorigin/matrixone/pkg/udf/udferr" + "github.com/matrixorigin/matrixone/pkg/util/errutil" + + "github.com/google/uuid" + "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" + planpb "github.com/matrixorigin/matrixone/pkg/pb/plan" + "github.com/matrixorigin/matrixone/pkg/sql/plan/function" + "github.com/matrixorigin/matrixone/pkg/udf" + pythonudf "github.com/matrixorigin/matrixone/pkg/udf/python" + "github.com/matrixorigin/matrixone/pkg/vm/process" +) + +// ExternalRoutineEval is the physical boundary for a typed RoutineCall. It +// owns argument evaluation, selection compaction/scatter, strict NULL +// guarding, and the result lifetime. The Flight gateway only sees the +// already-admitted selected rows and never owns SQL CASE semantics. +type ExternalRoutineEval struct { + mp *mpool.MPool + allocation *vector.AllocationAccountSelection + call *planpb.RoutineCall + resultType types.Type + + parameterExecutor []ExpressionExecutor + parameterResults []*vector.Vector + result vector.FunctionResultWrapper + + selectedRows []int64 + selectedParameters []*vector.Vector + selectedOwned []*vector.Vector + selectedResult vector.FunctionResultWrapper + selectedNull *vector.Vector + generation uint64 + executionMu sync.Mutex + freed bool + groupMu sync.Mutex + groupStatementID string + groupID string + groupEpoch uint64 +} + +func newExternalRoutineEval( + proc *process.Process, + call *planpb.RoutineCall, + parameters []ExpressionExecutor, + allocation *vector.AllocationAccountSelection, +) (*ExternalRoutineEval, error) { + if proc == nil || proc.Base == nil { + return nil, udferr.Newf("python udf: evaluator has no process") + } + if err := validateRoutineCall(call); err != nil { + return nil, err + } + if len(call.ArgumentTypes) != len(parameters) { + return nil, udferr.Newf("python udf: typed routine has %d argument descriptors but %d bound arguments", len(call.ArgumentTypes), len(parameters)) + } + resultType := planTypeToSQL(call.ReturnType) + result, err := vector.NewFunctionResultWrapperWithAllocation(resultType, proc.Mp(), allocation) + if err != nil { + return nil, err + } + return &ExternalRoutineEval{ + mp: proc.Mp(), + allocation: allocation, + call: call, + resultType: resultType, + parameterExecutor: parameters, + parameterResults: make([]*vector.Vector, len(parameters)), + result: result, + }, nil +} + +func validateRoutineCall(call *planpb.RoutineCall) error { + if call == nil || call.FunctionRef == nil || call.FunctionRef.FunctionId == 0 || + call.FunctionRef.DatabaseId == 0 || call.FunctionRef.Revision == 0 || call.FunctionRef.NamespaceVersion == 0 { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: typed routine call has no exact FunctionRef") + } + if call.ReturnType.Id == int32(types.T_any) { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: typed routine call has no return descriptor") + } + if call.ContractVersion != udf.PythonPlanContractVersion || call.Language != udf.LanguagePython { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: unsupported typed routine call contract") + } + if call.Volatility != "VOLATILE" { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python routine must be VOLATILE") + } + if !call.MayError || call.SecurityMode != "INVOKER" || call.Leakproof { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python routine semantic contract is not supported") + } + if call.CallsiteId == "" || len(call.CallsiteId) > 256 || strings.ContainsAny(call.CallsiteId, "\r\n") { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: typed routine call has no valid callsite id") + } + if len(call.Context) != 0 { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: typed routine call contains execution context") + } + python := call.GetPython() + if python == nil { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: typed routine call has no Python implementation") + } + if python.Source != "" { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: typed Python plan contains source; rebind from the current artifact contract") + } + if python.Handler == "" || + python.AbiContract != udf.PythonABIContract || + python.AdapterVersion != udf.PythonAdapterVersion || + python.SdkVersion != udf.PythonSDKVersion || + python.DefinitionSchemaVersion != udf.PythonDefinitionSchemaVersion { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: typed Python implementation contract is not supported") + } + if python.Mode != "SCALAR" && python.Mode != "VECTOR" { + return udferr.Newf("python udf: unsupported typed call mode %q", python.Mode) + } + if python.NullPolicy != udf.NullCallHandler && python.NullPolicy != udf.NullReturnNull { + return udferr.Newf("python udf: unsupported typed NULL policy %q", python.NullPolicy) + } + if call.NullPolicy != python.NullPolicy { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: typed call NULL policy does not match its implementation") + } + if !udf.IsSHA256Digest(python.ArtifactDigest) || !udf.IsSHA256Digest(python.EnvironmentDigest) { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: typed Python implementation has invalid artifact/environment digest") + } + if !udf.IsSHA256Digest(python.DefinitionFingerprint) { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: typed Python implementation has invalid definition fingerprint") + } + arguments := make([]pythonudf.TypeDescriptor, len(call.ArgumentTypes)) + for i, argumentType := range call.ArgumentTypes { + if argumentType == nil { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: typed Python argument %d is nil", i) + } + descriptor, err := function.NewPythonTypeDescriptor(planTypeToSQL(*argumentType)) + if err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: typed Python argument %d is unsupported", i) + } + arguments[i] = descriptor + } + result, err := function.NewPythonTypeDescriptor(planTypeToSQL(call.ReturnType)) + if err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: typed Python return descriptor is unsupported") + } + fingerprint, err := pythonudf.DefinitionFingerprint( + int(python.DefinitionSchemaVersion), python.Handler, python.Mode, python.NullPolicy, + python.AbiContract, python.AdapterVersion, python.ArtifactDigest, + python.EnvironmentDigest, python.SdkVersion, arguments, result, + ) + if err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: invalid typed Python definition") + } + if fingerprint != python.DefinitionFingerprint { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: typed Python definition fingerprint mismatch") + } + + return nil +} + +func (e *ExternalRoutineEval) Eval(proc *process.Process, batches []*batch.Batch, selectList []bool) (*vector.Vector, error) { + return e.eval(proc, batches, selectList, false) +} + +func (e *ExternalRoutineEval) eval(proc *process.Process, batches []*batch.Batch, selectList []bool, transfer bool) (output *vector.Vector, evalErr error) { + if e == nil || proc == nil || proc.Base == nil { + return nil, udferr.Newf("python udf: evaluator has no process") + } + e.executionMu.Lock() + defer e.executionMu.Unlock() + if e.freed { + return nil, udferr.Newf("python udf: evaluator is freed") + } + // Transfer under executionMu, before a concurrent Eval/Free can reuse the + // backing. The wrapper retains its allocation policy for the next result. + defer func() { + if transfer && evalErr == nil { + e.result.SetResultVector(nil) + } + }() + + if err := validateRoutineCall(e.call); err != nil { + return nil, err + } + accountID, err := defines.GetAccountId(proc.Ctx) + if err != nil { + return nil, err + } + if uint64(accountID) != e.call.FunctionRef.AccountId { + return nil, udferr.Newf("python udf: FunctionRef account does not match the execution account") + } + python := e.call.GetPython() + rowCount, err := externalRoutineRowCount(python.Mode, batches) + if err != nil { + return nil, err + } + // Keep the row-domain contract strict even for an empty batch. Returning + // early before this check would let a stale selection mask cross the + // physical boundary and hide a relation-position bug in the caller. + if selectList != nil && len(selectList) != rowCount { + return nil, udferr.Newf("external routine selection has %d rows, expected %d", len(selectList), rowCount) + } + if rowCount == 0 { + if err := e.result.PreExtendAndReset(0); err != nil { + return nil, err + } + return e.result.GetResultVector(), nil + } + + if noRowsSelected(selectList, rowCount) { + return e.nullResult(rowCount) + } + + for i, parameter := range e.parameterExecutor { + var err error + e.parameterResults[i], err = parameter.Eval(proc, batches, selectList) + if err != nil { + return nil, err + } + } + if err := validateExternalRoutineInputs(e.parameterResults, e.call, rowCount); err != nil { + return nil, err + } + e.selectedRows = e.selectedRows[:0] + for row := 0; row < rowCount; row++ { + selected := selectList == nil || selectList[row] + if selected && python.NullPolicy == udf.NullReturnNull && routineHasNullAt(e.parameterResults, row) { + selected = false + } + if selected { + e.selectedRows = append(e.selectedRows, int64(row)) + } + } + if len(e.selectedRows) == 0 { + return e.nullResult(rowCount) + } + + inputs, err := e.compactParameters(proc, rowCount) + if err != nil { + // compactParameters may have already materialized earlier selected + // arguments before a later column fails. There is no execution defer + // until compaction succeeds, so release that partial ownership here. + e.releaseOwnedParameters() + return nil, err + } + defer e.releaseOwnedParameters() + + selectedResult := e.result + if len(e.selectedRows) != rowCount { + if e.selectedResult == nil { + e.selectedResult, err = vector.NewFunctionResultWrapperWithAllocation(e.resultType, e.mp, e.allocation) + if err != nil { + return nil, err + } + } + selectedResult = e.selectedResult + } + if err := selectedResult.PreExtendAndReset(len(e.selectedRows)); err != nil { + return nil, err + } + context, err := buildRoutineContext(proc) + if err != nil { + return nil, err + } + statementContext, err := udf.StatementContextFromMap(context) + if err != nil { + return nil, err + } + if err := e.attachInvocationGroup(context, proc.QueryId()); err != nil { + return nil, err + } + tuple, err := function.NewInvocationTuple(context, proc.QueryId(), accountID) + if err != nil { + return nil, err + } + args := make([]types.Type, len(e.call.ArgumentTypes)) + for i, typ := range e.call.ArgumentTypes { + args[i] = planTypeToSQL(*typ) + } + invocation := &udf.Invocation{ + FunctionRef: udf.FunctionRef{ + AccountID: pythonFunctionAccountID(e.call), + DatabaseID: e.call.FunctionRef.DatabaseId, + FunctionID: e.call.FunctionRef.FunctionId, + Revision: e.call.FunctionRef.Revision, + NamespaceVersion: e.call.FunctionRef.NamespaceVersion, + }, + Language: udf.LanguagePython, + Handler: python.Handler, + Args: args, + ReturnType: e.resultType, + Inputs: inputs, + Length: len(e.selectedRows), + Mode: python.Mode, + NullPolicy: python.NullPolicy, + ABIContract: python.AbiContract, + AdapterVersion: python.AdapterVersion, + SDKVersion: python.SdkVersion, + DefinitionSchemaVersion: int(python.DefinitionSchemaVersion), + ArtifactDigest: python.ArtifactDigest, + EnvironmentDigest: python.EnvironmentDigest, + DefinitionFingerprint: python.DefinitionFingerprint, + Context: context, + CallsiteID: e.call.CallsiteId, + MayError: e.call.MayError, + SecurityMode: e.call.SecurityMode, + Leakproof: e.call.Leakproof, + StatementContext: statementContext, + SecurityFrame: &udf.SecurityFrame{ + ContractVersion: udf.SecurityFrameContractVersion, + Mode: e.call.SecurityMode, + InvokerUserID: defines.GetUserId(proc.Ctx), + InvokerRoleID: defines.GetRoleId(proc.Ctx), + EffectiveUserID: defines.GetUserId(proc.Ctx), + EffectiveRoleID: defines.GetRoleId(proc.Ctx), + }, + Tuple: tuple, + } + if proc.Base.UdfService == nil { + return nil, udferr.Newf("RESOURCE_UNAVAILABLE: Python UDF runtime is not enabled") + } + if err := proc.Base.UdfService.Execute(proc.Ctx, invocation, selectedResult, proc.Mp()); err != nil { + return nil, err + } + if selectedResult.ResultLength() != len(e.selectedRows) { + return nil, udferr.Newf("python udf: runtime produced %d result rows, expected %d", selectedResult.ResultLength(), len(e.selectedRows)) + } + if selectedResult.GetResultVector() == nil { + return nil, udferr.Newf("python udf: runtime returned no result vector") + } + if len(e.selectedRows) == rowCount { + return e.result.GetResultVector(), nil + } + return e.scatter(proc, selectedResult.GetResultVector(), rowCount) +} + +// attachInvocationGroup gives one physical evaluator ownership of a reusable +// execution group for one statement. Each invocation still has its own +// InvocationID and monotonically increasing GroupEpoch, so a completed epoch +// cannot be reopened and a later batch cannot consume the previous member's +// resources. ResetForNextQuery discards the group identity; an evaluator that +// has no statement query id uses a fresh one-shot group because it cannot prove +// that two calls belong to the same statement. +func (e *ExternalRoutineEval) attachInvocationGroup(context map[string]string, queryID string) error { + if context == nil { + return udferr.Newf("python udf: invocation context is unavailable") + } + e.groupMu.Lock() + defer e.groupMu.Unlock() + if queryID == "" { + group, err := uuid.NewV7() + if err != nil { + return errutil.Wrapf(err, "python udf: create execution group fence") + } + context["group_id"] = "python/" + group.String() + context["group_epoch"] = "1" + return nil + } + if e.groupID == "" || e.groupStatementID != queryID { + group, err := uuid.NewV7() + if err != nil { + return errutil.Wrapf(err, "python udf: create execution group fence") + } + e.groupStatementID = queryID + e.groupID = queryID + "/python/" + group.String() + e.groupEpoch = 0 + } + if e.groupEpoch == ^uint64(0) { + return udferr.Newf("RESOURCE_EXHAUSTED: Python UDF execution group epoch overflow") + } + e.groupEpoch++ + context["group_id"] = e.groupID + context["group_epoch"] = strconv.FormatUint(e.groupEpoch, 10) + return nil +} + +func pythonFunctionAccountID(call *planpb.RoutineCall) uint64 { + if call == nil || call.FunctionRef == nil { + return 0 + } + return call.FunctionRef.AccountId +} + +func (e *ExternalRoutineEval) compactParameters(proc *process.Process, rowCount int) ([]*vector.Vector, error) { + if len(e.selectedRows) == 0 { + return nil, nil + } + e.selectedParameters = e.selectedParameters[:0] + for i, input := range e.parameterResults { + if input == nil { + return nil, udferr.Newf("external routine parameter %d is nil", i) + } + if input.IsConst() || len(e.selectedRows) == rowCount { + e.selectedParameters = append(e.selectedParameters, input) + continue + } + selected, err := vector.NewOffHeapVecWithTypeAndAllocation(*input.GetType(), e.allocation) + if err != nil { + return nil, err + } + selected.SetIsBin(input.GetIsBin()) + if err := selected.Union(input, e.selectedRows, proc.Mp()); err != nil { + selected.Free(proc.Mp()) + return nil, err + } + e.selectedOwned = append(e.selectedOwned, selected) + e.selectedParameters = append(e.selectedParameters, selected) + } + return e.selectedParameters, nil +} + +func validateExternalRoutineInputs(inputs []*vector.Vector, call *planpb.RoutineCall, rowCount int) error { + if len(inputs) != len(call.ArgumentTypes) { + return udferr.Newf("python udf: evaluated input count %d does not match routine argument count %d", len(inputs), len(call.ArgumentTypes)) + } + for index, input := range inputs { + if input == nil || input.GetType() == nil { + return udferr.Newf("python udf: evaluated input vector %d has no type", index) + } + if input.Length() == 0 || (!input.IsConst() && input.Length() < rowCount) { + return udferr.Newf("python udf: evaluated input vector %d has %d rows, expected at least %d", index, input.Length(), rowCount) + } + expected, err := function.NewPythonTypeDescriptor(planTypeToSQL(*call.ArgumentTypes[index])) + if err != nil { + return errutil.Wrapf(err, "python udf: invalid argument descriptor %d", index) + } + actual, err := function.NewPythonTypeDescriptor(*input.GetType()) + if err != nil { + return errutil.Wrapf(err, "python udf: evaluated input vector %d has unsupported type", index) + } + expectedFingerprint, err := expected.Fingerprint() + if err != nil { + return err + } + actualFingerprint, err := actual.Fingerprint() + if err != nil { + return err + } + if expectedFingerprint != actualFingerprint { + return udferr.Newf("python udf: evaluated input vector %d type %s does not match the frozen descriptor", index, input.GetType().DescString()) + } + } + return nil +} + +func (e *ExternalRoutineEval) releaseOwnedParameters() { + for _, selected := range e.selectedOwned { + if selected != nil { + selected.Free(e.mp) + } + } + e.selectedOwned = e.selectedOwned[:0] +} + +func (e *ExternalRoutineEval) nullResult(rowCount int) (*vector.Vector, error) { + if err := e.result.PreExtendAndReset(rowCount); err != nil { + return nil, err + } + result := e.result.GetResultVector() + result.SetAllNulls(rowCount) + result.SetLength(rowCount) + return result, nil +} + +func (e *ExternalRoutineEval) scatter(proc *process.Process, selected *vector.Vector, rowCount int) (*vector.Vector, error) { + if err := e.result.PreExtendAndReset(rowCount); err != nil { + return nil, err + } + result := e.result.GetResultVector() + result.ResetWithSameType() + if e.selectedNull == nil || *e.selectedNull.GetType() != *selected.GetType() { + if e.selectedNull != nil { + e.selectedNull.Free(e.mp) + } + e.selectedNull = vector.NewConstNull(*selected.GetType(), 1, proc.Mp()) + } + selectedRow := 0 + for row := 0; row < rowCount; row++ { + if selectedRow < len(e.selectedRows) && e.selectedRows[selectedRow] == int64(row) { + if err := result.UnionOne(selected, int64(selectedRow), proc.Mp()); err != nil { + return nil, err + } + selectedRow++ + } else if err := result.UnionOne(e.selectedNull, 0, proc.Mp()); err != nil { + return nil, err + } + } + return result, nil +} + +func (e *ExternalRoutineEval) EvalWithoutResultReusing(proc *process.Process, batches []*batch.Batch, selectList []bool) (*vector.Vector, error) { + return e.eval(proc, batches, selectList, true) +} + +func (e *ExternalRoutineEval) ResetForNextQuery() { + if e == nil { + return + } + e.executionMu.Lock() + defer e.executionMu.Unlock() + if e.freed { + return + } + e.generation++ + e.groupMu.Lock() + e.groupStatementID = "" + e.groupID = "" + e.groupEpoch = 0 + e.groupMu.Unlock() + for _, parameter := range e.parameterExecutor { + parameter.ResetForNextQuery() + } + e.parameterResults = make([]*vector.Vector, len(e.parameterExecutor)) +} + +func (e *ExternalRoutineEval) Free() { + if e == nil { + return + } + e.executionMu.Lock() + defer e.executionMu.Unlock() + if e.freed { + return + } + e.freed = true + for _, parameter := range e.parameterExecutor { + if parameter != nil { + parameter.Free() + } + } + if e.result != nil { + e.result.Free() + } + if e.selectedResult != nil { + e.selectedResult.Free() + } + if e.selectedNull != nil { + e.selectedNull.Free(e.mp) + } + e.releaseOwnedParameters() +} + +func (e *ExternalRoutineEval) IsColumnExpr() bool { return false } +func (e *ExternalRoutineEval) TypeName() string { return "external routine eval" } + +func routineHasNullAt(inputs []*vector.Vector, row int) bool { + for _, input := range inputs { + if input == nil || input.IsNull(uint64(row)) { + return true + } + } + return false +} + +func planTypeToSQL(typ planpb.Type) types.Type { + return types.NewWithCharset(types.T(typ.Id), typ.Width, typ.Scale, uint8(typ.Charset)) +} + +func externalRoutineRowCount(mode string, batches []*batch.Batch) (int, error) { + if len(batches) > 0 { + // ExpressionExecutor uses the first batch as the logical row domain and + // uses relation positions to read the other batches. Join operators pass + // several one-to-one materialized relation batches, so rejecting every + // multi-batch call would make a Python routine unusable in JOIN ON. A + // different cardinality is still a contract violation: silently selecting + // batches[0] would let an argument from another relation lose rows. + rowCount := -1 + for index, input := range batches { + if input == nil { + return 0, udferr.Newf("external routine input batch %d is nil", index) + } + if rowCount < 0 { + rowCount = input.RowCount() + continue + } + if input.RowCount() != rowCount { + return 0, udferr.Newf("python udf: external routine input batch %d has %d rows, expected %d for the logical row domain", index, input.RowCount(), rowCount) + } + } + return rowCount, nil + } + if mode == "VECTOR" { + return 0, udferr.Newf("python udf: zero-argument VECTOR requires an input batch with num_rows") + } + return 1, nil +} + +// buildRoutineContext freezes the statement-visible values at the physical +// execution boundary. The plan carries only immutable routine metadata; it +// must not carry a statement identity or mutable session values because a +// prepared plan can outlive both. +func buildRoutineContext(proc *process.Process) (map[string]string, error) { + if proc == nil || proc.Base == nil { + return nil, udferr.Newf("python udf: process is unavailable for statement context") + } + context := make(map[string]string) + // The current query id is stable for the statement and changes for every + // prepared execution; NewInvocationTuple generates one only for internal + // tests that have no query id. It is control metadata, never plan data. + if queryID := proc.QueryId(); queryID != "" { + context["statement_id"] = queryID + } else { + delete(context, "statement_id") + } + queryStart := proc.GetStmtProfile().GetQueryStart() + if queryStart.IsZero() { + // Internal/background processes do not always install a statement + // profile. UnixTime is process-scoped and therefore deterministic for + // the lifetime of that process; a real frontend statement always uses + // its query start above. + if proc.Base.UnixTime == 0 { + return nil, udferr.Newf("python udf: statement timestamp is unavailable") + } + queryStart = time.Unix(0, proc.Base.UnixTime) + } + context["statement_timestamp_utc"] = strconv.FormatInt(queryStart.UTC().UnixMicro(), 10) + + location := proc.GetSessionInfo().TimeZone + if location == nil { + return nil, udferr.Newf("python udf: session timezone is unavailable") + } + zoneName := location.String() + var timezoneErr error + if zoneName == "" || zoneName == "SYSTEM" { + return nil, udferr.Newf("python udf: session timezone is not a stable IANA identity") + } + if zoneName == "Local" { + zoneName, location, timezoneErr = resolveSystemTimezone() + if timezoneErr != nil { + return nil, timezoneErr + } + } + if zoneName == "FixedZone" { + _, offset := queryStart.In(location).Zone() + if offset%60 != 0 { + return nil, udferr.Newf("python udf: fixed session timezone offset must be a whole number of minutes") + } + context["session_timezone_kind"] = "FIXED_OFFSET" + context["session_timezone_offset_minutes"] = formatTimezoneOffsetMinutes(offset / 60) + delete(context, "session_timezone_name") + delete(context, "session_timezone_tzdb_version") + } else { + context["session_timezone_kind"] = "IANA" + context["session_timezone_name"] = zoneName + tzdbVersion, err := udf.TimezoneDatabaseVersion() + if err != nil { + return nil, err + } + context["session_timezone_tzdb_version"] = tzdbVersion + delete(context, "session_timezone_offset_minutes") + } + + mode := sessionSQLMode(proc) + encodedMode, err := json.Marshal(mode) + if err != nil { + return nil, errutil.Wrapf(err, "python udf: encode sql_mode context") + } + context["sql_mode"] = string(encodedMode) + info := proc.GetSessionInfo() + context["current_user"] = info.User + context["connection_collation"] = info.GetCollation() + if info.Database != "" { + context["current_database"] = info.Database + } else { + delete(context, "current_database") + } + if info.Role != "" { + context["current_role"] = info.Role + } else { + delete(context, "current_role") + } + return context, nil +} + +// resolveSystemTimezone turns the frontend's SYSTEM location into the IANA +// identity that is part of the Python call contract. time.Local intentionally +// hides that identity behind the name "Local"; accepting that name would make +// two workers interpret a DST boundary from different host configuration. +// Prefer an explicit TZ setting, then use the conventional /etc/localtime +// symlink. A regular localtime file has no portable IANA identity and fails +// closed until the deployment supplies one. +func resolveSystemTimezone() (string, *time.Location, error) { + candidates := []string{strings.TrimSpace(os.Getenv("TZ"))} + if link, err := os.Readlink("/etc/localtime"); err == nil { + const marker = "/zoneinfo/" + if index := strings.Index(link, marker); index >= 0 { + candidates = append(candidates, link[index+len(marker):]) + } + } + for _, candidate := range candidates { + candidate = strings.TrimPrefix(candidate, ":") + candidate = strings.TrimPrefix(candidate, "posix/") + candidate = strings.TrimPrefix(candidate, "right/") + if candidate == "" || candidate == "Local" || candidate == "SYSTEM" || strings.HasPrefix(candidate, "/") || strings.Contains(candidate, "..") { + continue + } + location, err := time.LoadLocation(candidate) + if err == nil { + return candidate, location, nil + } + } + return "", nil, udferr.Newf("python udf: SYSTEM timezone has no stable IANA identity") +} + +func formatTimezoneOffsetMinutes(offset int) string { + if offset >= 0 { + return "+" + strconv.Itoa(offset) + } + return strconv.Itoa(offset) +} + +func sessionSQLMode(proc *process.Process) []string { + value := "" + if proc != nil && proc.GetSessionInfo() != nil { + value = proc.GetSessionInfo().SqlMode + } + if proc != nil { + if resolve := proc.GetResolveVariableFunc(); resolve != nil { + if resolved, err := resolve("sql_mode", true, false); err == nil { + if text, ok := resolved.(string); ok { + value = text + } + } + } + } + if value == process.EmptySqlModeSentinel { + value = "" + } + seen := make(map[string]struct{}) + for _, item := range strings.FieldsFunc(value, func(r rune) bool { return r == ',' || r == ' ' || r == '\t' || r == '\n' || r == '\r' }) { + item = strings.ToUpper(strings.TrimSpace(item)) + if item != "" { + seen[item] = struct{}{} + } + } + result := make([]string, 0, len(seen)) + for item := range seen { + result = append(result, item) + } + sort.Strings(result) + return result +} diff --git a/pkg/sql/colexec/external_routine_eval_test.go b/pkg/sql/colexec/external_routine_eval_test.go new file mode 100644 index 0000000000000..d905cb55113ac --- /dev/null +++ b/pkg/sql/colexec/external_routine_eval_test.go @@ -0,0 +1,821 @@ +// Copyright 2026 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" + "encoding/json" + "errors" + "strconv" + "testing" + "time" + + "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" + planpb "github.com/matrixorigin/matrixone/pkg/pb/plan" + "github.com/matrixorigin/matrixone/pkg/sql/plan/function" + "github.com/matrixorigin/matrixone/pkg/testutil" + "github.com/matrixorigin/matrixone/pkg/udf" + "github.com/matrixorigin/matrixone/pkg/udf/python" + "github.com/matrixorigin/matrixone/pkg/vm/process" + "github.com/stretchr/testify/require" +) + +type externalRoutineTestExecutor struct { + vector *vector.Vector + evalSeen *int + err error +} + +func (e *externalRoutineTestExecutor) Eval(_ *process.Process, _ []*batch.Batch, _ []bool) (*vector.Vector, error) { + if e.evalSeen != nil { + *e.evalSeen++ + } + return e.vector, e.err +} + +func (e *externalRoutineTestExecutor) EvalWithoutResultReusing(proc *process.Process, batches []*batch.Batch, selectList []bool) (*vector.Vector, error) { + return e.Eval(proc, batches, selectList) +} + +func (e *externalRoutineTestExecutor) ResetForNextQuery() {} +func (e *externalRoutineTestExecutor) Free() {} +func (e *externalRoutineTestExecutor) IsColumnExpr() bool { return true } +func (e *externalRoutineTestExecutor) TypeName() string { return "test input" } + +type externalRoutineCaptureRuntime struct { + invocation *udf.Invocation + invocations []udf.Invocation +} + +type externalRoutineEmptySuccessRuntime struct{} + +type externalRoutineErrorRuntime struct{ err error } + +func (r *externalRoutineEmptySuccessRuntime) Language() string { return udf.LanguagePython } + +func (r *externalRoutineEmptySuccessRuntime) Execute(_ context.Context, _ *udf.Invocation, _ vector.FunctionResultWrapper, _ *mpool.MPool) error { + return nil +} + +func (r *externalRoutineErrorRuntime) Language() string { return udf.LanguagePython } + +func (r *externalRoutineErrorRuntime) Execute(_ context.Context, _ *udf.Invocation, _ vector.FunctionResultWrapper, _ *mpool.MPool) error { + return r.err +} + +func (r *externalRoutineCaptureRuntime) Language() string { return udf.LanguagePython } + +func (r *externalRoutineCaptureRuntime) Execute(_ context.Context, invocation *udf.Invocation, result vector.FunctionResultWrapper, mp *mpool.MPool) error { + r.invocation = invocation + r.invocations = append(r.invocations, *invocation) + output := result.(*vector.FunctionResult[int64]) + input := invocation.Inputs[0] + values := vector.MustFixedColNoTypeCheck[int64](input) + for row, value := range values[:invocation.Length] { + if err := output.Append(value+1, input.IsNull(uint64(row))); err != nil { + return err + } + } + return nil +} + +func TestExternalRoutineEvalReusesGroupWithNewEpoch(t *testing.T) { + proc := testutil.NewProcess(t) + defer proc.Free() + proc.SetQueryId("reentry-runtime-query") + proc.GetSessionInfo().TimeZone = time.FixedZone("FixedZone", 8*60*60) + proc.GetSessionInfo().User = "root" + proc.Base.StmtProfile = &process.StmtProfile{} + proc.GetStmtProfile().SetQueryStart(time.Date(2026, 9, 10, 1, 2, 3, 4000, time.UTC)) + + input := vector.NewVec(types.T_int64.ToType()) + defer input.Free(proc.Mp()) + require.NoError(t, vector.AppendFixed(input, int64(1), false, proc.Mp())) + inputBatch := batch.NewWithSize(0) + inputBatch.SetRowCount(1) + + runtime := &externalRoutineCaptureRuntime{} + proc.Base.UdfService = runtime + evaluator, err := newExternalRoutineEval(proc, testExternalRoutineCall(t, "SCALAR", udf.NullCallHandler), []ExpressionExecutor{ + &externalRoutineTestExecutor{vector: input}, + }, nil) + require.NoError(t, err) + defer evaluator.Free() + + _, err = evaluator.Eval(proc, []*batch.Batch{inputBatch}, []bool{true}) + require.NoError(t, err) + _, err = evaluator.Eval(proc, []*batch.Batch{inputBatch}, []bool{true}) + require.NoError(t, err) + require.Len(t, runtime.invocations, 2) + require.Equal(t, runtime.invocations[0].Tuple.GroupID, runtime.invocations[1].Tuple.GroupID) + require.Equal(t, uint64(1), runtime.invocations[0].Tuple.GroupEpoch) + require.Equal(t, uint64(2), runtime.invocations[1].Tuple.GroupEpoch) + require.NotEqual(t, runtime.invocations[0].Tuple.InvocationID, runtime.invocations[1].Tuple.InvocationID) + + evaluator.ResetForNextQuery() + _, err = evaluator.Eval(proc, []*batch.Batch{inputBatch}, []bool{true}) + require.NoError(t, err) + require.Len(t, runtime.invocations, 3) + require.NotEqual(t, runtime.invocations[1].Tuple.GroupID, runtime.invocations[2].Tuple.GroupID) + require.Equal(t, uint64(1), runtime.invocations[2].Tuple.GroupEpoch) +} + +func TestExternalRoutineEvalOwnsSelectionAndStrictNullGuard(t *testing.T) { + proc := testutil.NewProcess(t) + proc.SetQueryId("runtime-query") + proc.GetSessionInfo().TimeZone = time.FixedZone("FixedZone", 8*60*60) + proc.GetSessionInfo().User = "alice" + proc.GetSessionInfo().Database = "app" + proc.GetSessionInfo().Role = "writer" + proc.GetSessionInfo().SqlMode = "STRICT_TRANS_TABLES,ANSI" + proc.Base.StmtProfile = &process.StmtProfile{} + proc.GetStmtProfile().SetQueryStart(time.Date(2026, 9, 10, 1, 2, 3, 4000, time.FixedZone("input", 8*60*60))) + + mp := proc.Mp() + input := vector.NewVec(types.T_int64.ToType()) + defer input.Free(mp) + require.NoError(t, vector.AppendFixed(input, int64(1), false, mp)) + require.NoError(t, vector.AppendFixed(input, int64(0), true, mp)) + require.NoError(t, vector.AppendFixed(input, int64(3), false, mp)) + + runtime := &externalRoutineCaptureRuntime{} + proc.Base.UdfService = runtime + call := testExternalRoutineCall(t, "SCALAR", udf.NullReturnNull) + evaluator, err := newExternalRoutineEval(proc, call, []ExpressionExecutor{ + &externalRoutineTestExecutor{vector: input}, + }, nil) + require.NoError(t, err) + defer evaluator.Free() + + inputBatch := batch.NewWithSize(0) + inputBatch.SetRowCount(3) + result, err := evaluator.Eval(proc, []*batch.Batch{inputBatch}, []bool{true, true, true}) + require.NoError(t, err) + require.Equal(t, 2, runtime.invocation.Length, "the parent evaluator removes strict NULL rows before dispatch") + require.Equal(t, []int64{2, 0, 4}, vector.MustFixedColNoTypeCheck[int64](result)) + require.True(t, result.IsNull(1), "the skipped row is scattered back as NULL") + require.Equal(t, "runtime-query", runtime.invocation.Context["statement_id"]) + require.Equal(t, "[\"ANSI\",\"STRICT_TRANS_TABLES\"]", runtime.invocation.Context["sql_mode"]) + require.Equal(t, "+480", runtime.invocation.Context["session_timezone_offset_minutes"]) + require.Equal(t, "alice", runtime.invocation.Context["current_user"]) +} + +func TestExternalRoutineEvalRejectsSelectionWithWrongRowDomain(t *testing.T) { + proc := testutil.NewProcess(t) + defer proc.Free() + + input := vector.NewVec(types.T_int64.ToType()) + defer input.Free(proc.Mp()) + require.NoError(t, vector.AppendFixed(input, int64(1), false, proc.Mp())) + inputBatch := batch.NewWithSize(0) + inputBatch.SetRowCount(1) + evaluator, err := newExternalRoutineEval(proc, testExternalRoutineCall(t, "SCALAR", udf.NullCallHandler), []ExpressionExecutor{ + &externalRoutineTestExecutor{vector: input}, + }, nil) + require.NoError(t, err) + defer evaluator.Free() + + _, err = evaluator.Eval(proc, []*batch.Batch{inputBatch}, []bool{true, false}) + require.ErrorContains(t, err, "selection has 2 rows, expected 1") +} + +func TestExternalRoutineEvalRejectsSelectionForEmptyRowDomain(t *testing.T) { + proc := testutil.NewProcess(t) + defer proc.Free() + + input := vector.NewVec(types.T_int64.ToType()) + defer input.Free(proc.Mp()) + evaluator, err := newExternalRoutineEval(proc, testExternalRoutineCall(t, "SCALAR", udf.NullCallHandler), []ExpressionExecutor{ + &externalRoutineTestExecutor{vector: input}, + }, nil) + require.NoError(t, err) + defer evaluator.Free() + + emptyBatch := batch.NewWithSize(0) + emptyBatch.SetRowCount(0) + _, err = evaluator.Eval(proc, []*batch.Batch{emptyBatch}, []bool{true}) + require.ErrorContains(t, err, "selection has 1 rows, expected 0") +} + +func TestNewExpressionExecutorDispatchesTypedRoutineCall(t *testing.T) { + proc := testutil.NewProcess(t) + defer proc.Free() + proc.SetQueryId("physical-external-routine-query") + proc.GetSessionInfo().TimeZone = time.FixedZone("FixedZone", 8*60*60) + proc.GetSessionInfo().User = "root" + proc.Base.StmtProfile = &process.StmtProfile{} + proc.GetStmtProfile().SetQueryStart(time.Date(2026, 9, 10, 1, 2, 3, 4000, time.UTC)) + + input := vector.NewVec(types.T_int64.ToType()) + for _, value := range []int64{1, 2, 3} { + require.NoError(t, vector.AppendFixed(input, value, false, proc.Mp())) + } + inputBatch := batch.NewWithSize(1) + inputBatch.Vecs[0] = input + inputBatch.SetRowCount(3) + defer inputBatch.Clean(proc.Mp()) + + runtime := &externalRoutineCaptureRuntime{} + proc.Base.UdfService = runtime + call := testExternalRoutineCall(t, "SCALAR", udf.NullCallHandler) + expression := &planpb.Expr{ + Typ: call.ReturnType, + Expr: &planpb.Expr_F{F: &planpb.Function{ + Args: []*planpb.Expr{{ + Typ: *call.ArgumentTypes[0], + Expr: &planpb.Expr_Col{Col: &planpb.ColRef{RelPos: 0, ColPos: 0}}, + }}, + RoutineCall: call, + }}, + } + + executor, err := NewExpressionExecutor(proc, expression) + require.NoError(t, err) + defer executor.Free() + result, err := executor.Eval(proc, []*batch.Batch{inputBatch}, []bool{true, false, true}) + require.NoError(t, err) + require.Len(t, runtime.invocations, 1) + require.Equal(t, 2, runtime.invocation.Length) + require.Equal(t, []int64{2, 0, 4}, vector.MustFixedColNoTypeCheck[int64](result)) + require.True(t, result.IsNull(1)) +} + +func TestExternalRoutineEvalRequiresRowDomainForZeroArgumentVector(t *testing.T) { + rows, err := externalRoutineRowCount("VECTOR", nil) + require.Zero(t, rows) + require.ErrorContains(t, err, "requires an input batch with num_rows") + + rows, err = externalRoutineRowCount("VECTOR", []*batch.Batch{nil}) + require.Zero(t, rows) + require.ErrorContains(t, err, "input batch 0 is nil") +} + +func TestExternalRoutineRowCountValidatesAllJoinDomains(t *testing.T) { + first := batch.NewWithSize(0) + first.SetRowCount(3) + second := batch.NewWithSize(0) + second.SetRowCount(3) + short := batch.NewWithSize(0) + short.SetRowCount(2) + for _, tc := range []struct { + name string + mode string + batches []*batch.Batch + want int + err string + }{ + {name: "aligned join row domains", mode: "SCALAR", batches: []*batch.Batch{first, second}, want: 3}, + {name: "scalar without explicit batch has one row", mode: "SCALAR", want: 1}, + {name: "empty vector batch carries zero rows", mode: "VECTOR", batches: []*batch.Batch{{}}, err: ""}, + {name: "nil later relation", mode: "SCALAR", batches: []*batch.Batch{first, nil}, err: "input batch 1 is nil"}, + {name: "unequal join cardinality", mode: "SCALAR", batches: []*batch.Batch{first, short}, err: "has 2 rows, expected 3"}, + } { + t.Run(tc.name, func(t *testing.T) { + rows, err := externalRoutineRowCount(tc.mode, tc.batches) + if tc.err != "" { + require.Zero(t, rows) + require.ErrorContains(t, err, tc.err) + return + } + require.NoError(t, err) + require.Equal(t, tc.want, rows) + }) + } +} + +func TestExternalRoutineEvalAcceptsAlignedJoinBatches(t *testing.T) { + first := batch.NewWithSize(0) + first.SetRowCount(1) + second := batch.NewWithSize(0) + second.SetRowCount(1) + + rows, err := externalRoutineRowCount("SCALAR", []*batch.Batch{first, second}) + require.NoError(t, err) + require.Equal(t, 1, rows) + + second.SetRowCount(2) + rows, err = externalRoutineRowCount("SCALAR", []*batch.Batch{first, second}) + require.Zero(t, rows) + require.ErrorContains(t, err, "expected 1 for the logical row domain") +} + +func TestExternalRoutineEvalRejectsMissingReturnDescriptor(t *testing.T) { + call := testExternalRoutineCall(t, "SCALAR", udf.NullCallHandler) + call.ReturnType = planpb.Type{} + + require.NotPanics(t, func() { + err := validateRoutineCall(call) + require.ErrorContains(t, err, "no return descriptor") + }) +} + +func TestExternalRoutineEvalRejectsUnsupportedTypeBeforeResultAllocation(t *testing.T) { + proc := testutil.NewProcess(t) + defer proc.Free() + + call := testExternalRoutineCall(t, "SCALAR", udf.NullCallHandler) + call.ReturnType = planpb.Type{Id: int32(types.T_decimal256), Width: 76, Scale: 2} + input := vector.NewVec(types.T_int64.ToType()) + defer input.Free(proc.Mp()) + + require.NotPanics(t, func() { + _, err := newExternalRoutineEval(proc, call, []ExpressionExecutor{ + &externalRoutineTestExecutor{vector: input}, + }, nil) + require.ErrorContains(t, err, "typed Python return descriptor is unsupported") + }) +} + +func TestExternalRoutineEvalRejectsExecutionContextInPlan(t *testing.T) { + call := testExternalRoutineCall(t, "SCALAR", udf.NullCallHandler) + call.Context = map[string]string{"current_user": "attacker"} + + err := validateRoutineCall(call) + require.ErrorContains(t, err, "contains execution context") +} + +func TestExternalRoutineEvalRejectsAccountBeforeEvaluatingParameters(t *testing.T) { + proc := testutil.NewProcess(t) + defer proc.Free() + proc.SetQueryId("account-boundary-query") + proc.GetSessionInfo().TimeZone = time.FixedZone("FixedZone", 8*60*60) + proc.Base.StmtProfile = &process.StmtProfile{} + proc.GetStmtProfile().SetQueryStart(time.Date(2026, 9, 10, 1, 2, 3, 4000, time.UTC)) + + input := vector.NewVec(types.T_int64.ToType()) + defer input.Free(proc.Mp()) + require.NoError(t, vector.AppendFixed(input, int64(1), false, proc.Mp())) + seen := 0 + call := testExternalRoutineCall(t, "SCALAR", udf.NullCallHandler) + call.FunctionRef.AccountId = 99 + evaluator, err := newExternalRoutineEval(proc, call, []ExpressionExecutor{ + &externalRoutineTestExecutor{vector: input, evalSeen: &seen}, + }, nil) + require.NoError(t, err) + defer evaluator.Free() + + inputBatch := batch.NewWithSize(0) + inputBatch.SetRowCount(1) + _, err = evaluator.Eval(proc, []*batch.Batch{inputBatch}, []bool{true}) + require.ErrorContains(t, err, "FunctionRef account does not match") + require.Zero(t, seen) +} + +func TestMaskedNestedExternalRoutineIsCompactedBeforeOuterEval(t *testing.T) { + proc := testutil.NewProcess(t) + defer proc.Free() + proc.SetQueryId("nested-runtime-query") + proc.GetSessionInfo().TimeZone = time.FixedZone("FixedZone", 8*60*60) + proc.GetSessionInfo().User = "alice" + proc.GetSessionInfo().Database = "app" + proc.GetSessionInfo().SqlMode = "STRICT_TRANS_TABLES" + proc.Base.StmtProfile = &process.StmtProfile{} + proc.GetStmtProfile().SetQueryStart(time.Date(2026, 9, 10, 1, 2, 3, 4000, time.FixedZone("input", 8*60*60))) + + input := vector.NewVec(types.T_int64.ToType()) + for _, value := range []int64{1, 2, 3} { + require.NoError(t, vector.AppendFixed(input, value, false, proc.Mp())) + } + inputBatch := batch.NewWithSize(1) + inputBatch.Vecs[0] = input + inputBatch.SetRowCount(3) + defer inputBatch.Clean(proc.Mp()) + + runtime := &externalRoutineCaptureRuntime{} + proc.Base.UdfService = runtime + external, err := newExternalRoutineEval(proc, testExternalRoutineCall(t, "SCALAR", udf.NullCallHandler), []ExpressionExecutor{ + &externalRoutineTestExecutor{vector: input}, + }, nil) + require.NoError(t, err) + + outer := NewFunctionExpressionExecutor() + require.NoError(t, outer.Init(proc, 1, types.T_int64.ToType())) + defer outer.Free() + outer.evalFn = func(parameters []*vector.Vector, result vector.FunctionResultWrapper, _ *process.Process, length int, _ *function.FunctionSelectList) error { + values := vector.GenerateFunctionFixedTypeParameter[int64](parameters[0]) + output := vector.MustFunctionResult[int64](result) + for row := 0; row < length; row++ { + value, isNull := values.GetValue(uint64(row)) + if err := output.Append(value, isNull); err != nil { + return err + } + } + return nil + } + outer.SetParameter(0, external) + + result, err := outer.Eval(proc, []*batch.Batch{inputBatch}, []bool{false, true, true}) + require.NoError(t, err) + require.Equal(t, []int64{0, 3, 4}, vector.MustFixedColNoTypeCheck[int64](result)) + require.True(t, result.IsNull(0)) +} + +func TestBuildRoutineContextRejectsUnstableTimezone(t *testing.T) { + proc := testutil.NewProcess(t) + proc.GetSessionInfo().TimeZone = time.Local + _, err := buildRoutineContext(proc) + if time.Local.String() == "Local" { + if _, _, resolveErr := resolveSystemTimezone(); resolveErr != nil { + require.ErrorContains(t, err, "stable IANA identity") + } else { + require.NoError(t, err) + } + } else { + require.NoError(t, err) + } +} + +func TestBuildRoutineContextRejectsSubMinuteFixedTimezone(t *testing.T) { + proc := testutil.NewProcess(t) + defer proc.Free() + proc.GetSessionInfo().TimeZone = time.FixedZone("FixedZone", 8*60*60+30) + + _, err := buildRoutineContext(proc) + require.ErrorContains(t, err, "whole number of minutes") +} + +func TestBuildRoutineContextRejectsMissingStatementInputs(t *testing.T) { + if _, err := buildRoutineContext(nil); err == nil { + t.Fatal("nil process must not produce an invocation context") + } + if _, err := buildRoutineContext(&process.Process{}); err == nil { + t.Fatal("process without Base must not produce an invocation context") + } + proc := testutil.NewProcess(t) + defer proc.Free() + proc.Base.StmtProfile = &process.StmtProfile{} + proc.GetSessionInfo().TimeZone = time.UTC + proc.Base.UnixTime = 0 + _, err := buildRoutineContext(proc) + require.ErrorContains(t, err, "statement timestamp is unavailable") + + proc.Base.UnixTime = time.Now().UnixNano() + proc.GetSessionInfo().TimeZone = nil + _, err = buildRoutineContext(proc) + require.ErrorContains(t, err, "session timezone is unavailable") +} + +func TestResolveSystemTimezoneUsesExplicitStableZone(t *testing.T) { + t.Setenv("TZ", "posix/UTC") + name, location, err := resolveSystemTimezone() + require.NoError(t, err) + require.Equal(t, "UTC", name) + require.Equal(t, "UTC", location.String()) +} + +func TestBuildRoutineContextUsesStableStatementAndSessionSnapshot(t *testing.T) { + for _, tc := range []struct { + name string + sessionMode string + resolve func() (interface{}, error) + wantMode string + }{ + { + name: "resolved SQL mode overrides session fallback", + sessionMode: "ANSI", + resolve: func() (interface{}, error) { return "strict_trans_tables, ansi,STRICT_TRANS_TABLES", nil }, + wantMode: `["ANSI","STRICT_TRANS_TABLES"]`, + }, + { + name: "resolver error keeps session SQL mode", + sessionMode: "ansi, strict_trans_tables", + resolve: func() (interface{}, error) { return nil, errors.New("variable unavailable") }, + wantMode: `["ANSI","STRICT_TRANS_TABLES"]`, + }, + { + name: "non-string resolution keeps session SQL mode", + sessionMode: "ANSI", + resolve: func() (interface{}, error) { return int64(1), nil }, + wantMode: `["ANSI"]`, + }, + { + name: "empty sentinel becomes empty mode list", + sessionMode: process.EmptySqlModeSentinel, + wantMode: `[]`, + }, + } { + t.Run(tc.name, func(t *testing.T) { + proc := testutil.NewProcess(t) + defer proc.Free() + proc.SetQueryId("") + proc.GetSessionInfo().TimeZone = time.UTC + proc.GetSessionInfo().User = "root" + proc.GetSessionInfo().Database = "" + proc.GetSessionInfo().Role = "" + proc.GetSessionInfo().SqlMode = tc.sessionMode + proc.Base.StmtProfile = &process.StmtProfile{} + proc.Base.UnixTime = time.Date(2026, 9, 23, 1, 2, 3, 4000, time.UTC).UnixNano() + if tc.resolve != nil { + proc.SetResolveVariableFunc(func(name string, system, global bool) (interface{}, error) { + require.Equal(t, "sql_mode", name) + require.True(t, system) + require.False(t, global) + return tc.resolve() + }) + } + + values, err := buildRoutineContext(proc) + require.NoError(t, err) + require.NotContains(t, values, "statement_id") + require.Equal(t, strconv.FormatInt(time.Unix(0, proc.Base.UnixTime).UTC().UnixMicro(), 10), values["statement_timestamp_utc"]) + require.Equal(t, "IANA", values["session_timezone_kind"]) + require.Equal(t, "UTC", values["session_timezone_name"]) + require.NotEmpty(t, values["session_timezone_tzdb_version"]) + require.Equal(t, tc.wantMode, values["sql_mode"]) + require.NotContains(t, values, "current_database") + require.NotContains(t, values, "current_role") + }) + } +} + +func testExternalRoutineCall(t *testing.T, mode, nullPolicy string) *planpb.RoutineCall { + t.Helper() + descriptor, err := function.NewPythonTypeDescriptor(types.T_int64.ToType()) + require.NoError(t, err) + body, err := json.Marshal(function.PythonRoutineBody{ + DefinitionSchemaVersion: udf.PythonDefinitionSchemaVersion, + Handler: "add", + Source: "def add(ctx, value): return value + 1", + Mode: mode, + NullPolicy: nullPolicy, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + ArtifactDigest: udf.PythonInlineArtifactDigest("add", "def add(ctx, value): return value + 1"), + EnvironmentDigest: func() string { digest, _ := udf.PythonEnvironmentDigest(); return digest }(), + SDKVersion: udf.PythonSDKVersion, + ArgTypes: []function.PythonTypeDescriptor{descriptor}, + ReturnType: &descriptor, + }) + require.NoError(t, err) + routine := &function.Udf{ + FunctionID: 100, + AccountID: 0, + DatabaseID: 2, + Revision: 7, + NamespaceVersion: 9, + Language: udf.LanguagePython, + Body: string(body), + PythonArgTypes: []function.PythonTypeDescriptor{descriptor}, + PythonReturnType: &descriptor, + } + call, err := routine.GetRoutineCall() + require.NoError(t, err) + call.CallsiteId = "python/test" + return call +} + +func TestExternalRoutineEvalRejectsSourceInExecutablePlan(t *testing.T) { + call := testExternalRoutineCall(t, python.ModeScalar, udf.NullCallHandler) + call.GetPython().Source = "def add(ctx, value): return value + 1" + require.ErrorContains(t, validateRoutineCall(call), "plan contains source") +} + +func TestExternalRoutineEvalRequiresCanonicalLanguage(t *testing.T) { + call := testExternalRoutineCall(t, python.ModeScalar, udf.NullCallHandler) + call.Language = "PYTHON" + require.ErrorContains(t, validateRoutineCall(call), "unsupported typed routine call contract") +} + +func TestExternalRoutineEvalRejectsSuccessfulRuntimeWithoutResultRows(t *testing.T) { + proc := testutil.NewProcess(t) + defer proc.Free() + proc.SetQueryId("missing-result-query") + proc.GetSessionInfo().TimeZone = time.UTC + proc.GetSessionInfo().User = "root" + proc.Base.StmtProfile = &process.StmtProfile{} + proc.GetStmtProfile().SetQueryStart(time.Date(2026, 9, 14, 0, 0, 0, 0, time.UTC)) + + input := vector.NewVec(types.T_int64.ToType()) + defer input.Free(proc.Mp()) + require.NoError(t, vector.AppendFixed(input, int64(10), false, proc.Mp())) + bat := batch.NewWithSize(0) + bat.SetRowCount(1) + proc.Base.UdfService = &externalRoutineEmptySuccessRuntime{} + evaluator, err := newExternalRoutineEval( + proc, + testExternalRoutineCall(t, python.ModeScalar, udf.NullCallHandler), + []ExpressionExecutor{&externalRoutineTestExecutor{vector: input}}, + nil, + ) + require.NoError(t, err) + defer evaluator.Free() + + _, err = evaluator.Eval(proc, []*batch.Batch{bat}, []bool{true}) + require.ErrorContains(t, err, "runtime produced 0 result rows, expected 1") +} + +func TestExternalRoutineEvalPropagatesParameterAndRuntimeFailures(t *testing.T) { + for _, tc := range []struct { + name string + parameterFailure bool + runtimeFailure bool + want string + }{ + {name: "parameter evaluation fails", parameterFailure: true, want: "parameter expression failed"}, + {name: "runtime is disabled", want: "runtime is not enabled"}, + {name: "runtime execution fails", runtimeFailure: true, want: "handler process was cancelled"}, + } { + t.Run(tc.name, func(t *testing.T) { + proc := testutil.NewProcess(t) + defer proc.Free() + proc.SetQueryId("error-path-query") + proc.GetSessionInfo().TimeZone = time.UTC + proc.GetSessionInfo().User = "root" + proc.Base.StmtProfile = &process.StmtProfile{} + proc.GetStmtProfile().SetQueryStart(time.Date(2026, 9, 23, 0, 0, 0, 0, time.UTC)) + input := vector.NewVec(types.T_int64.ToType()) + defer input.Free(proc.Mp()) + require.NoError(t, vector.AppendFixed(input, int64(10), false, proc.Mp())) + parameter := &externalRoutineTestExecutor{vector: input} + if tc.parameterFailure { + parameter.err = errors.New(tc.want) + } else if tc.runtimeFailure { + proc.Base.UdfService = &externalRoutineErrorRuntime{err: errors.New(tc.want)} + } + evaluator, err := newExternalRoutineEval( + proc, testExternalRoutineCall(t, python.ModeScalar, udf.NullCallHandler), + []ExpressionExecutor{parameter}, nil, + ) + require.NoError(t, err) + defer evaluator.Free() + bat := batch.NewWithSize(0) + bat.SetRowCount(1) + _, err = evaluator.Eval(proc, []*batch.Batch{bat}, []bool{true}) + require.ErrorContains(t, err, tc.want) + }) + } +} + +func TestExternalRoutineTransfersResultOwnership(t *testing.T) { + for _, mode := range []string{"SCALAR", "VECTOR"} { + t.Run(mode, func(t *testing.T) { + proc := testutil.NewProcess(t) + defer proc.Free() + proc.SetQueryId("result-ownership") + proc.GetSessionInfo().TimeZone = time.UTC + proc.GetSessionInfo().User = "root" + proc.Base.StmtProfile = &process.StmtProfile{} + proc.GetStmtProfile().SetQueryStart(time.Date(2026, 9, 14, 0, 0, 0, 0, time.UTC)) + input := vector.NewVec(types.T_int64.ToType()) + defer input.Free(proc.Mp()) + require.NoError(t, vector.AppendFixed(input, int64(10), false, proc.Mp())) + require.NoError(t, vector.AppendFixed(input, int64(20), false, proc.Mp())) + bat := batch.NewWithSize(0) + bat.SetRowCount(2) + proc.Base.UdfService = &externalRoutineCaptureRuntime{} + evaluator, err := newExternalRoutineEval(proc, testExternalRoutineCall(t, mode, udf.NullCallHandler), []ExpressionExecutor{&externalRoutineTestExecutor{vector: input}}, nil) + require.NoError(t, err) + defer evaluator.Free() + owned, err := evaluator.EvalWithoutResultReusing(proc, []*batch.Batch{bat}, []bool{true, false}) + require.NoError(t, err) + // Only free when ownership actually moved, so the pre-fix counterexample + // reports the alias without double freeing the evaluator's vector. + if owned != evaluator.result.GetResultVector() { + defer owned.Free(proc.Mp()) + } + require.NotSame(t, owned, evaluator.result.GetResultVector()) + _, err = evaluator.Eval(proc, []*batch.Batch{bat}, nil) + require.NoError(t, err) + evaluator.Free() + require.Equal(t, 2, owned.Length()) + require.Equal(t, int64(11), vector.GetFixedAtNoTypeCheck[int64](owned, 0)) + require.True(t, owned.IsNull(1)) + }) + } +} + +func TestExternalRoutineRejectsDamagedDefinitionBeforeArguments(t *testing.T) { + for _, damage := range []string{"precision", "fingerprint", "argument-type"} { + t.Run(damage, func(t *testing.T) { + call := testExternalRoutineCall(t, "SCALAR", udf.NullCallHandler) + switch damage { + case "precision": + call.ReturnType = planpb.Type{Id: int32(types.T_decimal64), Width: 19, Scale: 2} + case "fingerprint": + call.GetPython().DefinitionFingerprint = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + case "argument-type": + call.ArgumentTypes[0].Id = int32(types.T_int32) + } + require.Error(t, validateRoutineCall(call)) + }) + } +} + +func TestValidateRoutineCallRejectsIncompleteTypedContracts(t *testing.T) { + for _, tc := range []struct { + name string + mutate func(*planpb.RoutineCall) + want string + }{ + {name: "missing FunctionRef", mutate: func(call *planpb.RoutineCall) { call.FunctionRef = nil }, want: "no exact FunctionRef"}, + {name: "zero function identity", mutate: func(call *planpb.RoutineCall) { call.FunctionRef.FunctionId = 0 }, want: "no exact FunctionRef"}, + {name: "missing return descriptor", mutate: func(call *planpb.RoutineCall) { call.ReturnType.Id = int32(types.T_any) }, want: "no return descriptor"}, + {name: "unsupported contract version", mutate: func(call *planpb.RoutineCall) { call.ContractVersion++ }, want: "unsupported typed routine call contract"}, + {name: "non-volatile function", mutate: func(call *planpb.RoutineCall) { call.Volatility = "IMMUTABLE" }, want: "must be VOLATILE"}, + {name: "function cannot error", mutate: func(call *planpb.RoutineCall) { call.MayError = false }, want: "semantic contract is not supported"}, + {name: "unsupported security contract", mutate: func(call *planpb.RoutineCall) { call.SecurityMode = "DEFINER" }, want: "semantic contract is not supported"}, + {name: "leakproof function", mutate: func(call *planpb.RoutineCall) { call.Leakproof = true }, want: "semantic contract is not supported"}, + {name: "invalid callsite newline", mutate: func(call *planpb.RoutineCall) { call.CallsiteId = "python/test\nother" }, want: "valid callsite id"}, + {name: "execution context in plan", mutate: func(call *planpb.RoutineCall) { call.Context = map[string]string{"statement_id": "stale"} }, want: "contains execution context"}, + {name: "missing Python implementation", mutate: func(call *planpb.RoutineCall) { call.Implementation = nil }, want: "no Python implementation"}, + {name: "source in plan", mutate: func(call *planpb.RoutineCall) { call.GetPython().Source = "def add(ctx, value): return value" }, want: "plan contains source"}, + {name: "unsupported SDK contract", mutate: func(call *planpb.RoutineCall) { call.GetPython().SdkVersion = "future" }, want: "implementation contract is not supported"}, + {name: "unsupported mode", mutate: func(call *planpb.RoutineCall) { call.GetPython().Mode = "BATCH" }, want: "unsupported typed call mode"}, + {name: "unsupported NULL policy", mutate: func(call *planpb.RoutineCall) { call.GetPython().NullPolicy = "DEFAULT" }, want: "unsupported typed NULL policy"}, + {name: "NULL policy mismatch", mutate: func(call *planpb.RoutineCall) { call.NullPolicy = udf.NullReturnNull }, want: "NULL policy does not match"}, + {name: "malformed artifact digest", mutate: func(call *planpb.RoutineCall) { call.GetPython().ArtifactDigest = "not-a-digest" }, want: "invalid artifact/environment digest"}, + {name: "malformed definition fingerprint", mutate: func(call *planpb.RoutineCall) { call.GetPython().DefinitionFingerprint = "not-a-digest" }, want: "invalid definition fingerprint"}, + {name: "nil argument descriptor", mutate: func(call *planpb.RoutineCall) { call.ArgumentTypes[0] = nil }, want: "argument 0 is nil"}, + {name: "unsupported argument type", mutate: func(call *planpb.RoutineCall) { call.ArgumentTypes[0].Id = int32(types.T_any) }, want: "argument 0 is unsupported"}, + } { + t.Run(tc.name, func(t *testing.T) { + call := testExternalRoutineCall(t, python.ModeScalar, udf.NullCallHandler) + tc.mutate(call) + require.ErrorContains(t, validateRoutineCall(call), tc.want) + }) + } +} + +func TestValidateExternalRoutineInputsChecksRowAndTypeContracts(t *testing.T) { + proc := testutil.NewProcess(t) + defer proc.Free() + int64Rows := vector.NewVec(types.T_int64.ToType()) + defer int64Rows.Free(proc.Mp()) + require.NoError(t, vector.AppendFixed(int64Rows, int64(1), false, proc.Mp())) + require.NoError(t, vector.AppendFixed(int64Rows, int64(2), false, proc.Mp())) + shortRows := vector.NewVec(types.T_int64.ToType()) + defer shortRows.Free(proc.Mp()) + require.NoError(t, vector.AppendFixed(shortRows, int64(1), false, proc.Mp())) + int32Rows := vector.NewVec(types.T_int32.ToType()) + defer int32Rows.Free(proc.Mp()) + require.NoError(t, vector.AppendFixed(int32Rows, int32(1), false, proc.Mp())) + require.NoError(t, vector.AppendFixed(int32Rows, int32(2), false, proc.Mp())) + emptyRows := vector.NewVec(types.T_int64.ToType()) + defer emptyRows.Free(proc.Mp()) + + for _, tc := range []struct { + name string + inputs []*vector.Vector + rows int + mutate func(*planpb.RoutineCall) + wantErr string + }{ + {name: "valid aligned input", inputs: []*vector.Vector{int64Rows}, rows: 2}, + {name: "argument count mismatch", inputs: nil, rows: 2, wantErr: "evaluated input count 0"}, + {name: "missing input vector", inputs: []*vector.Vector{nil}, rows: 1, wantErr: "has no type"}, + {name: "empty input vector", inputs: []*vector.Vector{emptyRows}, rows: 1, wantErr: "has 0 rows"}, + {name: "short non-constant input", inputs: []*vector.Vector{shortRows}, rows: 2, wantErr: "expected at least 2"}, + {name: "physical SQL type mismatch", inputs: []*vector.Vector{int32Rows}, rows: 2, wantErr: "does not match the frozen descriptor"}, + {name: "unsupported frozen descriptor", inputs: []*vector.Vector{int64Rows}, rows: 2, mutate: func(call *planpb.RoutineCall) { call.ArgumentTypes[0].Id = int32(types.T_enum) }, wantErr: "invalid argument descriptor 0"}, + } { + t.Run(tc.name, func(t *testing.T) { + call := testExternalRoutineCall(t, python.ModeScalar, udf.NullCallHandler) + if tc.mutate != nil { + tc.mutate(call) + } + err := validateExternalRoutineInputs(tc.inputs, call, tc.rows) + if tc.wantErr == "" { + require.NoError(t, err) + return + } + require.ErrorContains(t, err, tc.wantErr) + }) + } +} + +func TestExternalRoutineSkipsArgumentsForEmptySelection(t *testing.T) { + for _, mode := range []string{"SCALAR", "VECTOR"} { + t.Run(mode, func(t *testing.T) { + proc := testutil.NewProcess(t) + defer proc.Free() + input := vector.NewVec(types.T_int64.ToType()) + defer input.Free(proc.Mp()) + require.NoError(t, vector.AppendFixed(input, int64(1), false, proc.Mp())) + seen := 0 + evaluator, err := newExternalRoutineEval(proc, testExternalRoutineCall(t, mode, udf.NullCallHandler), []ExpressionExecutor{&externalRoutineTestExecutor{vector: input, evalSeen: &seen}}, nil) + require.NoError(t, err) + defer evaluator.Free() + bat := batch.NewWithSize(0) + bat.SetRowCount(1) + result, err := evaluator.Eval(proc, []*batch.Batch{bat}, []bool{false}) + require.NoError(t, err) + require.True(t, result.IsNull(0)) + require.Zero(t, seen, "an unselected call must not evaluate any arguments") + }) + } +} diff --git a/pkg/sql/compile/Remote_Run_DEV_GUIDE.md b/pkg/sql/compile/Remote_Run_DEV_GUIDE.md index 5e1571e7fbb1a..6b722e922a37a 100644 --- a/pkg/sql/compile/Remote_Run_DEV_GUIDE.md +++ b/pkg/sql/compile/Remote_Run_DEV_GUIDE.md @@ -166,7 +166,7 @@ func CnServerMessageHandler( lockService lockservice.LockService, queryClient qclient.QueryClient, HaKeeper logservice.CNHAKeeperClient, - udfService udf.Service, + udfService udf.Runtime, txnClient client.TxnClient, autoIncreaseCM *defines.AutoIncrCacheManager, messageAcquirer func() morpc.Message) (err error) { diff --git a/pkg/sql/compile/remoterunServer.go b/pkg/sql/compile/remoterunServer.go index 9fa9fe9a87510..16da59abefa04 100644 --- a/pkg/sql/compile/remoterunServer.go +++ b/pkg/sql/compile/remoterunServer.go @@ -81,7 +81,7 @@ func CnServerMessageHandler( cs morpc.ClientSession, storageEngine engine.Engine, fileService fileservice.FileService, lockService lockservice.LockService, queryClient qclient.QueryClient, - HaKeeper logservice.CNHAKeeperClient, udfService udf.Service, txnClient client.TxnClient, + HaKeeper logservice.CNHAKeeperClient, udfService udf.Runtime, txnClient client.TxnClient, autoIncreaseCM *defines.AutoIncrCacheManager, messageAcquirer func() morpc.Message) (err error) { @@ -799,7 +799,7 @@ type cnInformation struct { lockService lockservice.LockService queryClient qclient.QueryClient hakeeper logservice.CNHAKeeperClient - udfService udf.Service + udfService udf.Runtime aicm *defines.AutoIncrCacheManager } @@ -880,7 +880,7 @@ func newMessageReceiverOnServer( lockService lockservice.LockService, queryClient qclient.QueryClient, hakeeper logservice.CNHAKeeperClient, - udfService udf.Service, + udfService udf.Runtime, txnClient client.TxnClient, aicm *defines.AutoIncrCacheManager, colexecServer *colexec.Server) (messageReceiverOnServer, error) { diff --git a/pkg/sql/compile/sql_executor.go b/pkg/sql/compile/sql_executor.go index c91d4a002ce05..244793384eca7 100644 --- a/pkg/sql/compile/sql_executor.go +++ b/pkg/sql/compile/sql_executor.go @@ -60,7 +60,7 @@ type sqlExecutor struct { ls lockservice.LockService qc qclient.QueryClient hakeeper logservice.CNHAKeeperClient - us udf.Service + us udf.Runtime buf *buffer.Buffer taskservice taskservice.TaskService } @@ -111,7 +111,7 @@ func NewSQLExecutor( fs fileservice.FileService, qc qclient.QueryClient, hakeeper logservice.CNHAKeeperClient, - us udf.Service, + us udf.Runtime, taskService taskservice.TaskService, ) executor.SQLExecutor { v, ok := runtime.ServiceRuntime(qc.ServiceID()).GetGlobalVariables(runtime.LockService) diff --git a/pkg/sql/parsers/dialect/mysql/keywords.go b/pkg/sql/parsers/dialect/mysql/keywords.go index be1c6eca1b8e2..6747d2d378847 100644 --- a/pkg/sql/parsers/dialect/mysql/keywords.go +++ b/pkg/sql/parsers/dialect/mysql/keywords.go @@ -73,6 +73,7 @@ func init() { "bit_and": BIT_AND, "bit_xor": BIT_XOR, "call": CALL, + "called": CALLED, "cancel": CANCEL, "catalog": CATALOG, "catalogs": CATALOGS, @@ -265,6 +266,7 @@ func init() { "mongodb_path": MONGODB_PATH, "if": IF, "ignore": IGNORE, + "input": INPUT, "in": IN, "index": INDEX, "indexes": INDEXES, @@ -477,6 +479,7 @@ func init() { "row_number": ROW_NUMBER, "rtree": RTREE, "schema": SCHEMA, + "scalar": SCALAR, "schemas": SCHEMAS, "schedule": SCHEDULE, "second": SECOND, @@ -721,6 +724,7 @@ func init() { "array": ARRAY, "array_agg": JSON_ARRAYAGG, "vecf32": VECF32, + "vector": VECTOR, "vecf64": VECF64, "vecbf16": VECBF16, "vecf16": VECF16, diff --git a/pkg/sql/parsers/dialect/mysql/mysql_sql.go b/pkg/sql/parsers/dialect/mysql/mysql_sql.go index d017063e58337..8327b8f8bf07e 100644 --- a/pkg/sql/parsers/dialect/mysql/mysql_sql.go +++ b/pkg/sql/parsers/dialect/mysql/mysql_sql.go @@ -541,309 +541,313 @@ const TEMPORARY = 57798 const ROUTINE = 57799 const EVENT = 57800 const SHUTDOWN = 57801 -const NULLX = 57802 -const AUTO_INCREMENT = 57803 -const APPROXNUM = 57804 -const ENGINES = 57805 -const LOW_CARDINALITY = 57806 -const AUTOEXTEND_SIZE = 57807 -const ADMIN_NAME = 57808 -const RANDOM = 57809 -const SUSPEND = 57810 -const ATTRIBUTE = 57811 -const HISTORY = 57812 -const REUSE = 57813 -const CURRENT = 57814 -const OPTIONAL = 57815 -const FAILED_LOGIN_ATTEMPTS = 57816 -const PASSWORD_LOCK_TIME = 57817 -const UNBOUNDED = 57818 -const SECONDARY = 57819 -const RESTRICTED = 57820 -const USER = 57821 -const IDENTIFIED = 57822 -const CIPHER = 57823 -const ISSUER = 57824 -const X509 = 57825 -const SUBJECT = 57826 -const SAN = 57827 -const REQUIRE = 57828 -const SSL = 57829 -const NONE = 57830 -const PASSWORD = 57831 -const SHARED = 57832 -const EXCLUSIVE = 57833 -const MAX_QUERIES_PER_HOUR = 57834 -const MAX_UPDATES_PER_HOUR = 57835 -const MAX_CONNECTIONS_PER_HOUR = 57836 -const MAX_USER_CONNECTIONS = 57837 -const FORMAT = 57838 -const VERBOSE = 57839 -const CONNECTION = 57840 -const TRIGGERS = 57841 -const PROFILES = 57842 -const PROFILE = 57843 -const LOAD = 57844 -const INLINE = 57845 -const INFILE = 57846 -const TERMINATED = 57847 -const OPTIONALLY = 57848 -const ENCLOSED = 57849 -const ESCAPED = 57850 -const STARTING = 57851 -const LINES = 57852 -const ROWS = 57853 -const IMPORT = 57854 -const DISCARD = 57855 -const JSONTYPE = 57856 -const MODUMP = 57857 -const OVER = 57858 -const PRECEDING = 57859 -const FOLLOWING = 57860 -const GROUPS = 57861 -const DATABASES = 57862 -const TABLES = 57863 -const SEQUENCES = 57864 -const EXTENDED = 57865 -const FULL = 57866 -const PROCESSLIST = 57867 -const FIELDS = 57868 -const COLUMNS = 57869 -const OPEN = 57870 -const ERRORS = 57871 -const WARNINGS = 57872 -const INDEXES = 57873 -const SCHEMAS = 57874 -const NODE = 57875 -const LOCKS = 57876 -const ROLES = 57877 -const RULE = 57878 -const RULES = 57879 -const TABLE_NUMBER = 57880 -const COLUMN_NUMBER = 57881 -const TABLE_VALUES = 57882 -const TABLE_SIZE = 57883 -const TASKS = 57884 -const RUNS = 57885 -const NAMES = 57886 -const GLOBAL = 57887 -const PERSIST = 57888 -const SESSION = 57889 -const ISOLATION = 57890 -const LEVEL = 57891 -const READ = 57892 -const WRITE = 57893 -const ONLY = 57894 -const REPEATABLE = 57895 -const COMMITTED = 57896 -const UNCOMMITTED = 57897 -const SERIALIZABLE = 57898 -const LOCAL = 57899 -const EVENTS = 57900 -const PLUGINS = 57901 -const CURRENT_TIMESTAMP = 57902 -const DATABASE = 57903 -const CURRENT_TIME = 57904 -const LOCALTIME = 57905 -const LOCALTIMESTAMP = 57906 -const UTC_DATE = 57907 -const UTC_TIME = 57908 -const UTC_TIMESTAMP = 57909 -const REPLACE = 57910 -const CONVERT = 57911 -const SEPARATOR = 57912 -const TIMESTAMPDIFF = 57913 -const TIMESTAMPADD = 57914 -const CURRENT_DATE = 57915 -const CURRENT_USER = 57916 -const CURRENT_ROLE = 57917 -const SECOND_MICROSECOND = 57918 -const MINUTE_MICROSECOND = 57919 -const MINUTE_SECOND = 57920 -const HOUR_MICROSECOND = 57921 -const HOUR_SECOND = 57922 -const HOUR_MINUTE = 57923 -const DAY_MICROSECOND = 57924 -const DAY_SECOND = 57925 -const DAY_MINUTE = 57926 -const DAY_HOUR = 57927 -const YEAR_MONTH = 57928 -const SQL_TSI_HOUR = 57929 -const SQL_TSI_DAY = 57930 -const SQL_TSI_WEEK = 57931 -const SQL_TSI_MONTH = 57932 -const SQL_TSI_QUARTER = 57933 -const SQL_TSI_YEAR = 57934 -const SQL_TSI_SECOND = 57935 -const SQL_TSI_MINUTE = 57936 -const RECURSIVE = 57937 -const CONFIG = 57938 -const DRAINER = 57939 -const DAEMON = 57940 -const PAUSE = 57941 -const CANCEL = 57942 -const RESUME = 57943 -const SCHEDULE = 57944 -const TIMEZONE = 57945 -const TIMEOUT = 57946 -const TASK = 57947 -const MATCH = 57948 -const AGAINST = 57949 -const BOOLEAN = 57950 -const LANGUAGE = 57951 -const QUERY = 57952 -const EXPANSION = 57953 -const WITHOUT = 57954 -const VALIDATION = 57955 -const UPGRADE = 57956 -const RETRY = 57957 -const ADDDATE = 57958 -const BIT_AND = 57959 -const BIT_OR = 57960 -const BIT_XOR = 57961 -const CAST = 57962 -const COUNT = 57963 -const APPROX_COUNT = 57964 -const APPROX_COUNT_DISTINCT = 57965 -const SERIAL_EXTRACT = 57966 -const APPROX_PERCENTILE = 57967 -const CURDATE = 57968 -const CURTIME = 57969 -const DATE_ADD = 57970 -const DATE_SUB = 57971 -const EXTRACT = 57972 -const GROUP_CONCAT = 57973 -const MAX = 57974 -const MID = 57975 -const MIN = 57976 -const NOW = 57977 -const POSITION = 57978 -const SESSION_USER = 57979 -const STD = 57980 -const STDDEV = 57981 -const MEDIAN = 57982 -const CLUSTER_CENTERS = 57983 -const KMEANS = 57984 -const STDDEV_POP = 57985 -const STDDEV_SAMP = 57986 -const SUBDATE = 57987 -const SUBSTR = 57988 -const SUBSTRING = 57989 -const SUM = 57990 -const SYSDATE = 57991 -const SYSTEM_USER = 57992 -const TRANSLATE = 57993 -const TRIM = 57994 -const VARIANCE = 57995 -const VAR_POP = 57996 -const VAR_SAMP = 57997 -const AVG = 57998 -const RANK = 57999 -const ROW_NUMBER = 58000 -const DENSE_RANK = 58001 -const CUME_DIST = 58002 -const BIT_CAST = 58003 -const LAG = 58004 -const LEAD = 58005 -const FIRST_VALUE = 58006 -const LAST_VALUE = 58007 -const NTH_VALUE = 58008 -const NTILE = 58009 -const PERCENT_RANK = 58010 -const BITMAP_BIT_POSITION = 58011 -const BITMAP_BUCKET_NUMBER = 58012 -const BITMAP_COUNT = 58013 -const BITMAP_CONSTRUCT_AGG = 58014 -const BITMAP_OR_AGG = 58015 -const JSON_ARRAYAGG = 58016 -const JSON_OBJECTAGG = 58017 -const GET_FORMAT = 58018 -const SRID = 58019 -const NEXTVAL = 58020 -const SETVAL = 58021 -const CURRVAL = 58022 -const LASTVAL = 58023 -const ROW = 58024 -const OUTFILE = 58025 -const HEADER = 58026 -const MAX_FILE_SIZE = 58027 -const FORCE_QUOTE = 58028 -const PARALLEL = 58029 -const STRICT = 58030 -const SPLITSIZE = 58031 -const UNUSED = 58032 -const BINDINGS = 58033 -const GENERATED = 58034 -const ALWAYS = 58035 -const STORED = 58036 -const VIRTUAL = 58037 -const DO = 58038 -const PERFORM = 58039 -const DECLARE = 58040 -const LOOP = 58041 -const WHILE = 58042 -const LEAVE = 58043 -const ITERATE = 58044 -const UNTIL = 58045 -const CALL = 58046 -const PREV = 58047 -const SLIDING = 58048 -const FILL = 58049 -const GAPFILL = 58050 -const SPBEGIN = 58051 -const BACKEND = 58052 -const SERVERS = 58053 -const HANDLER = 58054 -const PERCENT = 58055 -const SAMPLE = 58056 -const MO_TS = 58057 -const PITR = 58058 -const RECOVERY_WINDOW = 58059 -const INTERNAL = 58060 -const CDC_TASK_NAME = 58061 -const CDC = 58062 -const ICEBERG = 58063 -const CATALOG = 58064 -const CATALOGS = 58065 -const NAMESPACE = 58066 -const NAMESPACES = 58067 -const REF = 58068 -const FOR_ICEBERG = 58069 -const MONGODB = 58070 -const MONGODB_PATH = 58071 -const MONGODB_CONVERT = 58072 -const CONNECTIONS = 58073 -const DATASTREAM = 58074 -const ESQL = 58075 -const KAFKA = 58076 -const GROUPING = 58077 -const SETS = 58078 -const CUBE = 58079 -const ROLLUP = 58080 -const LOGSERVICE = 58081 -const REPLICAS = 58082 -const STORES = 58083 -const SETTINGS = 58084 -const DUMP = 58085 -const METADATA = 58086 -const KILL = 58087 -const BACKUP = 58088 -const FILESYSTEM = 58089 -const PARALLELISM = 58090 -const RESTORE = 58091 -const QUERY_RESULT = 58092 -const RETURNING = 58093 -const ARRAY = 58094 -const WITHIN = 58095 -const PERCENTILE_CONT = 58096 -const PERCENTILE_DISC = 58097 -const ASOF = 58098 -const TOLERANCE = 58099 -const WINDOW = 58100 -const WINDOW_NAME_EMPTY = 58101 -const RESPECT = 58102 -const MEMBER = 58103 -const AUTO_ID_CACHE = 58104 +const CALLED = 57802 +const INPUT = 57803 +const SCALAR = 57804 +const VECTOR = 57805 +const NULLX = 57806 +const AUTO_INCREMENT = 57807 +const APPROXNUM = 57808 +const ENGINES = 57809 +const LOW_CARDINALITY = 57810 +const AUTOEXTEND_SIZE = 57811 +const ADMIN_NAME = 57812 +const RANDOM = 57813 +const SUSPEND = 57814 +const ATTRIBUTE = 57815 +const HISTORY = 57816 +const REUSE = 57817 +const CURRENT = 57818 +const OPTIONAL = 57819 +const FAILED_LOGIN_ATTEMPTS = 57820 +const PASSWORD_LOCK_TIME = 57821 +const UNBOUNDED = 57822 +const SECONDARY = 57823 +const RESTRICTED = 57824 +const USER = 57825 +const IDENTIFIED = 57826 +const CIPHER = 57827 +const ISSUER = 57828 +const X509 = 57829 +const SUBJECT = 57830 +const SAN = 57831 +const REQUIRE = 57832 +const SSL = 57833 +const NONE = 57834 +const PASSWORD = 57835 +const SHARED = 57836 +const EXCLUSIVE = 57837 +const MAX_QUERIES_PER_HOUR = 57838 +const MAX_UPDATES_PER_HOUR = 57839 +const MAX_CONNECTIONS_PER_HOUR = 57840 +const MAX_USER_CONNECTIONS = 57841 +const FORMAT = 57842 +const VERBOSE = 57843 +const CONNECTION = 57844 +const TRIGGERS = 57845 +const PROFILES = 57846 +const PROFILE = 57847 +const LOAD = 57848 +const INLINE = 57849 +const INFILE = 57850 +const TERMINATED = 57851 +const OPTIONALLY = 57852 +const ENCLOSED = 57853 +const ESCAPED = 57854 +const STARTING = 57855 +const LINES = 57856 +const ROWS = 57857 +const IMPORT = 57858 +const DISCARD = 57859 +const JSONTYPE = 57860 +const MODUMP = 57861 +const OVER = 57862 +const PRECEDING = 57863 +const FOLLOWING = 57864 +const GROUPS = 57865 +const DATABASES = 57866 +const TABLES = 57867 +const SEQUENCES = 57868 +const EXTENDED = 57869 +const FULL = 57870 +const PROCESSLIST = 57871 +const FIELDS = 57872 +const COLUMNS = 57873 +const OPEN = 57874 +const ERRORS = 57875 +const WARNINGS = 57876 +const INDEXES = 57877 +const SCHEMAS = 57878 +const NODE = 57879 +const LOCKS = 57880 +const ROLES = 57881 +const RULE = 57882 +const RULES = 57883 +const TABLE_NUMBER = 57884 +const COLUMN_NUMBER = 57885 +const TABLE_VALUES = 57886 +const TABLE_SIZE = 57887 +const TASKS = 57888 +const RUNS = 57889 +const NAMES = 57890 +const GLOBAL = 57891 +const PERSIST = 57892 +const SESSION = 57893 +const ISOLATION = 57894 +const LEVEL = 57895 +const READ = 57896 +const WRITE = 57897 +const ONLY = 57898 +const REPEATABLE = 57899 +const COMMITTED = 57900 +const UNCOMMITTED = 57901 +const SERIALIZABLE = 57902 +const LOCAL = 57903 +const EVENTS = 57904 +const PLUGINS = 57905 +const CURRENT_TIMESTAMP = 57906 +const DATABASE = 57907 +const CURRENT_TIME = 57908 +const LOCALTIME = 57909 +const LOCALTIMESTAMP = 57910 +const UTC_DATE = 57911 +const UTC_TIME = 57912 +const UTC_TIMESTAMP = 57913 +const REPLACE = 57914 +const CONVERT = 57915 +const SEPARATOR = 57916 +const TIMESTAMPDIFF = 57917 +const TIMESTAMPADD = 57918 +const CURRENT_DATE = 57919 +const CURRENT_USER = 57920 +const CURRENT_ROLE = 57921 +const SECOND_MICROSECOND = 57922 +const MINUTE_MICROSECOND = 57923 +const MINUTE_SECOND = 57924 +const HOUR_MICROSECOND = 57925 +const HOUR_SECOND = 57926 +const HOUR_MINUTE = 57927 +const DAY_MICROSECOND = 57928 +const DAY_SECOND = 57929 +const DAY_MINUTE = 57930 +const DAY_HOUR = 57931 +const YEAR_MONTH = 57932 +const SQL_TSI_HOUR = 57933 +const SQL_TSI_DAY = 57934 +const SQL_TSI_WEEK = 57935 +const SQL_TSI_MONTH = 57936 +const SQL_TSI_QUARTER = 57937 +const SQL_TSI_YEAR = 57938 +const SQL_TSI_SECOND = 57939 +const SQL_TSI_MINUTE = 57940 +const RECURSIVE = 57941 +const CONFIG = 57942 +const DRAINER = 57943 +const DAEMON = 57944 +const PAUSE = 57945 +const CANCEL = 57946 +const RESUME = 57947 +const SCHEDULE = 57948 +const TIMEZONE = 57949 +const TIMEOUT = 57950 +const TASK = 57951 +const MATCH = 57952 +const AGAINST = 57953 +const BOOLEAN = 57954 +const LANGUAGE = 57955 +const QUERY = 57956 +const EXPANSION = 57957 +const WITHOUT = 57958 +const VALIDATION = 57959 +const UPGRADE = 57960 +const RETRY = 57961 +const ADDDATE = 57962 +const BIT_AND = 57963 +const BIT_OR = 57964 +const BIT_XOR = 57965 +const CAST = 57966 +const COUNT = 57967 +const APPROX_COUNT = 57968 +const APPROX_COUNT_DISTINCT = 57969 +const SERIAL_EXTRACT = 57970 +const APPROX_PERCENTILE = 57971 +const CURDATE = 57972 +const CURTIME = 57973 +const DATE_ADD = 57974 +const DATE_SUB = 57975 +const EXTRACT = 57976 +const GROUP_CONCAT = 57977 +const MAX = 57978 +const MID = 57979 +const MIN = 57980 +const NOW = 57981 +const POSITION = 57982 +const SESSION_USER = 57983 +const STD = 57984 +const STDDEV = 57985 +const MEDIAN = 57986 +const CLUSTER_CENTERS = 57987 +const KMEANS = 57988 +const STDDEV_POP = 57989 +const STDDEV_SAMP = 57990 +const SUBDATE = 57991 +const SUBSTR = 57992 +const SUBSTRING = 57993 +const SUM = 57994 +const SYSDATE = 57995 +const SYSTEM_USER = 57996 +const TRANSLATE = 57997 +const TRIM = 57998 +const VARIANCE = 57999 +const VAR_POP = 58000 +const VAR_SAMP = 58001 +const AVG = 58002 +const RANK = 58003 +const ROW_NUMBER = 58004 +const DENSE_RANK = 58005 +const CUME_DIST = 58006 +const BIT_CAST = 58007 +const LAG = 58008 +const LEAD = 58009 +const FIRST_VALUE = 58010 +const LAST_VALUE = 58011 +const NTH_VALUE = 58012 +const NTILE = 58013 +const PERCENT_RANK = 58014 +const BITMAP_BIT_POSITION = 58015 +const BITMAP_BUCKET_NUMBER = 58016 +const BITMAP_COUNT = 58017 +const BITMAP_CONSTRUCT_AGG = 58018 +const BITMAP_OR_AGG = 58019 +const JSON_ARRAYAGG = 58020 +const JSON_OBJECTAGG = 58021 +const GET_FORMAT = 58022 +const SRID = 58023 +const NEXTVAL = 58024 +const SETVAL = 58025 +const CURRVAL = 58026 +const LASTVAL = 58027 +const ROW = 58028 +const OUTFILE = 58029 +const HEADER = 58030 +const MAX_FILE_SIZE = 58031 +const FORCE_QUOTE = 58032 +const PARALLEL = 58033 +const STRICT = 58034 +const SPLITSIZE = 58035 +const UNUSED = 58036 +const BINDINGS = 58037 +const GENERATED = 58038 +const ALWAYS = 58039 +const STORED = 58040 +const VIRTUAL = 58041 +const DO = 58042 +const PERFORM = 58043 +const DECLARE = 58044 +const LOOP = 58045 +const WHILE = 58046 +const LEAVE = 58047 +const ITERATE = 58048 +const UNTIL = 58049 +const CALL = 58050 +const PREV = 58051 +const SLIDING = 58052 +const FILL = 58053 +const GAPFILL = 58054 +const SPBEGIN = 58055 +const BACKEND = 58056 +const SERVERS = 58057 +const HANDLER = 58058 +const PERCENT = 58059 +const SAMPLE = 58060 +const MO_TS = 58061 +const PITR = 58062 +const RECOVERY_WINDOW = 58063 +const INTERNAL = 58064 +const CDC_TASK_NAME = 58065 +const CDC = 58066 +const ICEBERG = 58067 +const CATALOG = 58068 +const CATALOGS = 58069 +const NAMESPACE = 58070 +const NAMESPACES = 58071 +const REF = 58072 +const FOR_ICEBERG = 58073 +const MONGODB = 58074 +const MONGODB_PATH = 58075 +const MONGODB_CONVERT = 58076 +const CONNECTIONS = 58077 +const DATASTREAM = 58078 +const ESQL = 58079 +const KAFKA = 58080 +const GROUPING = 58081 +const SETS = 58082 +const CUBE = 58083 +const ROLLUP = 58084 +const LOGSERVICE = 58085 +const REPLICAS = 58086 +const STORES = 58087 +const SETTINGS = 58088 +const DUMP = 58089 +const METADATA = 58090 +const KILL = 58091 +const BACKUP = 58092 +const FILESYSTEM = 58093 +const PARALLELISM = 58094 +const RESTORE = 58095 +const QUERY_RESULT = 58096 +const RETURNING = 58097 +const ARRAY = 58098 +const WITHIN = 58099 +const PERCENTILE_CONT = 58100 +const PERCENTILE_DISC = 58101 +const ASOF = 58102 +const TOLERANCE = 58103 +const WINDOW = 58104 +const WINDOW_NAME_EMPTY = 58105 +const RESPECT = 58106 +const MEMBER = 58107 +const AUTO_ID_CACHE = 58108 var yyToknames = [...]string{ "$end", @@ -1322,6 +1326,10 @@ var yyToknames = [...]string{ "ROUTINE", "EVENT", "SHUTDOWN", + "CALLED", + "INPUT", + "SCALAR", + "VECTOR", "NULLX", "AUTO_INCREMENT", "APPROXNUM", @@ -1638,7 +1646,7 @@ const yyEofCode = 1 const yyErrCode = 2 const yyInitialStackSize = 16 -//line mysql_sql.y:16591 +//line mysql_sql.y:16643 //line yacctab:1 var yyExca = [...]int{ @@ -1650,8872 +1658,8916 @@ var yyExca = [...]int{ 280, 743, 307, 750, 308, 750, - 548, 743, + 552, 743, -2, 783, -1, 172, 11, 994, 24, 994, -2, 980, -1, 198, - 278, 1569, - 280, 1394, - -2, 1472, + 278, 1578, + 280, 1403, + -2, 1481, -1, 275, - 783, 2551, + 787, 2563, -2, 617, - -1, 659, - 783, 2678, + -1, 663, + 787, 2691, -2, 454, - -1, 719, - 783, 2739, + -1, 723, + 787, 2752, -2, 452, - -1, 720, - 783, 2740, + -1, 724, + 787, 2753, -2, 453, - -1, 721, - 783, 2741, + -1, 725, + 787, 2754, -2, 455, - -1, 875, - 543, 783, - 544, 783, + -1, 879, + 547, 783, + 548, 783, -2, 744, - -1, 947, + -1, 951, 359, 212, - 520, 212, - 521, 212, - -2, 2394, - -1, 1017, - 90, 2130, - -2, 2613, - -1, 1018, - 90, 2149, - -2, 2582, + 524, 212, + 525, 212, + -2, 2404, + -1, 1021, + 90, 2139, + -2, 2626, -1, 1022, - 90, 2150, - -2, 2612, - -1, 1070, - 90, 2051, - -2, 2833, - -1, 1071, - 90, 2052, - -2, 2832, - -1, 1072, - 90, 2053, - -2, 2822, - -1, 1073, - 90, 2793, - -2, 2813, + 90, 2158, + -2, 2594, + -1, 1026, + 90, 2159, + -2, 2625, -1, 1074, - 90, 2794, - -2, 2814, + 90, 2060, + -2, 2846, -1, 1075, - 90, 2795, - -2, 2824, + 90, 2061, + -2, 2845, -1, 1076, - 90, 2796, - -2, 2802, + 90, 2062, + -2, 2835, -1, 1077, - 90, 2797, - -2, 2811, - -1, 1078, - 90, 2798, + 90, 2806, -2, 2826, + -1, 1078, + 90, 2807, + -2, 2827, -1, 1079, - 90, 2799, - -2, 2831, + 90, 2808, + -2, 2837, -1, 1080, - 90, 2800, - -2, 2836, + 90, 2809, + -2, 2815, -1, 1081, - 90, 2801, - -2, 2837, + 90, 2810, + -2, 2824, -1, 1082, - 90, 2126, - -2, 2651, + 90, 2811, + -2, 2839, -1, 1083, - 90, 2127, - -2, 2377, + 90, 2812, + -2, 2844, -1, 1084, - 90, 2128, - -2, 2661, + 90, 2813, + -2, 2849, -1, 1085, - 90, 2129, - -2, 2388, + 90, 2814, + -2, 2850, + -1, 1086, + 90, 2135, + -2, 2664, -1, 1087, - 90, 2132, - -2, 2396, + 90, 2136, + -2, 2387, + -1, 1088, + 90, 2137, + -2, 2674, -1, 1089, - 90, 2134, - -2, 2686, + 90, 2138, + -2, 2398, -1, 1091, - 90, 2136, - -2, 2420, + 90, 2141, + -2, 2406, -1, 1093, - 90, 2138, - -2, 2698, - -1, 1094, - 90, 2139, - -2, 2697, + 90, 2143, + -2, 2699, -1, 1095, - 90, 2140, - -2, 2506, - -1, 1096, - 90, 2141, - -2, 2608, - -1, 1099, - 90, 2144, - -2, 2709, - -1, 1100, 90, 2145, - -2, 2550, - -1, 1102, + -2, 2430, + -1, 1097, 90, 2147, - -2, 2712, - -1, 1103, + -2, 2711, + -1, 1098, 90, 2148, - -2, 2714, + -2, 2710, + -1, 1099, + 90, 2149, + -2, 2517, + -1, 1100, + 90, 2150, + -2, 2621, + -1, 1103, + 90, 2153, + -2, 2722, -1, 1104, - 90, 2151, - -2, 2721, - -1, 1105, - 90, 2152, - -2, 2591, + 90, 2154, + -2, 2562, -1, 1106, - 90, 2153, - -2, 2638, + 90, 2156, + -2, 2725, -1, 1107, - 90, 2154, - -2, 2602, + 90, 2157, + -2, 2727, -1, 1108, - 90, 2155, - -2, 2628, - -1, 1119, - 90, 2027, - -2, 2827, - -1, 1120, - 90, 2028, - -2, 2828, - -1, 1121, - 90, 2029, - -2, 2829, - -1, 1250, - 132, 2377, - 143, 2377, - 176, 2377, - -2, 2343, - -1, 1399, + 90, 2160, + -2, 2734, + -1, 1109, + 90, 2161, + -2, 2603, + -1, 1110, + 90, 2162, + -2, 2651, + -1, 1111, + 90, 2163, + -2, 2615, + -1, 1112, + 90, 2164, + -2, 2641, + -1, 1123, + 90, 2036, + -2, 2840, + -1, 1124, + 90, 2037, + -2, 2841, + -1, 1125, + 90, 2038, + -2, 2842, + -1, 1254, + 132, 2387, + 143, 2387, + 176, 2387, + -2, 2352, + -1, 1403, 24, 1029, -2, 956, - -1, 1602, + -1, 1606, 11, 994, 24, 994, - -2, 1868, - -1, 1704, + -2, 1877, + -1, 1708, 24, 1029, -2, 956, - -1, 2032, + -1, 2036, 46, 743, 280, 743, 307, 750, 308, 750, - 548, 743, + 552, 743, -2, 783, - -1, 2141, - 90, 2213, - -2, 2610, - -1, 2142, - 90, 2214, - -2, 2611, - -1, 2451, + -1, 2145, + 90, 2222, + -2, 2623, + -1, 2146, + 90, 2223, + -2, 2624, + -1, 2455, 11, 994, 24, 994, -2, 1175, - -1, 2925, + -1, 2929, 91, 1250, -2, 1256, - -1, 2942, - 115, 1467, - 163, 1467, - 211, 1467, - 214, 1467, - 320, 1467, + -1, 2946, + 115, 1476, + 163, 1476, + 211, 1476, + 214, 1476, + 320, 1476, + -2, 1469, + -1, 2949, + 38, 1512, -2, 1460, - -1, 2945, - 38, 1503, - -2, 1451, - -1, 3442, - 91, 2329, - 177, 2329, - -2, 2593, - -1, 3443, - 91, 2329, - 177, 2329, - -2, 2592, - -1, 3445, - 91, 2325, - 177, 2325, - -2, 2579, -1, 3446, - 91, 2281, - 177, 2281, - -2, 2584, + 91, 2338, + 177, 2338, + -2, 2605, -1, 3447, - 91, 2282, - 177, 2282, - -2, 2492, - -1, 3448, - 91, 2283, - 177, 2283, - -2, 2485, + 91, 2338, + 177, 2338, + -2, 2604, -1, 3449, - 91, 2325, - 177, 2325, - -2, 2362, + 91, 2334, + 177, 2334, + -2, 2591, -1, 3450, - 91, 2285, - 177, 2285, - -2, 2581, + 91, 2290, + 177, 2290, + -2, 2596, -1, 3451, - 91, 2286, - 177, 2286, - -2, 2490, + 91, 2291, + 177, 2291, + -2, 2503, -1, 3452, - 91, 2287, - 177, 2287, - -2, 2484, + 91, 2292, + 177, 2292, + -2, 2496, -1, 3453, - 91, 2288, - 177, 2288, - -2, 2460, + 91, 2334, + 177, 2334, + -2, 2371, -1, 3454, - 91, 2329, - 177, 2329, - -2, 2461, + 91, 2294, + 177, 2294, + -2, 2593, -1, 3455, - 91, 2329, - 177, 2329, - -2, 2462, + 91, 2295, + 177, 2295, + -2, 2501, -1, 3456, - 91, 2329, - 177, 2329, - -2, 2463, + 91, 2296, + 177, 2296, + -2, 2495, -1, 3457, - 91, 2329, - 177, 2329, - -2, 2464, + 91, 2297, + 177, 2297, + -2, 2471, -1, 3458, - 91, 2329, - 177, 2329, - -2, 2465, + 91, 2338, + 177, 2338, + -2, 2472, -1, 3459, - 91, 2329, - 177, 2329, - -2, 2466, + 91, 2338, + 177, 2338, + -2, 2473, + -1, 3460, + 91, 2338, + 177, 2338, + -2, 2474, -1, 3461, - 91, 2297, - 177, 2297, - -2, 2628, + 91, 2338, + 177, 2338, + -2, 2475, -1, 3462, - 91, 2268, - 177, 2268, - -2, 2613, + 91, 2338, + 177, 2338, + -2, 2476, -1, 3463, - 91, 2327, - 177, 2327, - -2, 2582, - -1, 3464, - 91, 2327, - 177, 2327, - -2, 2612, + 91, 2338, + 177, 2338, + -2, 2477, -1, 3465, - 91, 2327, - 177, 2327, - -2, 2397, + 91, 2306, + 177, 2306, + -2, 2641, -1, 3466, - 91, 2325, - 177, 2325, - -2, 2602, + 91, 2277, + 177, 2277, + -2, 2626, -1, 3467, - 90, 2248, - 91, 2248, - 166, 2248, - 167, 2248, - 169, 2248, - 177, 2248, - -2, 2361, + 91, 2336, + 177, 2336, + -2, 2594, -1, 3468, - 90, 2249, - 91, 2249, - 166, 2249, - 167, 2249, - 169, 2249, - 177, 2249, - -2, 2363, + 91, 2336, + 177, 2336, + -2, 2625, -1, 3469, - 90, 2250, - 91, 2250, - 166, 2250, - 167, 2250, - 169, 2250, - 177, 2250, - -2, 2657, + 91, 2336, + 177, 2336, + -2, 2407, -1, 3470, - 90, 2252, - 91, 2252, - 166, 2252, - 167, 2252, - 169, 2252, - 177, 2252, - -2, 2583, + 91, 2334, + 177, 2334, + -2, 2615, -1, 3471, - 90, 2254, - 91, 2254, - 166, 2254, - 167, 2254, - 169, 2254, - 177, 2254, - -2, 2561, + 90, 2257, + 91, 2257, + 166, 2257, + 167, 2257, + 169, 2257, + 177, 2257, + -2, 2370, -1, 3472, - 90, 2256, - 91, 2256, - 166, 2256, - 167, 2256, - 169, 2256, - 177, 2256, - -2, 2491, - -1, 3473, 90, 2258, 91, 2258, 166, 2258, 167, 2258, 169, 2258, 177, 2258, - -2, 2446, - -1, 3474, + -2, 2372, + -1, 3473, 90, 2259, 91, 2259, 166, 2259, 167, 2259, 169, 2259, 177, 2259, - -2, 2447, - -1, 3475, + -2, 2670, + -1, 3474, 90, 2261, 91, 2261, 166, 2261, 167, 2261, 169, 2261, 177, 2261, - -2, 2360, + -2, 2595, + -1, 3475, + 90, 2263, + 91, 2263, + 166, 2263, + 167, 2263, + 169, 2263, + 177, 2263, + -2, 2573, -1, 3476, - 91, 2332, - 166, 2332, - 167, 2332, - 169, 2332, - 177, 2332, - -2, 2404, + 90, 2265, + 91, 2265, + 166, 2265, + 167, 2265, + 169, 2265, + 177, 2265, + -2, 2502, -1, 3477, - 91, 2332, - 166, 2332, - 167, 2332, - 169, 2332, - 177, 2332, - -2, 2421, + 90, 2267, + 91, 2267, + 166, 2267, + 167, 2267, + 169, 2267, + 177, 2267, + -2, 2457, -1, 3478, - 91, 2335, - 166, 2335, - 167, 2335, - 169, 2335, - 177, 2335, - -2, 2398, + 90, 2268, + 91, 2268, + 166, 2268, + 167, 2268, + 169, 2268, + 177, 2268, + -2, 2458, -1, 3479, - 91, 2335, - 166, 2335, - 167, 2335, - 169, 2335, - 177, 2335, - -2, 2511, + 90, 2270, + 91, 2270, + 166, 2270, + 167, 2270, + 169, 2270, + 177, 2270, + -2, 2369, -1, 3480, - 91, 2332, - 166, 2332, - 167, 2332, - 169, 2332, - 177, 2332, - -2, 2541, + 91, 2341, + 166, 2341, + 167, 2341, + 169, 2341, + 177, 2341, + -2, 2414, -1, 3481, - 91, 2305, - 177, 2305, - -2, 2425, + 91, 2341, + 166, 2341, + 167, 2341, + 169, 2341, + 177, 2341, + -2, 2431, -1, 3482, - 91, 2306, - 177, 2306, - -2, 2526, + 91, 2344, + 166, 2344, + 167, 2344, + 169, 2344, + 177, 2344, + -2, 2408, -1, 3483, - 91, 2307, - 177, 2307, - -2, 2481, + 91, 2344, + 166, 2344, + 167, 2344, + 169, 2344, + 177, 2344, + -2, 2522, -1, 3484, - 91, 2308, - 177, 2308, - -2, 2527, + 91, 2341, + 166, 2341, + 167, 2341, + 169, 2341, + 177, 2341, + -2, 2553, -1, 3485, - 91, 2309, - 177, 2309, - -2, 2426, - -1, 3486, - 91, 2310, - 177, 2310, - -2, 2498, - -1, 3487, - 91, 2311, - 177, 2311, - -2, 2497, - -1, 3488, - 91, 2312, - 177, 2312, - -2, 2499, - -1, 3489, - 91, 2313, - 177, 2313, - -2, 2428, - -1, 3490, 91, 2314, 177, 2314, - -2, 2427, - -1, 3491, + -2, 2435, + -1, 3486, 91, 2315, 177, 2315, - -2, 2429, - -1, 3492, + -2, 2537, + -1, 3487, 91, 2316, 177, 2316, - -2, 2430, - -1, 3493, + -2, 2492, + -1, 3488, 91, 2317, 177, 2317, - -2, 2431, - -1, 3494, + -2, 2538, + -1, 3489, 91, 2318, 177, 2318, - -2, 2432, - -1, 3495, + -2, 2436, + -1, 3490, 91, 2319, 177, 2319, - -2, 2433, - -1, 3496, + -2, 2509, + -1, 3491, 91, 2320, 177, 2320, - -2, 2434, - -1, 3497, + -2, 2508, + -1, 3492, 91, 2321, 177, 2321, - -2, 2435, - -1, 3498, + -2, 2510, + -1, 3493, 91, 2322, 177, 2322, - -2, 2436, - -1, 3534, - 115, 1467, - 163, 1467, - 211, 1467, - 214, 1467, - 320, 1467, - -2, 1461, - -1, 3550, - 38, 1504, - -2, 1506, - -1, 3551, - 38, 1505, - -2, 1507, - -1, 3584, + -2, 2438, + -1, 3494, + 91, 2323, + 177, 2323, + -2, 2437, + -1, 3495, + 91, 2324, + 177, 2324, + -2, 2439, + -1, 3496, + 91, 2325, + 177, 2325, + -2, 2440, + -1, 3497, + 91, 2326, + 177, 2326, + -2, 2441, + -1, 3498, + 91, 2327, + 177, 2327, + -2, 2442, + -1, 3499, + 91, 2328, + 177, 2328, + -2, 2443, + -1, 3500, + 91, 2329, + 177, 2329, + -2, 2444, + -1, 3501, + 91, 2330, + 177, 2330, + -2, 2445, + -1, 3502, + 91, 2331, + 177, 2331, + -2, 2446, + -1, 3538, + 115, 1476, + 163, 1476, + 211, 1476, + 214, 1476, + 320, 1476, + -2, 1470, + -1, 3554, + 38, 1513, + -2, 1515, + -1, 3555, + 38, 1514, + -2, 1516, + -1, 3588, 87, 849, 177, 849, - -2, 1729, - -1, 4120, - 214, 1467, - 344, 1830, - -2, 1794, - -1, 4152, + -2, 1738, + -1, 4124, + 214, 1476, + 344, 1839, + -2, 1803, + -1, 4156, 11, 994, 24, 994, - -2, 1868, - -1, 4339, - 38, 1503, - 115, 1467, - 163, 1467, - 211, 1467, - 214, 1467, - -2, 1660, - -1, 4348, - 115, 1467, - 163, 1467, - 211, 1467, - 214, 1467, - -2, 1660, - -1, 4366, + -2, 1877, + -1, 4343, + 38, 1512, + 115, 1476, + 163, 1476, + 211, 1476, + 214, 1476, + -2, 1669, + -1, 4352, + 115, 1476, + 163, 1476, + 211, 1476, + 214, 1476, + -2, 1669, + -1, 4370, 87, 849, 177, 849, - -2, 1729, - -1, 4417, - 214, 1467, - 344, 1830, - -2, 1795, - -1, 4604, - 115, 1467, - 163, 1467, - 211, 1467, - 214, 1467, - -2, 1661, - -1, 4689, - 91, 1587, - 177, 1587, - -2, 1467, - -1, 4899, - 91, 1587, - 177, 1587, - -2, 1467, - -1, 5136, - 91, 1591, - 177, 1591, - -2, 1467, - -1, 5203, - 91, 1592, - 177, 1592, - -2, 1467, + -2, 1738, + -1, 4421, + 214, 1476, + 344, 1839, + -2, 1804, + -1, 4608, + 115, 1476, + 163, 1476, + 211, 1476, + 214, 1476, + -2, 1670, + -1, 4693, + 91, 1596, + 177, 1596, + -2, 1476, + -1, 4903, + 91, 1596, + 177, 1596, + -2, 1476, + -1, 5140, + 91, 1600, + 177, 1600, + -2, 1476, + -1, 5207, + 91, 1601, + 177, 1601, + -2, 1476, } const yyPrivate = 57344 -const yyLast = 82870 +const yyLast = 83265 var yyAct = [...]int{ - 983, 958, 5272, 5252, 985, 5245, 5303, 5290, 3645, 5249, - 263, 5262, 5228, 5146, 5244, 3762, 5140, 4901, 2120, 5150, - 4390, 5091, 1975, 968, 4400, 4500, 3907, 5151, 4109, 5139, - 4899, 4090, 3162, 5041, 5080, 4723, 4929, 4758, 3957, 4198, - 4434, 1861, 3421, 4803, 3216, 3634, 1974, 3959, 4946, 4495, - 4199, 1641, 4898, 4855, 4987, 1486, 774, 4593, 3417, 2068, - 3541, 4314, 44, 5092, 1014, 2195, 5094, 1878, 4196, 3637, - 4637, 4902, 1915, 4833, 796, 1249, 4328, 4508, 4322, 3799, - 3041, 1461, 1493, 2182, 3339, 4418, 813, 823, 3365, 833, - 4115, 4622, 833, 250, 5, 3587, 4371, 3340, 1405, 1877, - 4600, 4027, 1457, 3542, 3543, 3419, 4606, 4009, 960, 2959, - 3553, 1258, 4576, 3209, 4179, 3763, 2123, 2567, 4013, 910, - 4312, 1256, 2452, 2422, 2570, 1440, 3731, 3664, 4274, 3761, - 3333, 4117, 1879, 4125, 4105, 4349, 3250, 3623, 3758, 2445, - 3429, 4149, 3617, 3437, 2619, 248, 3621, 4266, 3615, 829, - 2178, 3749, 2073, 170, 3520, 901, 3978, 2201, 1854, 3991, - 4028, 4124, 3030, 2980, 3989, 2733, 4030, 950, 4029, 3157, - 1985, 4040, 2965, 2316, 2968, 905, 4025, 1891, 3535, 2886, - 1958, 2960, 2776, 3939, 1166, 1967, 1789, 2885, 2729, 3189, - 951, 2624, 3168, 955, 1963, 3435, 2584, 3508, 1706, 3249, - 813, 1210, 2563, 2728, 3502, 3666, 1243, 3132, 2446, 3042, - 2465, 3045, 1948, 2454, 3650, 237, 3556, 3014, 2179, 3591, - 3590, 2979, 2453, 2957, 2963, 259, 7, 4, 885, 2385, - 1757, 2942, 2196, 1787, 774, 258, 6, 1322, 2115, 2730, - 959, 1496, 1988, 1916, 817, 1833, 2970, 813, 2933, 2967, - 1870, 1801, 1980, 795, 2428, 1839, 2412, 2189, 2936, 1475, - 2888, 2119, 773, 263, 2106, 263, 949, 1312, 1313, 2772, - 1438, 1497, 2157, 2072, 1240, 813, 26, 1421, 2641, 1923, - 898, 2376, 1443, 244, 1838, 2380, 1242, 1806, 38, 2384, - 2114, 1835, 956, 1264, 77, 1794, 1209, 969, 1127, 5229, - 951, 1732, 243, 77, 2406, 1130, 86, 1265, 1790, 907, - 54, 42, 1132, 908, 3133, 2202, 29, 814, 87, 249, - 1131, 27, 1291, 1129, 28, 236, 19, 1207, 1642, 10, - 832, 1471, 1189, 1788, 904, 870, 78, 4972, 153, 1202, - 81, 5, 80, 76, 2708, 4829, 3389, 1126, 2433, 2437, - 2438, 2439, 2434, 2444, 2435, 2441, 3389, 3389, 2436, 1565, - 2442, 1566, 1564, 1565, 2457, 1566, 1564, 1565, 2344, 1566, - 1564, 1309, 4212, 4369, 3949, 825, 4065, 16, 3948, 3814, - 830, 3813, 2745, 1406, 4556, 4331, 3134, 1733, 1407, 4191, - 3282, 3195, 1260, 3193, 1734, 2433, 2437, 2438, 2439, 2434, - 2444, 2435, 2441, 805, 2333, 2436, 3192, 2442, 1308, 3589, - 1310, 3190, 1930, 1305, 803, 247, 799, 1926, 800, 1304, - 801, 802, 837, 3366, 2433, 2437, 2438, 2439, 2434, 2444, - 2435, 2441, 4750, 4074, 2436, 3334, 2442, 2849, 4372, 2958, - 3217, 798, 2884, 1727, 2197, 3208, 1453, 1454, 1455, 1837, - 1406, 5069, 1452, 1684, 1262, 2666, 1345, 1989, 2697, 4217, - 2698, 2693, 1124, 1895, 827, 1816, 1305, 1761, 32, 4347, - 3163, 4540, 1305, 7, 1153, 1303, 2667, 3950, 1150, 1451, - 1592, 3946, 1598, 6, 2899, 2433, 2437, 2438, 2439, 2434, - 2444, 2435, 2441, 2891, 1123, 2436, 4999, 2442, 1595, 1597, - 1591, 2340, 1596, 1578, 1577, 1587, 1588, 1589, 1590, 1580, - 1581, 1582, 1583, 1584, 1585, 1586, 1579, 1736, 3925, 1593, - 3922, 5240, 1943, 1513, 3932, 3930, 9, 17, 3923, 3920, - 2327, 2880, 1715, 1928, 4493, 2796, 3794, 3792, 1994, 2629, - 4715, 77, 1565, 4205, 1566, 1564, 5148, 5147, 4941, 1254, - 1257, 15, 4766, 4759, 4496, 828, 77, 1255, 77, 1345, - 1253, 2433, 2437, 2438, 2439, 2434, 2444, 2435, 2441, 3934, - 4197, 2436, 1124, 2442, 5097, 1565, 2425, 1566, 1564, 2962, - 1636, 1069, 1128, 2324, 3885, 3976, 4545, 2237, 2180, 2181, - 2648, 3112, 2686, 1363, 1364, 1325, 3077, 5277, 4955, 1141, - 4543, 5236, 4775, 2047, 1123, 4772, 4952, 4815, 4303, 3314, - 2906, 1228, 5053, 1892, 824, 1444, 1353, 1357, 1359, 1361, - 1366, 1742, 1371, 1367, 1368, 1369, 1370, 1740, 2558, 1348, - 1349, 1350, 1351, 1323, 1324, 1354, 1739, 1326, 826, 1327, - 1329, 1330, 1331, 1332, 1328, 1333, 1334, 1335, 1336, 1337, - 1344, 1346, 1338, 1339, 1340, 1341, 1342, 1343, 1372, 1373, - 1374, 1375, 1376, 1377, 1378, 1379, 1381, 1380, 1382, 1383, - 1384, 1385, 1386, 1387, 1388, 1389, 1356, 1358, 1360, 1362, - 1365, 1449, 4298, 1450, 3979, 957, 939, 1992, 2923, 941, - 1154, 1151, 1267, 2526, 940, 903, 1363, 1364, 1325, 3880, - 1154, 2743, 1314, 1783, 1151, 3756, 2937, 2353, 1991, 3416, - 939, 1142, 3153, 941, 2351, 2065, 4817, 1347, 940, 1353, - 1357, 1359, 1361, 1366, 1561, 1371, 1367, 1368, 1369, 1370, - 3924, 3921, 1348, 1349, 1350, 1351, 1323, 1324, 1354, 3412, - 1326, 3798, 1327, 1329, 1330, 1331, 1332, 1328, 1333, 1334, - 1335, 1336, 1337, 1344, 1346, 1338, 1339, 1340, 1341, 1342, - 1343, 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1381, - 1380, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1356, - 1358, 1360, 1362, 1365, 3414, 3154, 3140, 1221, 1219, 3139, - 1220, 3767, 3141, 3768, 3769, 2546, 1929, 1927, 813, 2547, - 2548, 2580, 1541, 2358, 2359, 1542, 3069, 3935, 813, 1840, - 3118, 1842, 1448, 813, 3409, 1409, 1749, 2440, 1224, 3117, - 1347, 3956, 1152, 1592, 1148, 1598, 1149, 200, 245, 199, - 232, 201, 4094, 1544, 3210, 833, 833, 1435, 2044, 813, - 813, 1595, 1597, 1591, 894, 1596, 1578, 1577, 1587, 1588, - 1589, 1590, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1579, - 3261, 3260, 1593, 2107, 2440, 3413, 2111, 939, 4092, 4783, - 941, 2063, 2122, 1492, 3504, 940, 1483, 1491, 1494, 1495, - 5101, 829, 829, 829, 3505, 1494, 1495, 5182, 2088, 1559, - 2110, 1229, 1252, 2440, 1413, 3410, 5154, 5155, 1251, 5101, - 5188, 1823, 1114, 238, 1113, 1115, 1116, 5100, 1117, 1118, - 1534, 5100, 5187, 1536, 1509, 5099, 5186, 1510, 1399, 3001, - 5099, 2438, 2439, 5082, 5098, 1490, 2856, 2343, 1400, 4774, - 5098, 5185, 5113, 1463, 3503, 1487, 1554, 1487, 5085, 1401, - 4547, 1537, 4971, 1225, 5231, 5232, 4944, 3800, 1726, 813, - 4828, 4224, 1460, 3239, 2440, 4200, 4762, 4200, 1539, 5082, - 1469, 3843, 3388, 3933, 3801, 1896, 3802, 1479, 1611, 200, - 245, 199, 232, 201, 1817, 1260, 1499, 1500, 1407, 1502, - 1503, 1407, 1762, 1505, 1604, 3805, 1410, 2747, 1407, 2042, - 4983, 1315, 4947, 4948, 4949, 4950, 200, 245, 199, 232, - 201, 200, 245, 2744, 4221, 1227, 3547, 2354, 4313, 3415, - 2564, 2668, 3685, 2739, 2352, 2064, 1409, 4585, 1512, 2112, - 1540, 2554, 1546, 3815, 1826, 1547, 4005, 3812, 3127, 2102, - 2440, 2781, 4320, 4544, 2707, 3750, 822, 1262, 3839, 3411, - 1305, 3120, 1305, 2109, 1305, 821, 2931, 1355, 810, 2443, - 3426, 4782, 3549, 1549, 4447, 1407, 5115, 3511, 4077, 4784, - 3837, 1305, 3382, 1412, 1414, 1417, 1530, 2746, 1305, 1556, - 1305, 229, 238, 4819, 4820, 1557, 1558, 3540, 1521, 4619, - 4635, 3274, 2126, 1145, 3111, 3075, 3114, 1226, 1529, 2222, - 4494, 246, 1532, 3793, 3744, 5153, 2443, 3113, 2557, 1429, - 3123, 3124, 1543, 2578, 2579, 1535, 1538, 825, 825, 825, - 1481, 3122, 830, 830, 830, 1260, 4933, 2126, 1254, 1424, - 1427, 3217, 1477, 1478, 1645, 2443, 1255, 3544, 1531, 1398, - 1734, 1223, 1472, 1476, 1476, 1476, 1594, 3191, 2042, 200, - 245, 199, 232, 201, 2524, 1729, 1731, 1402, 1735, 1734, - 1355, 4773, 4825, 4582, 4541, 4011, 805, 1768, 1146, 1472, - 1472, 4010, 3391, 2108, 1753, 1433, 1434, 803, 1756, 799, - 1931, 800, 4347, 801, 802, 1765, 4409, 1262, 1545, 4994, - 3931, 1766, 3130, 4995, 4998, 4997, 2443, 2654, 1551, 1128, - 1428, 1320, 1552, 1553, 794, 4875, 827, 827, 827, 1504, - 4546, 4315, 1445, 2038, 813, 813, 813, 3999, 1498, 1210, - 1533, 1501, 1911, 1518, 1511, 238, 4096, 1815, 1550, 1514, - 1515, 1741, 813, 1738, 1822, 4405, 4818, 1828, 819, 820, - 4975, 813, 1993, 246, 4806, 774, 774, 1520, 4610, 1147, - 1548, 1704, 1222, 2125, 2124, 774, 774, 1217, 1701, 1865, - 1865, 1705, 813, 4557, 1218, 1419, 4003, 4107, 4108, 1408, - 246, 4041, 2443, 4106, 1708, 246, 4337, 4185, 1612, 4024, - 3550, 3507, 942, 943, 944, 945, 946, 2525, 2125, 2124, - 1507, 1508, 833, 3557, 796, 1494, 1495, 828, 828, 828, - 1919, 1867, 5011, 5001, 1320, 4278, 942, 943, 944, 945, - 946, 4098, 4862, 4099, 4101, 4100, 263, 4845, 1863, 1863, - 4000, 4001, 3033, 4280, 1155, 774, 2218, 4011, 3032, 3035, - 835, 1494, 1495, 2215, 834, 3754, 4002, 2217, 2214, 2216, - 2220, 2221, 831, 4102, 1767, 2219, 2944, 2939, 3997, 2132, - 2136, 2137, 4453, 3940, 1824, 4988, 824, 824, 824, 5013, - 2133, 4391, 2043, 3546, 5042, 1657, 1658, 4091, 3639, 1426, - 1425, 4398, 200, 245, 199, 232, 201, 2918, 1470, 1748, - 826, 826, 826, 4812, 4565, 1872, 3034, 4289, 1482, 1827, - 4549, 4550, 4551, 1144, 1888, 1889, 3969, 3110, 2440, 2134, - 1198, 1971, 1199, 4411, 1130, 4011, 1976, 4292, 79, 4410, - 1759, 1760, 4982, 246, 1763, 1859, 1860, 1990, 1771, 1773, - 1774, 1775, 1776, 4006, 1778, 4711, 1711, 5297, 1782, 3126, - 2565, 3751, 3088, 5114, 3635, 3636, 3840, 3639, 3552, 2000, - 1805, 2013, 1737, 4700, 3087, 1709, 1254, 2016, 238, 4511, - 1712, 1844, 1846, 3029, 1255, 1431, 2045, 1699, 3510, 3517, - 1700, 1857, 1858, 942, 943, 944, 945, 946, 2039, 2058, - 1646, 4821, 1850, 4586, 1849, 4291, 1865, 1519, 1983, 2681, - 3108, 3109, 1828, 3686, 831, 3687, 3688, 823, 829, 1594, - 2739, 829, 829, 2225, 2226, 2227, 2228, 2229, 2230, 2223, - 2224, 2555, 4863, 1468, 4097, 2030, 1418, 4846, 2087, 2103, - 4706, 831, 2046, 3514, 3515, 1828, 4111, 1485, 1484, 1770, - 2096, 2096, 2042, 1828, 1487, 1828, 1828, 1467, 3513, 1466, - 1979, 1932, 5043, 5138, 4904, 4834, 1865, 4116, 1865, 1409, - 1960, 1961, 1981, 4245, 1938, 1793, 1800, 1908, 1875, 2059, - 79, 1882, 1986, 1796, 1797, 4112, 1949, 2755, 2757, 2758, - 5265, 1848, 2050, 2053, 2054, 2057, 1969, 1873, 3384, 3078, - 1881, 2078, 1876, 1966, 1962, 1795, 1970, 79, 4350, 3032, - 2070, 2071, 3551, 4107, 4108, 1257, 1890, 4491, 2086, 3033, - 1758, 2089, 2090, 5079, 2091, 3032, 3035, 2080, 2081, 903, - 805, 1836, 3016, 3018, 1599, 1744, 2751, 2753, 2754, 77, - 1984, 3998, 1865, 4275, 200, 245, 199, 232, 201, 2093, - 4153, 1769, 1906, 1920, 4133, 3270, 4358, 2268, 2270, 2269, - 1409, 2199, 5095, 1526, 3145, 1921, 246, 3116, 3073, 2889, - 3048, 4963, 1772, 4964, 2736, 1746, 2135, 2250, 1601, 1600, - 2553, 2541, 1977, 3034, 831, 1755, 1604, 1777, 1606, 1607, - 1608, 1609, 1610, 3715, 2240, 2241, 2242, 2092, 2336, 3554, - 1999, 2183, 4306, 2002, 2003, 2099, 3051, 2256, 4469, 3398, - 2257, 1416, 2231, 2232, 3169, 3170, 2236, 2036, 1197, 4168, - 238, 4155, 3842, 2943, 2251, 4903, 1902, 2919, 4103, 1781, - 1998, 2278, 2279, 2001, 1780, 1779, 797, 2258, 1230, 2260, - 4375, 2261, 2262, 2263, 825, 2267, 5266, 825, 825, 830, - 79, 3738, 830, 830, 4714, 839, 2118, 2074, 4702, 2076, - 2077, 2311, 4701, 838, 3683, 1409, 830, 2066, 1525, 4110, - 4965, 200, 245, 5137, 2084, 1130, 1211, 2345, 1472, 2031, - 2079, 2348, 2098, 2029, 2027, 4267, 813, 813, 813, 2028, - 3058, 2019, 1476, 2085, 2024, 2363, 2365, 2018, 2366, 2023, - 2369, 2370, 2017, 2138, 2373, 1476, 1184, 796, 2377, 4707, - 4708, 2773, 2381, 2322, 1865, 2387, 2388, 1260, 2390, 1828, - 2748, 2749, 1266, 813, 4211, 2234, 1865, 2116, 2100, 2101, - 3237, 1804, 813, 827, 2075, 3017, 827, 827, 2069, 3047, - 1210, 2314, 3406, 2423, 3049, 2910, 808, 238, 809, 1752, - 2021, 2448, 2448, 1815, 2448, 2335, 2361, 2458, 2459, 813, - 813, 2312, 2523, 2362, 2095, 2097, 2381, 2534, 2317, 3052, - 1865, 2538, 2539, 1167, 2113, 4282, 1815, 2321, 774, 1262, - 2117, 2360, 4961, 2909, 2756, 1743, 1941, 2341, 1944, 1945, - 2404, 4963, 774, 4964, 1865, 5263, 5264, 2414, 3050, 2912, - 2911, 1950, 1951, 1952, 1953, 1954, 1955, 831, 246, 4957, - 2143, 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151, 2152, - 2153, 2154, 4359, 1156, 828, 200, 245, 828, 828, 2159, - 2175, 2176, 2475, 2752, 2596, 2598, 4210, 1758, 813, 2381, - 1865, 2025, 2605, 3100, 813, 901, 901, 2325, 2377, 200, - 245, 2612, 1157, 2614, 2615, 2616, 2200, 2337, 1158, 2620, - 4375, 2235, 1946, 895, 4104, 1947, 263, 2477, 3399, 263, - 263, 2391, 263, 79, 4623, 895, 2249, 1791, 3716, 3718, - 3719, 3720, 3717, 824, 2259, 3585, 824, 824, 1745, 1747, - 4965, 2450, 2389, 2456, 1750, 1751, 2532, 2320, 2543, 2323, - 2022, 238, 1965, 2530, 2528, 5333, 1260, 826, 2529, 1231, - 826, 826, 2581, 2121, 2405, 2264, 2265, 2573, 2574, 1213, - 1214, 1215, 5299, 4020, 2020, 238, 5327, 2656, 2586, 2587, - 1424, 1427, 2371, 2372, 3057, 246, 2674, 5312, 3055, 2378, - 2379, 2315, 4932, 2550, 5332, 2552, 3706, 3707, 4175, 1277, - 2392, 2393, 2394, 1254, 4958, 1259, 2571, 2572, 5093, 897, - 2375, 1255, 896, 2601, 2313, 895, 2559, 774, 1262, 2607, - 2334, 897, 2338, 5089, 896, 2386, 3135, 2342, 1462, 813, - 5067, 2423, 2566, 813, 2544, 5325, 2618, 2400, 2661, 2542, - 2690, 1563, 2692, 1160, 1563, 1565, 2696, 1566, 1564, 2935, - 5323, 1428, 2582, 3564, 2701, 2702, 2703, 829, 2706, 1259, - 1828, 2628, 5314, 3072, 2631, 2632, 2604, 2634, 1964, 2652, - 3524, 3530, 3531, 3532, 3525, 3529, 3526, 3528, 3527, 2669, - 1563, 2537, 2418, 2419, 829, 2424, 2420, 2407, 2411, 1828, - 2042, 1165, 2407, 3586, 1415, 4170, 1865, 2732, 885, 831, - 2010, 2531, 1526, 1565, 3877, 1566, 1564, 1164, 3432, 2536, - 2873, 897, 1162, 1161, 896, 2817, 2007, 2008, 2549, 2816, - 2551, 1563, 2691, 2735, 5310, 2694, 2695, 2105, 2560, 2699, - 4021, 245, 4174, 1462, 2060, 2061, 1563, 5287, 3705, 246, - 200, 245, 2710, 2711, 3433, 3434, 2638, 4340, 5311, 2645, - 5284, 2116, 2713, 2714, 2684, 1563, 2790, 1462, 2617, 2329, - 2416, 5281, 3876, 246, 2591, 79, 2595, 4263, 2700, 3009, - 2653, 1702, 2657, 2760, 2602, 2608, 2609, 2718, 2721, 2610, - 2603, 1266, 2934, 2589, 2723, 3009, 2725, 1565, 2590, 1566, - 1564, 2413, 2625, 4724, 4725, 4726, 4730, 4728, 4729, 4731, - 4732, 4733, 4734, 4727, 1163, 1563, 238, 3048, 3051, 77, - 5311, 4064, 77, 77, 5279, 77, 2415, 200, 245, 245, - 1426, 1425, 2012, 5288, 4958, 1563, 2643, 2658, 4959, 200, - 245, 2011, 5274, 1160, 4223, 5259, 5285, 2663, 5220, 2677, - 2271, 2726, 3009, 2274, 2275, 2276, 2789, 5282, 2280, 2281, - 2282, 2283, 2285, 2286, 2287, 2288, 2289, 2290, 2291, 2292, - 2294, 2295, 2296, 2297, 2298, 2155, 2156, 2676, 2660, 1884, - 3269, 2173, 2174, 2678, 5205, 2177, 200, 245, 5168, 1982, - 3549, 200, 245, 825, 2827, 1526, 1526, 2830, 830, 2832, - 4175, 2680, 2735, 2662, 238, 2104, 2839, 1159, 4136, 2683, - 2741, 3586, 1162, 1161, 1260, 238, 3048, 3051, 4134, 2852, - 825, 2712, 4085, 4082, 4175, 830, 3985, 2719, 5275, 3915, - 2720, 5206, 200, 245, 5221, 1458, 2890, 4207, 2892, 1459, - 2894, 2895, 4051, 2709, 2898, 1523, 3982, 1135, 1136, 1137, - 1138, 2722, 813, 1828, 813, 1828, 1565, 3938, 1566, 1564, - 3570, 5167, 238, 1476, 2779, 2913, 1133, 238, 1286, 2727, - 5206, 3247, 2920, 2921, 5169, 950, 1262, 4923, 2738, 813, - 813, 3052, 827, 1266, 2932, 5166, 3047, 3032, 3046, 3385, - 3043, 3049, 3912, 813, 813, 813, 1524, 2855, 2857, 2858, - 2859, 1851, 2861, 2735, 246, 3214, 2734, 5156, 238, 827, - 2793, 3156, 2871, 2864, 246, 3916, 2966, 2966, 2972, 1565, - 1702, 1566, 1564, 2545, 2618, 2981, 1815, 1815, 1815, 1815, - 1815, 1815, 1815, 1815, 2761, 2872, 1524, 2759, 3027, 2766, - 1565, 2883, 1566, 1564, 2774, 3050, 2783, 1563, 2448, 1135, - 1136, 1137, 1138, 1287, 4581, 2870, 2716, 2764, 2765, 2159, - 2869, 2826, 2769, 2770, 2159, 3269, 2825, 2824, 1133, 2950, - 2682, 1563, 5134, 828, 2955, 3064, 2576, 2540, 3913, 5133, - 3052, 2414, 2414, 1799, 2186, 3047, 3032, 3046, 4744, 3043, - 3049, 246, 246, 2791, 5064, 2862, 986, 996, 4375, 2865, - 828, 3036, 4369, 246, 3019, 2903, 987, 2905, 988, 992, - 995, 991, 989, 990, 4362, 3873, 1139, 4319, 5014, 3784, - 2875, 2876, 1565, 5005, 1566, 1564, 1299, 1300, 1301, 4919, - 3588, 3044, 824, 1565, 1887, 1566, 1564, 1135, 1136, 1137, - 1138, 813, 2096, 1280, 3050, 1272, 1276, 1278, 3569, 1565, - 246, 1566, 1564, 3071, 4918, 246, 826, 4742, 5135, 824, - 3394, 1298, 774, 774, 1295, 2741, 2734, 3272, 3271, 1260, - 1409, 1283, 4917, 3238, 993, 1275, 1865, 813, 2878, 4462, - 2791, 2863, 2927, 826, 1130, 1565, 2812, 1566, 1564, 2969, - 2795, 2637, 3361, 4916, 2724, 4915, 246, 4866, 2045, 2893, - 3164, 3165, 4865, 2897, 2741, 994, 4831, 813, 2715, 1563, - 2679, 2623, 796, 2339, 2575, 2791, 3310, 3311, 1139, 1919, - 1995, 4800, 3180, 3304, 3182, 4797, 1281, 263, 1620, 1430, - 3044, 1262, 3038, 3053, 3054, 3151, 3040, 4642, 3039, 2982, - 2791, 2924, 2951, 1565, 2868, 1566, 1564, 3115, 1284, 3175, - 1371, 1367, 1368, 1369, 1370, 1285, 3008, 3309, 2791, 3308, - 3307, 3305, 4641, 2966, 2966, 3223, 1395, 1579, 3142, 1390, - 3143, 4069, 3234, 4567, 4566, 2973, 2974, 3303, 1645, 2791, - 3240, 2791, 3834, 2741, 5002, 4464, 2083, 4412, 2741, 3148, - 3149, 4385, 2791, 4382, 3245, 4356, 3002, 3007, 3248, 3251, - 1273, 4256, 2787, 3136, 3253, 4486, 1139, 1563, 1865, 2778, - 2777, 2977, 4252, 3026, 2983, 2984, 2985, 2986, 2987, 2988, - 2989, 4144, 4046, 4643, 1282, 3266, 1936, 1935, 2732, 3864, - 5003, 3810, 3167, 3190, 3808, 1865, 4189, 1865, 3574, 1196, - 3572, 5300, 1409, 3566, 829, 3306, 5289, 3359, 2977, 3346, - 3283, 3338, 1292, 1293, 1294, 1297, 5286, 1296, 1506, 4085, - 4082, 3284, 1274, 2367, 1601, 1600, 3242, 3255, 1844, 1846, - 3218, 2042, 3185, 4413, 3205, 3203, 1473, 4085, 3201, 4082, - 3155, 1563, 3199, 3010, 2976, 3125, 3131, 4257, 2874, 2835, - 2834, 1865, 1409, 2815, 3257, 3244, 3317, 2806, 4253, 3246, - 3262, 3137, 2368, 2805, 2804, 2792, 5283, 4145, 3567, 2740, - 2004, 5235, 3256, 3326, 4515, 1563, 1260, 3573, 1865, 3318, - 3567, 4042, 3263, 3264, 3575, 3267, 3573, 3152, 1599, 3567, - 3848, 2626, 3312, 1563, 4624, 1563, 2969, 1563, 4847, 2239, - 2238, 1458, 952, 3825, 1279, 1459, 3295, 1563, 2762, 2763, - 1863, 3211, 2977, 2767, 2768, 4353, 1853, 3362, 1599, 3327, - 3206, 3204, 3179, 1458, 3200, 3172, 3070, 1459, 3200, 3009, - 2977, 4351, 1601, 1600, 2873, 1563, 1563, 1863, 1262, 1563, - 4625, 3254, 1458, 1563, 2239, 2238, 1459, 3219, 1269, 1563, - 1563, 2791, 3392, 4973, 1855, 2741, 2005, 3396, 2170, 1474, - 3400, 4354, 1601, 1600, 4043, 1856, 3212, 813, 813, 813, - 3215, 3222, 3232, 3221, 2167, 2169, 2166, 4352, 2168, 3341, - 77, 4892, 4891, 3241, 4830, 3347, 1412, 1409, 3499, 4770, - 4848, 4704, 3184, 4703, 3280, 1865, 3958, 3298, 1828, 3300, - 3275, 4687, 4514, 4652, 1828, 2534, 4589, 4363, 4330, 3332, - 4044, 4176, 3336, 3368, 2966, 3370, 3371, 2284, 3364, 4166, - 3335, 4158, 1852, 3315, 3265, 4146, 3342, 3268, 5131, 3293, - 825, 4087, 3378, 3273, 4084, 830, 4849, 2055, 3581, 3584, - 4015, 1578, 1577, 1587, 1588, 1589, 1590, 1580, 1581, 1582, - 1583, 1584, 1585, 1586, 1579, 2051, 2116, 3747, 3379, 1288, - 3746, 3562, 2277, 1268, 1270, 3576, 3571, 3522, 3548, 3390, - 1815, 1271, 1815, 2819, 1646, 3281, 3147, 2896, 3577, 3578, - 2672, 3619, 3625, 2671, 3313, 2670, 1785, 3302, 1784, 1411, - 3640, 1409, 3285, 3286, 3642, 3643, 3644, 3288, 3289, 1409, - 1582, 1583, 1584, 1585, 1586, 1579, 2190, 3654, 2784, 3536, - 1565, 5130, 1566, 1564, 1409, 1409, 1409, 2096, 4372, 827, - 1409, 3669, 3961, 3670, 3671, 1924, 3672, 2626, 3674, 5, - 3377, 1792, 3424, 2408, 3539, 5007, 2190, 1792, 3785, 3669, - 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1579, 3961, 1791, - 3518, 5184, 2448, 2165, 3321, 4856, 3537, 5173, 1458, 2475, - 2056, 4799, 1459, 1306, 1307, 4798, 3728, 1564, 1311, 2162, - 2164, 2161, 3328, 2163, 1566, 1564, 1458, 4718, 2052, 1565, - 1459, 1566, 1564, 774, 1565, 4717, 1566, 1564, 3380, 3381, - 4192, 2534, 3866, 4190, 2477, 1409, 1409, 1565, 2405, 1566, - 1564, 1565, 3958, 1566, 1564, 3439, 1865, 4047, 3194, 1924, - 828, 3765, 1587, 1588, 1589, 1590, 1580, 1581, 1582, 1583, - 1584, 1585, 1586, 1579, 3516, 3675, 3960, 813, 3558, 3733, - 3673, 3657, 1409, 1792, 3655, 3781, 4693, 3545, 3560, 1815, - 3500, 3501, 1565, 4692, 1566, 1564, 3278, 263, 3561, 5033, - 5034, 3297, 263, 5031, 5032, 3851, 2386, 3865, 3579, 3647, - 3583, 7, 5132, 3580, 1622, 3594, 3595, 3596, 3597, 824, - 3373, 6, 3374, 1565, 3659, 1566, 1564, 1621, 1919, 3806, - 3325, 5296, 3186, 5208, 1565, 3607, 1566, 1564, 3611, 3612, - 3613, 3608, 3606, 826, 5126, 5037, 3739, 3226, 3630, 3817, - 1565, 3627, 1566, 1564, 3628, 4896, 4897, 3225, 3251, 2954, - 1565, 3649, 1566, 1564, 3766, 3651, 3651, 5036, 3782, 3652, - 3651, 3158, 3159, 3656, 3662, 1565, 2254, 1566, 1564, 77, - 1865, 2808, 4583, 3836, 1925, 1565, 3653, 1566, 1564, 3752, - 1565, 2255, 1566, 1564, 3689, 4590, 4591, 5035, 5295, 3076, - 3807, 5030, 3079, 3080, 3081, 3082, 3083, 3084, 3085, 3086, - 3702, 3783, 3089, 3090, 3091, 3092, 3093, 3094, 3095, 3096, - 3097, 3098, 3099, 4317, 3101, 3102, 3103, 3104, 3105, 1565, - 3106, 1566, 1564, 3748, 3742, 5029, 3819, 5143, 3821, 3745, - 5028, 3727, 3786, 5027, 4584, 3725, 5050, 3790, 3826, 1565, - 5026, 1566, 1564, 2807, 3723, 3828, 3829, 4791, 3820, 3770, - 3773, 3823, 3824, 3775, 1565, 5025, 1566, 1564, 3521, 5023, - 3779, 3827, 3712, 1565, 3909, 1566, 1564, 3780, 3830, 4529, - 1565, 3440, 1566, 1564, 1565, 4318, 1566, 1564, 3788, 3787, - 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1568, 5022, 5021, - 3439, 5020, 3944, 3726, 5019, 3947, 1565, 3724, 1566, 1564, - 3951, 5018, 813, 1828, 2799, 3928, 3722, 3869, 3774, 5016, - 5015, 3963, 3965, 3966, 3968, 5004, 3970, 3971, 3881, 3418, - 3883, 4527, 3886, 3887, 3711, 4518, 4907, 3888, 3889, 3890, - 3891, 3892, 1409, 3893, 3894, 3895, 3896, 3897, 3898, 3899, - 3900, 3838, 3902, 3903, 3904, 3905, 3833, 3822, 1565, 4517, - 1566, 1564, 1565, 4869, 1566, 1564, 4850, 3291, 3832, 3292, - 4824, 4516, 4796, 3910, 3803, 4760, 3914, 4713, 3917, 3918, - 3845, 4870, 4627, 4626, 4392, 3641, 1565, 2788, 1566, 1564, - 77, 3846, 4457, 3648, 3847, 77, 3863, 4241, 1565, 3857, - 1566, 1564, 4355, 3859, 3860, 4316, 4299, 4323, 3648, 3660, - 3661, 4004, 1987, 1565, 3665, 1566, 1564, 3993, 3995, 1565, - 3818, 1566, 1564, 3797, 1565, 3796, 1566, 1564, 4008, 3736, - 3856, 3710, 3858, 3709, 813, 1578, 1577, 1587, 1588, 1589, - 1590, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1579, 4023, - 3708, 1409, 3700, 3937, 3694, 813, 3693, 813, 2534, 3692, - 4329, 3691, 3690, 1409, 4231, 3954, 1409, 1565, 3386, 1566, - 1564, 3243, 3207, 3144, 2882, 2687, 2647, 2646, 2966, 3942, - 4055, 2966, 3941, 2644, 4058, 2640, 4059, 3927, 2639, 3764, - 3764, 1565, 4045, 1566, 1564, 2593, 1815, 2981, 2350, 4068, - 1577, 1587, 1588, 1589, 1590, 1580, 1581, 1582, 1583, 1584, - 1585, 1586, 1579, 4031, 2347, 3548, 1996, 1725, 3919, 3990, - 1393, 3229, 4019, 3878, 3231, 5278, 3440, 3619, 1069, 3230, - 3871, 4822, 4823, 3625, 4061, 5316, 5276, 4012, 4501, 4052, - 3926, 5233, 2786, 5192, 3064, 1565, 4022, 1566, 1564, 3870, - 1565, 3536, 1566, 1564, 3011, 1960, 1961, 1565, 5110, 1566, - 1564, 4122, 5108, 4122, 4126, 4804, 4126, 4126, 3867, 3986, - 3996, 1409, 1949, 1847, 5077, 1969, 1565, 4985, 1566, 1564, - 3360, 1392, 1966, 4113, 4137, 1970, 3358, 3539, 4054, 1962, - 3357, 5328, 1865, 1865, 4594, 1565, 4979, 1566, 1564, 4970, - 2317, 4968, 4089, 4951, 1260, 4942, 4057, 1565, 4906, 1566, - 1564, 4905, 4884, 1565, 3355, 1566, 1564, 1565, 4066, 1566, - 1564, 4883, 1565, 4018, 1566, 1564, 4649, 4874, 4093, 4095, - 4873, 5063, 3354, 4138, 4139, 4827, 4811, 4036, 4809, 4037, - 813, 1565, 4039, 1566, 1564, 4795, 4761, 3353, 3506, 4050, - 4053, 1863, 1863, 2969, 3993, 4056, 4048, 4697, 2405, 1565, - 4067, 1566, 1564, 4063, 4696, 4695, 1262, 1828, 4598, 4587, - 2534, 2534, 4572, 4571, 1565, 4083, 1566, 1564, 4569, 4086, - 1578, 1577, 1587, 1588, 1589, 1590, 1580, 1581, 1582, 1583, - 1584, 1585, 1586, 1579, 4121, 3317, 4123, 4562, 4560, 4539, - 4538, 4131, 4537, 4193, 3038, 3352, 1567, 4533, 3040, 4088, - 3039, 4532, 3351, 4505, 1603, 4503, 4499, 3350, 4497, 4475, - 4472, 4466, 3349, 3732, 1614, 4311, 4301, 4127, 4128, 3348, - 4284, 4132, 1565, 3345, 1566, 1564, 4268, 3854, 3855, 1565, - 3344, 1566, 1564, 4239, 1565, 4135, 1566, 1564, 4236, 1565, - 1624, 1566, 1564, 813, 4173, 4206, 1565, 4177, 1566, 1564, - 1565, 4164, 1566, 1564, 3343, 4143, 4163, 1565, 4161, 1566, - 1564, 4160, 4147, 4229, 4142, 4141, 4016, 4120, 3980, 3972, - 3962, 4208, 3952, 3945, 4232, 4647, 3983, 3943, 3681, 3682, - 5326, 1565, 2887, 1566, 1564, 3844, 3337, 3841, 4129, 4151, - 3816, 4148, 3795, 3322, 3698, 3699, 3772, 3740, 4171, 4172, - 4162, 3737, 4213, 4157, 4159, 4215, 4216, 4156, 4165, 4169, - 3734, 3721, 4218, 1565, 3713, 1566, 1564, 3703, 4203, 4209, - 1565, 3701, 1566, 1564, 3697, 4214, 3696, 3743, 3316, 1578, - 1577, 1587, 1588, 1589, 1590, 1580, 1581, 1582, 1583, 1584, - 1585, 1586, 1579, 3695, 3600, 3425, 3407, 4270, 3395, 3387, - 3224, 4271, 3213, 2620, 3173, 1565, 2914, 1566, 1564, 2901, - 3294, 1069, 1068, 5061, 2867, 4285, 1945, 4287, 2900, 5270, - 2750, 2651, 4293, 2650, 3619, 3625, 1713, 1950, 1951, 1952, - 1953, 1954, 1955, 2642, 2383, 3648, 1409, 1565, 2866, 1566, - 1564, 1565, 2860, 1566, 1564, 2349, 2346, 3648, 4281, 4220, - 3648, 4246, 4225, 2829, 4248, 4294, 2332, 4219, 2828, 2331, - 2094, 813, 2534, 4240, 1997, 1565, 2185, 1566, 1564, 1565, - 1653, 1566, 1564, 1649, 1648, 4338, 4288, 1397, 4290, 1143, - 1565, 5268, 1566, 1564, 5045, 1565, 4344, 1566, 1564, 200, - 245, 4260, 4801, 1565, 4790, 1566, 1564, 5258, 4309, 4310, - 3548, 3548, 5256, 4276, 2239, 2238, 4789, 4777, 245, 199, - 232, 201, 4771, 4570, 2448, 1815, 4366, 245, 199, 232, - 201, 4536, 5257, 2423, 4522, 4512, 4467, 5255, 5294, 4377, - 4360, 4348, 4346, 3619, 4339, 3251, 3625, 4264, 4387, 4269, - 4262, 4327, 4259, 4341, 4258, 3548, 4265, 4273, 4374, 4255, - 4254, 202, 4242, 4238, 4235, 3648, 4195, 4194, 4184, 4178, - 2293, 902, 4075, 4062, 3984, 238, 5292, 4414, 3981, 4300, - 1409, 4296, 4295, 4304, 4401, 4402, 4403, 4404, 3936, 4307, - 4122, 4151, 1918, 238, 1409, 1409, 4324, 4461, 3874, 3861, - 3853, 1865, 238, 2952, 3852, 3850, 3614, 3202, 4367, 3198, - 4326, 4336, 3197, 3196, 3161, 3160, 4470, 2840, 4345, 2833, - 2823, 4361, 2822, 2821, 4368, 2820, 2818, 2814, 2953, 813, - 2813, 2534, 2811, 2802, 2798, 1815, 1409, 2797, 2717, 2649, - 4261, 2304, 4463, 2302, 2301, 2300, 4487, 4365, 2299, 2253, - 2252, 263, 2243, 3875, 245, 1886, 4373, 3646, 5269, 5198, - 1863, 4448, 4305, 4364, 3439, 5197, 5196, 5172, 5165, 5163, - 5070, 5049, 1643, 5044, 4936, 4935, 4934, 4914, 4507, 4908, - 4882, 4383, 4483, 4384, 4389, 4381, 4738, 4441, 4716, 4710, - 4651, 4628, 4455, 4454, 4451, 4450, 4449, 4399, 4406, 4396, - 4394, 4332, 4283, 4279, 4237, 4078, 4476, 1578, 1577, 1587, - 1588, 1589, 1590, 1580, 1581, 1582, 1583, 1584, 1585, 1586, - 1579, 4072, 4460, 4456, 4458, 1965, 1968, 1940, 1959, 238, - 1956, 1942, 4465, 4468, 1937, 3977, 3974, 4473, 4471, 3973, - 2423, 3901, 3862, 4552, 4474, 1130, 3735, 4558, 3729, 3658, - 3565, 4481, 3559, 4564, 4477, 4479, 4506, 4480, 4510, 3555, - 4478, 4482, 1802, 3383, 3171, 2062, 4554, 3146, 3107, 2994, - 2975, 2926, 2925, 2881, 2771, 2160, 238, 4504, 4502, 2664, - 2417, 2328, 2040, 4521, 1957, 1724, 4523, 1703, 1698, 1697, - 1696, 2082, 1695, 1409, 1865, 1865, 4492, 1694, 4599, 4530, - 1693, 1409, 1692, 1691, 4526, 1690, 4528, 1689, 4561, 4520, - 4563, 1688, 1687, 1686, 1685, 1684, 1683, 1682, 1681, 1409, - 1680, 4038, 1679, 4630, 1678, 4524, 4519, 1677, 1676, 1675, - 1674, 1673, 1672, 4640, 4629, 4596, 4534, 1671, 1670, 1669, - 1668, 1667, 1666, 1665, 1664, 4393, 1663, 4395, 1662, 1661, - 1660, 1659, 1656, 1863, 2183, 1409, 1655, 1409, 4595, 4645, - 4601, 1654, 3548, 4548, 1652, 4542, 2128, 2129, 2130, 2131, - 1651, 4605, 4634, 4648, 1650, 4650, 1647, 4575, 4597, 1640, - 4605, 998, 172, 4578, 1639, 1637, 1636, 1635, 1634, 1865, - 3440, 172, 4588, 4686, 1633, 1632, 1631, 4555, 1630, 1629, - 1628, 1627, 4607, 4602, 4603, 4611, 4632, 4633, 813, 4621, - 1409, 1409, 1409, 4620, 2187, 1409, 1409, 4613, 2191, 2192, - 2193, 2194, 4368, 4618, 1626, 2669, 1603, 4636, 1625, 2233, - 4743, 4608, 1619, 1618, 1617, 1616, 1615, 1528, 2244, 1489, - 1394, 4644, 3592, 3593, 77, 5059, 4740, 5056, 2183, 4735, - 4452, 2941, 2705, 1436, 4756, 4757, 5212, 5210, 4448, 806, - 5152, 4154, 3741, 4691, 4688, 3523, 2272, 2273, 172, 3166, - 2958, 1865, 4698, 4752, 1527, 4720, 4721, 4722, 1456, 2992, - 4736, 4737, 3006, 3604, 4441, 4574, 2999, 2997, 3605, 4076, - 2991, 3000, 2998, 3603, 2303, 4746, 2305, 2306, 2307, 2308, - 2309, 4792, 4793, 82, 813, 2995, 2318, 1487, 4785, 3602, - 2996, 4745, 4769, 3004, 3601, 3005, 4080, 3598, 4805, 3003, - 4807, 2990, 4747, 1813, 4415, 5090, 4081, 4954, 4953, 4927, - 1863, 4484, 4748, 5324, 5320, 4690, 4357, 3809, 4459, 3665, - 3568, 1786, 4763, 2402, 2403, 2397, 2398, 2399, 3677, 4014, - 1125, 3021, 4768, 4808, 4343, 4810, 3678, 3679, 3680, 4118, - 4531, 4119, 3911, 3777, 4776, 3074, 4180, 4778, 4182, 4183, - 4764, 4840, 3023, 3022, 4407, 4308, 4786, 4079, 4787, 2515, - 3764, 804, 4485, 1933, 4813, 4181, 3563, 1982, 4788, 1133, - 3158, 3159, 2916, 1791, 3279, 2410, 1919, 2908, 2907, 4640, - 4640, 1978, 1216, 5068, 4859, 2915, 1982, 2611, 2527, 811, - 1522, 4851, 1409, 4911, 4836, 4568, 4032, 3988, 3987, 3629, - 1261, 4832, 4814, 4835, 3227, 3548, 3025, 4826, 2949, 172, - 4868, 2421, 2374, 2239, 2238, 5225, 4838, 5199, 4853, 1722, - 1723, 4910, 4839, 4140, 172, 3128, 172, 1720, 1721, 1718, - 1719, 3121, 4653, 3020, 4510, 4843, 4841, 2318, 4685, 2535, - 1125, 1517, 2318, 2318, 1716, 1717, 1516, 4609, 4854, 4857, - 4858, 1555, 3811, 2673, 2172, 4694, 4864, 1135, 1136, 1137, - 1138, 3610, 1259, 1488, 1133, 5179, 2917, 2675, 2585, 2049, - 1465, 1464, 1447, 1133, 1488, 4580, 1133, 3277, 2689, 1409, - 5177, 5116, 1865, 5087, 4579, 4924, 3276, 5086, 5084, 4989, - 4937, 4930, 4646, 4525, 4852, 4498, 4490, 4380, 4379, 4202, - 4201, 1707, 3059, 1206, 3028, 1885, 4489, 2627, 4187, 3882, - 2630, 3356, 1462, 2633, 5214, 5213, 2635, 4909, 5128, 5129, - 5201, 4559, 4286, 4921, 4272, 3648, 4251, 3831, 3402, 3401, - 3393, 4925, 4926, 3178, 3174, 2800, 2127, 1432, 1403, 4969, - 5213, 1863, 5214, 3764, 4920, 4962, 4712, 4974, 5200, 5183, - 1302, 5125, 1135, 1136, 1137, 1138, 4981, 1259, 5123, 5121, - 2171, 3422, 3420, 4577, 2877, 1973, 4333, 4334, 4335, 1259, - 4250, 807, 4938, 3290, 1135, 1136, 1137, 1138, 811, 2121, - 1480, 2121, 4976, 91, 4977, 4956, 4939, 2, 4960, 5238, - 5239, 1, 3929, 2879, 2326, 1714, 4986, 1578, 1577, 1587, - 1588, 1589, 1590, 1580, 1581, 1582, 1583, 1584, 1585, 1586, - 1579, 4978, 1134, 1841, 3138, 2577, 5017, 1869, 2330, 1140, - 3012, 3013, 3609, 1409, 4966, 4967, 3015, 4984, 2594, 1442, - 3408, 2737, 3753, 3119, 2930, 4007, 1803, 4990, 5000, 3548, - 1212, 5024, 4993, 2245, 2009, 1423, 2006, 1422, 5006, 4991, - 1420, 5009, 5010, 2188, 2266, 1409, 1000, 5039, 2961, 3730, - 1487, 3704, 4376, 1865, 5066, 5224, 5271, 5171, 5227, 2655, - 2035, 984, 5078, 4204, 3804, 4943, 5175, 5074, 4945, 4767, - 5055, 5057, 5058, 5060, 5062, 2742, 1560, 4049, 865, 1046, - 1012, 1638, 5038, 2659, 3884, 3879, 1011, 5071, 5072, 4321, - 3512, 5047, 4931, 5075, 5065, 4844, 866, 2636, 4940, 4765, - 1934, 1939, 3024, 4861, 5040, 4689, 5109, 4114, 3638, 1972, - 5054, 5096, 1863, 921, 920, 927, 917, 5012, 5076, 4397, - 4781, 4779, 4780, 1865, 5083, 5081, 924, 925, 3908, 926, - 930, 4928, 4749, 911, 5106, 909, 2556, 772, 5102, 5104, - 4739, 2956, 5111, 935, 2704, 4654, 5107, 5103, 5105, 4913, - 1182, 4302, 2940, 1183, 1175, 3534, 3533, 2139, 1569, 2780, - 3287, 2158, 4243, 2785, 5118, 5117, 4244, 5119, 1613, 954, - 2782, 2794, 3509, 5136, 4435, 3771, 90, 89, 88, 1865, - 271, 5127, 1863, 1003, 1578, 1577, 1587, 1588, 1589, 1590, - 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1579, 4930, 270, - 4802, 4592, 5073, 981, 980, 979, 978, 977, 976, 2431, - 2803, 2430, 2432, 2429, 2427, 2426, 1810, 1809, 2810, 4186, - 5144, 4488, 5157, 3176, 3177, 5158, 2121, 5159, 3668, 5160, - 4408, 3663, 2466, 2463, 5162, 5161, 1832, 2464, 1863, 3031, - 5178, 3061, 5180, 5181, 5170, 2462, 5176, 1409, 2831, 5149, - 5174, 4226, 4513, 2836, 2837, 2838, 5051, 5052, 2841, 2842, - 2843, 2844, 2845, 2846, 2847, 2848, 2513, 2850, 2851, 4709, - 2853, 2854, 5189, 5191, 5190, 3714, 4509, 2801, 2396, 5195, - 1578, 1577, 1587, 1588, 1589, 1590, 1580, 1581, 1582, 1583, - 1584, 1585, 1586, 1579, 3909, 3056, 2483, 5203, 5204, 5202, - 5223, 5211, 5207, 2250, 2515, 3684, 2480, 5230, 5209, 2479, - 3676, 4705, 5215, 5216, 5217, 5218, 4699, 2512, 4996, 5248, - 5219, 5122, 5251, 5124, 4617, 1409, 4616, 5246, 5246, 5246, - 1409, 5243, 5120, 5250, 5253, 5234, 5237, 4615, 5096, 4386, - 3624, 4614, 5222, 5241, 4604, 5254, 5242, 4416, 4417, 4424, - 4900, 5039, 5261, 5260, 1352, 2948, 5267, 5273, 1321, 1316, - 2490, 1318, 1319, 1317, 3301, 4167, 912, 914, 913, 3037, - 172, 172, 172, 1261, 4026, 3431, 3430, 3428, 919, 3427, - 1764, 5280, 806, 4980, 5112, 4573, 5291, 3438, 5291, 3436, - 923, 1446, 2041, 2037, 1437, 5293, 1391, 938, 2971, 4741, - 3955, 1730, 1728, 3599, 916, 2993, 2250, 2583, 3776, 1811, - 5230, 1808, 4073, 5246, 5304, 1807, 5246, 5304, 5301, 5246, - 5304, 5250, 5308, 5307, 5253, 5306, 5309, 5302, 1290, 1289, - 2588, 5273, 5317, 1263, 239, 1880, 240, 171, 1122, 4277, - 4342, 2506, 5321, 5322, 3755, 5313, 5298, 5315, 3129, 3228, - 3618, 4816, 2401, 1176, 2938, 126, 48, 2121, 5330, 144, - 125, 1818, 1819, 218, 1821, 69, 217, 1825, 68, 1829, - 1830, 1831, 20, 142, 216, 67, 53, 52, 214, 5329, - 121, 5331, 120, 119, 118, 141, 213, 66, 255, 254, - 257, 1396, 256, 253, 3187, 3188, 252, 1922, 251, 5088, - 4612, 1206, 5164, 51, 50, 219, 1404, 49, 127, 70, - 1893, 1894, 47, 1602, 1897, 1898, 1899, 1900, 1901, 46, - 1903, 1904, 1905, 2318, 1907, 2318, 1910, 2688, 1912, 1913, - 1914, 3975, 1439, 1441, 2048, 4297, 3423, 2922, 45, 40, - 2494, 14, 12, 43, 2318, 2318, 41, 25, 24, 2014, - 23, 2500, 31, 30, 13, 39, 4842, 37, 36, 918, - 922, 928, 163, 929, 931, 162, 35, 932, 933, 934, - 3868, 2488, 2522, 936, 937, 2489, 2491, 2493, 161, 2495, - 2496, 2497, 2501, 2502, 2503, 2505, 2508, 2509, 2510, 160, - 159, 1918, 4871, 4872, 158, 157, 2498, 2507, 2499, 4876, - 4877, 4878, 4879, 4880, 4881, 156, 155, 34, 4885, 4886, - 4887, 4888, 4889, 4890, 22, 61, 60, 59, 58, 4893, - 4894, 4895, 57, 56, 1578, 1577, 1587, 1588, 1589, 1590, - 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1579, 2775, 8, - 4370, 148, 1562, 3233, 147, 3236, 149, 145, 140, 138, - 2514, 33, 139, 136, 137, 130, 129, 128, 122, 102, - 101, 100, 1578, 1577, 1587, 1588, 1589, 1590, 1580, 1581, - 1582, 1583, 1584, 1585, 1586, 1579, 1125, 115, 114, 4922, - 113, 112, 111, 110, 1710, 108, 109, 864, 3258, 3259, - 99, 5193, 1578, 1577, 1587, 1588, 1589, 1590, 1580, 1581, - 1582, 1583, 1584, 1585, 1586, 1579, 98, 97, 96, 95, - 135, 134, 131, 117, 124, 123, 106, 116, 107, 105, - 2511, 104, 103, 94, 93, 92, 133, 132, 146, 915, - 220, 71, 197, 196, 195, 194, 193, 191, 2486, 192, - 190, 189, 2485, 188, 187, 186, 185, 62, 63, 64, - 65, 209, 208, 210, 222, 221, 212, 3296, 215, 211, - 3299, 206, 204, 207, 205, 203, 2504, 83, 1814, 2121, - 11, 143, 3319, 3320, 3764, 2492, 4992, 21, 18, 3, - 0, 3323, 3324, 0, 0, 2513, 0, 0, 0, 0, - 2473, 0, 0, 2521, 0, 0, 0, 3329, 3330, 3331, - 0, 0, 0, 0, 0, 0, 1874, 0, 0, 1883, - 0, 0, 1345, 0, 0, 0, 806, 0, 0, 0, - 0, 0, 0, 2515, 2482, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2516, 2517, 3367, 0, 3369, 0, - 0, 3372, 0, 2128, 0, 0, 2318, 5048, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, - 2481, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2490, - 0, 0, 0, 2513, 0, 0, 0, 0, 2473, 0, - 0, 2521, 0, 0, 0, 0, 0, 1206, 1206, 1798, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1820, 0, 0, 0, 0, - 0, 2515, 2482, 0, 1834, 0, 0, 0, 0, 0, - 0, 0, 2516, 2517, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1871, 0, 0, 0, 1363, - 1364, 1325, 0, 0, 0, 0, 0, 0, 2481, 0, - 2506, 0, 0, 0, 0, 0, 0, 172, 0, 0, - 172, 172, 1353, 1357, 1359, 1361, 1366, 2490, 1371, 1367, - 1368, 1369, 1370, 0, 172, 1348, 1349, 1350, 1351, 1323, - 1324, 1354, 0, 1326, 0, 1327, 1329, 1330, 1331, 1332, - 1328, 1333, 1334, 1335, 1336, 1337, 1344, 1346, 1338, 1339, - 1340, 1341, 1342, 1343, 1372, 1373, 1374, 1375, 1376, 1377, - 1378, 1379, 1381, 1380, 1382, 1383, 1384, 1385, 1386, 1387, - 1388, 1389, 1356, 1358, 1360, 1362, 1365, 0, 0, 2487, - 0, 0, 0, 0, 0, 0, 0, 0, 2468, 2474, - 2472, 0, 0, 0, 2469, 0, 0, 0, 2506, 2494, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2500, 0, 0, 1347, 0, 0, 0, 0, 2484, 0, - 2467, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2488, 2522, 0, 0, 2489, 2491, 2493, 0, 2495, 2496, - 2497, 2501, 2502, 2503, 2505, 2508, 2509, 2510, 0, 2318, - 0, 0, 0, 0, 0, 2498, 2507, 2499, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2476, 0, 2585, - 0, 0, 0, 0, 0, 0, 0, 2599, 2600, 2513, - 0, 0, 0, 0, 2606, 0, 3632, 3633, 2472, 0, - 0, 0, 3631, 2613, 0, 0, 0, 2494, 0, 0, - 0, 0, 0, 3789, 0, 3791, 0, 0, 2500, 2514, - 0, 0, 0, 0, 0, 1602, 0, 2515, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2488, 2522, - 1918, 0, 2489, 2491, 2493, 0, 2495, 2496, 2497, 2501, - 2502, 2503, 2505, 2508, 2509, 2510, 0, 0, 0, 0, - 0, 0, 0, 2498, 2507, 2499, 0, 0, 0, 0, - 0, 2470, 2471, 0, 0, 2476, 0, 0, 0, 2665, - 0, 0, 0, 2490, 0, 0, 0, 0, 0, 2511, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2486, 0, 0, - 0, 2485, 0, 0, 0, 0, 0, 2514, 0, 0, - 3849, 0, 200, 245, 199, 232, 201, 0, 0, 0, + 987, 5311, 5284, 962, 5276, 5249, 5318, 989, 5256, 5253, + 263, 5232, 5299, 5266, 3649, 5248, 5150, 5144, 4905, 3766, + 2124, 4394, 1979, 1978, 972, 5095, 4504, 3911, 5155, 5154, + 4113, 4903, 5143, 5045, 3166, 4094, 4438, 5084, 3961, 4202, + 4933, 3425, 4727, 4807, 4762, 3220, 1865, 3638, 3963, 4499, + 1645, 4902, 1490, 4950, 4859, 4203, 778, 4991, 4597, 3545, + 5096, 4906, 3421, 4318, 4200, 2199, 5098, 1882, 1018, 3641, + 4641, 4837, 4512, 1497, 800, 1253, 4326, 3803, 4404, 4332, + 1461, 1919, 3045, 4422, 3343, 2186, 817, 827, 3369, 837, + 4626, 4119, 837, 4375, 1881, 1409, 3591, 4604, 2072, 3344, + 250, 5, 3557, 4031, 4278, 3423, 4610, 964, 4580, 4013, + 2127, 2426, 4183, 1262, 3213, 3767, 2571, 1444, 170, 4017, + 2574, 1260, 2963, 4316, 3735, 3546, 3668, 3547, 3337, 248, + 3765, 4121, 2456, 4109, 3627, 1883, 4129, 4353, 914, 3254, + 2449, 3762, 3621, 3441, 4153, 2623, 3625, 2182, 3433, 3619, + 2737, 4270, 2205, 3524, 3995, 905, 1984, 3993, 1858, 3753, + 3982, 4032, 3034, 3161, 4128, 4034, 4033, 954, 2984, 1989, + 2972, 4044, 2077, 2320, 1793, 2969, 3539, 2964, 2183, 4029, + 3943, 909, 2890, 2889, 1170, 1268, 77, 1971, 1895, 3439, + 955, 1967, 2733, 959, 2780, 77, 2628, 3193, 1710, 237, + 817, 1214, 3253, 2588, 2567, 3172, 3512, 3506, 3136, 2732, + 3046, 3654, 1952, 2450, 3049, 2469, 3560, 2458, 2457, 44, + 3018, 3595, 1962, 2983, 2961, 4, 3594, 2967, 889, 3670, + 259, 7, 258, 6, 778, 1791, 2946, 2200, 1326, 2123, + 1805, 2389, 2119, 2734, 38, 1992, 963, 817, 2974, 16, + 2971, 1920, 1874, 799, 1837, 2432, 1843, 1500, 2193, 2416, + 2937, 2940, 953, 263, 2110, 263, 2892, 1316, 1317, 1442, + 2645, 1425, 834, 1244, 2776, 817, 2161, 32, 2076, 1927, + 2380, 902, 1810, 17, 2118, 1269, 1246, 1447, 821, 2388, + 1501, 1213, 960, 15, 973, 2384, 1479, 1839, 1794, 1736, + 955, 26, 1842, 1131, 2206, 1798, 833, 912, 1134, 1135, + 2410, 5233, 911, 249, 818, 1295, 244, 1206, 3137, 86, + 54, 243, 1475, 1133, 1193, 236, 42, 836, 1136, 29, + 1211, 829, 1247, 87, 1792, 908, 831, 27, 1646, 874, + 78, 2712, 153, 4976, 2461, 961, 81, 4833, 5, 28, + 80, 76, 19, 1313, 1128, 10, 2348, 1264, 1130, 1569, + 4216, 1570, 1568, 1569, 832, 1570, 1568, 3393, 3393, 1569, + 828, 1570, 1568, 1761, 3393, 4373, 3953, 3952, 3818, 3817, + 830, 2749, 1737, 4560, 4335, 1411, 4195, 3286, 777, 3196, + 3199, 3197, 1312, 3194, 1314, 4069, 1410, 1738, 2337, 1930, + 1308, 1309, 247, 809, 3370, 1934, 4754, 4078, 3338, 2853, + 4376, 2962, 3221, 802, 2888, 3212, 1731, 1841, 807, 841, + 803, 1457, 1458, 1459, 804, 5073, 1688, 1456, 805, 806, + 1410, 1993, 2701, 77, 2702, 4221, 2697, 1899, 1266, 1349, + 1820, 1765, 4351, 3167, 2201, 4544, 3954, 3950, 77, 1309, + 77, 1157, 2903, 2670, 2895, 2344, 2437, 2441, 2442, 2443, + 2438, 2448, 2439, 2445, 1128, 1309, 2440, 1740, 2446, 1154, + 3929, 3926, 5244, 1307, 2671, 1517, 9, 1596, 7, 1602, + 6, 1455, 2331, 2884, 3936, 3934, 1719, 4497, 3798, 3796, + 1569, 3927, 1570, 1568, 1127, 1599, 1601, 1595, 2633, 1600, + 1582, 1581, 1591, 1592, 1593, 1594, 1584, 1585, 1586, 1587, + 1588, 1589, 1590, 1583, 5003, 4719, 1597, 1932, 5152, 5151, + 4209, 1569, 4945, 1570, 1568, 4770, 4763, 4500, 1349, 3938, + 4201, 1073, 2800, 1640, 5101, 2966, 1132, 2328, 2437, 2441, + 2442, 2443, 2438, 2448, 2439, 2445, 1259, 3138, 2440, 3889, + 2446, 3924, 3593, 3116, 3980, 2652, 2690, 3081, 5281, 2241, + 1257, 4959, 5240, 4779, 2051, 1258, 1261, 4956, 1145, 4549, + 4819, 2184, 2185, 4307, 3318, 2910, 1367, 1368, 1329, 5057, + 1896, 1746, 1448, 4547, 1744, 2437, 2441, 2442, 2443, 2438, + 2448, 2439, 2445, 4776, 1743, 2440, 4302, 2446, 3983, 1357, + 1361, 1363, 1365, 1370, 1127, 1375, 1371, 1372, 1373, 1374, + 2530, 2927, 1352, 1353, 1354, 1355, 1327, 1328, 1358, 1158, + 1330, 1155, 1331, 1333, 1334, 1335, 1336, 1332, 1337, 1338, + 1339, 1340, 1341, 1348, 1350, 1342, 1343, 1344, 1345, 1346, + 1347, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1385, + 1384, 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1360, + 1362, 1364, 1366, 1369, 1998, 1367, 1368, 1329, 3884, 1271, + 1787, 1318, 2437, 2441, 2442, 2443, 2438, 2448, 2439, 2445, + 1146, 1158, 2440, 1453, 2446, 1454, 1349, 2429, 1357, 1361, + 1363, 1365, 1370, 3928, 1375, 1371, 1372, 1373, 1374, 1155, + 1351, 1352, 1353, 1354, 1355, 1327, 1328, 1358, 2747, 1330, + 3760, 1331, 1333, 1334, 1335, 1336, 1332, 1337, 1338, 1339, + 1340, 1341, 1348, 1350, 1342, 1343, 1344, 1345, 1346, 1347, + 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1385, 1384, + 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1360, 1362, + 1364, 1366, 1369, 3925, 1947, 2069, 2437, 2441, 2442, 2443, + 2438, 2448, 2439, 2445, 2941, 907, 2440, 3939, 2446, 200, + 245, 199, 232, 201, 1118, 2357, 1117, 1119, 1120, 2355, + 1121, 1122, 3420, 4821, 1933, 1931, 3157, 1565, 3144, 1351, + 943, 3143, 3073, 945, 3145, 3802, 3772, 3773, 944, 2551, + 2552, 1545, 817, 1156, 1546, 2362, 2363, 3158, 1844, 1753, + 1846, 1513, 817, 1996, 1514, 3771, 2550, 817, 2584, 1413, + 1452, 1153, 3122, 1367, 1368, 1329, 3121, 943, 1487, 3960, + 945, 2048, 1548, 3214, 1995, 944, 826, 3265, 3264, 837, + 837, 1439, 898, 817, 817, 825, 1357, 1361, 1363, 1365, + 1370, 4098, 1375, 1371, 1372, 1373, 1374, 3418, 3508, 1352, + 1353, 1354, 1355, 1327, 1328, 1358, 4096, 1330, 3509, 1331, + 1333, 1334, 1335, 1336, 1332, 1337, 1338, 1339, 1340, 1341, + 1348, 1350, 1342, 1343, 1344, 1345, 1346, 1347, 1376, 1377, + 1378, 1379, 1380, 1381, 1382, 1383, 1385, 1384, 1386, 1387, + 1388, 1389, 1390, 1391, 1392, 1393, 1360, 1362, 1364, 1366, + 1369, 2067, 1498, 1499, 5105, 1516, 1496, 4778, 3507, 2347, + 1495, 1498, 1499, 4551, 1403, 1730, 1494, 3937, 2126, 2444, + 1152, 1558, 1404, 3005, 1464, 2442, 2443, 2092, 3417, 1491, + 3416, 1491, 1473, 1563, 1264, 4787, 1405, 1351, 1256, 1483, + 5158, 5159, 4975, 817, 1255, 1319, 4832, 1543, 1503, 1504, + 5104, 1506, 1507, 5086, 5103, 1509, 5102, 1596, 2860, 1602, + 5105, 5192, 1615, 5104, 5191, 4948, 4228, 3847, 5103, 5190, + 5186, 1827, 2046, 3392, 1411, 1599, 1601, 1595, 1608, 1600, + 1582, 1581, 1591, 1592, 1593, 1594, 1584, 1585, 1586, 1587, + 1588, 1589, 1590, 1583, 1411, 1411, 1597, 3804, 834, 834, + 834, 2444, 5117, 2672, 2748, 3413, 4548, 5102, 5189, 5089, + 1413, 5235, 5236, 1544, 4766, 1266, 4204, 3819, 823, 824, + 5086, 3816, 4204, 246, 1359, 2711, 3805, 2785, 3806, 1411, + 3243, 1309, 833, 833, 833, 1309, 1309, 1309, 1900, 1821, + 3115, 1766, 3118, 1414, 1309, 1309, 4639, 4623, 2444, 2068, + 3809, 2751, 1485, 3117, 2568, 2528, 4987, 829, 829, 829, + 2750, 2130, 831, 831, 831, 4951, 4952, 4953, 4954, 2358, + 4225, 4317, 2111, 2356, 1264, 2115, 3419, 2743, 1525, 3195, + 4324, 1428, 1431, 4937, 3754, 2130, 3414, 3221, 1830, 2558, + 832, 832, 832, 4009, 4589, 1547, 828, 828, 828, 2114, + 2106, 1416, 1418, 1421, 3843, 1515, 830, 830, 830, 1259, + 1935, 3124, 1738, 1359, 2582, 2583, 2935, 1649, 1433, 1406, + 5286, 4786, 3689, 1402, 5312, 5313, 5350, 1598, 1258, 4788, + 814, 2658, 5345, 4777, 3935, 2444, 1132, 3430, 1738, 1733, + 1735, 3515, 1739, 5157, 4451, 1476, 1480, 1480, 1480, 5119, + 809, 2447, 1432, 1481, 1482, 1266, 1437, 1438, 1757, 3841, + 4081, 3386, 1760, 1449, 1560, 807, 3278, 803, 1324, 1769, + 3079, 804, 1476, 1476, 5283, 805, 806, 4550, 229, 1149, + 1533, 1556, 1557, 4498, 4351, 3797, 3131, 3748, 2529, 3126, + 4007, 4998, 1561, 1562, 4545, 4999, 5002, 5001, 817, 817, + 817, 1522, 4829, 1214, 1518, 1519, 1502, 1538, 4586, 1505, + 1540, 1819, 4823, 4824, 3127, 3128, 817, 1772, 1826, 2444, + 2046, 1832, 4003, 4015, 4014, 817, 2129, 2128, 2116, 778, + 778, 3395, 1524, 2447, 3415, 3134, 1555, 1708, 1541, 778, + 778, 1770, 1705, 1869, 1869, 1709, 817, 798, 4004, 4005, + 2129, 2128, 2113, 1412, 1150, 4413, 4879, 1324, 2042, 1616, + 4409, 1712, 4319, 2685, 4006, 1508, 4111, 4112, 835, 1511, + 1512, 1359, 4110, 1915, 1745, 4100, 837, 1742, 800, 1550, + 2447, 4979, 1551, 4045, 1923, 4810, 4614, 4822, 4561, 4341, + 1871, 4102, 4189, 4103, 4105, 4104, 4028, 3511, 1498, 1499, + 263, 3037, 1610, 1611, 1612, 1613, 1614, 3036, 3039, 778, + 1553, 5015, 4866, 1498, 1499, 5005, 4849, 1465, 3561, 4282, + 4284, 5285, 2948, 4106, 1486, 1430, 1429, 1159, 839, 200, + 245, 199, 232, 201, 79, 1151, 4553, 4554, 4555, 2047, + 838, 1867, 1867, 4457, 3758, 2943, 3944, 200, 245, 199, + 232, 201, 1997, 4001, 4395, 4992, 1752, 1828, 5017, 1661, + 1662, 5046, 4095, 1534, 3643, 3038, 4402, 2447, 2922, 1876, + 946, 947, 948, 949, 950, 1474, 2112, 4816, 1892, 1893, + 4015, 5286, 4569, 4293, 1748, 1975, 2136, 2140, 2141, 1536, + 1980, 1134, 3973, 1831, 1771, 5099, 2444, 2137, 3114, 1863, + 1864, 1994, 1539, 1542, 4967, 238, 4968, 946, 947, 948, + 949, 950, 1716, 4296, 1420, 1324, 4115, 4415, 200, 245, + 199, 232, 201, 238, 1750, 2017, 4986, 1259, 1809, 1535, + 4414, 1741, 3033, 4715, 2020, 1549, 2138, 2759, 2761, 2762, + 2049, 1703, 5306, 1715, 1704, 1202, 1258, 1203, 1713, 3639, + 3640, 2447, 3643, 3556, 1650, 4116, 3092, 3037, 3091, 4515, + 1869, 3052, 1987, 3036, 3039, 1435, 1832, 1472, 2569, 3112, + 3113, 827, 3521, 4379, 3755, 1554, 2062, 4015, 2755, 2757, + 2758, 4295, 1854, 1148, 4010, 77, 5047, 1471, 1853, 2046, + 1523, 1470, 2091, 2050, 238, 1774, 3844, 5118, 5142, 1832, + 4838, 1552, 4867, 4969, 2100, 2100, 4850, 1832, 1491, 1832, + 1832, 1537, 4354, 2043, 1983, 1800, 1801, 2562, 1489, 1488, + 1869, 3038, 1869, 1413, 2054, 2057, 2058, 2061, 1942, 1985, + 1797, 1912, 3514, 1804, 1880, 4120, 5269, 1763, 1764, 1852, + 1953, 1767, 2074, 2075, 4590, 1775, 1777, 1778, 1779, 1780, + 4704, 1782, 1973, 4101, 1970, 1786, 4908, 1974, 1966, 2084, + 2085, 1848, 1850, 2559, 4249, 1879, 1964, 1965, 1886, 2095, + 1877, 1861, 1862, 1885, 2107, 943, 3036, 3130, 945, 1990, + 4710, 2097, 5285, 944, 809, 1261, 1894, 3690, 1423, 3691, + 3692, 3518, 3519, 246, 1988, 834, 1869, 3388, 834, 834, + 1924, 3082, 1799, 1910, 4825, 4495, 3517, 1762, 4111, 4112, + 5083, 246, 834, 1925, 1413, 2203, 4002, 1598, 4728, 4729, + 4730, 4734, 4732, 4733, 4735, 4736, 4737, 4738, 4731, 833, + 3051, 2254, 833, 833, 1747, 3053, 2272, 2274, 2273, 4114, + 1608, 1936, 2743, 2235, 2236, 4362, 2034, 2240, 2244, 2245, + 2246, 3173, 3174, 1776, 829, 2255, 907, 829, 829, 831, + 1840, 2260, 831, 831, 2261, 4279, 1773, 1781, 2262, 2947, + 2264, 2096, 2265, 2266, 2267, 4157, 2025, 2040, 4137, 2103, + 3274, 1603, 246, 2139, 3558, 2282, 2283, 832, 2923, 3054, + 832, 832, 5270, 828, 2187, 1530, 828, 828, 2003, 2070, + 3719, 2006, 2007, 830, 2029, 3149, 830, 830, 5141, 2002, + 2026, 4473, 2005, 3120, 2122, 2315, 3062, 4907, 3077, 1413, + 2024, 2893, 2740, 2557, 2271, 1605, 1604, 2078, 2545, 2080, + 2081, 2349, 1134, 1201, 2760, 2352, 1264, 1749, 1751, 1981, + 817, 817, 817, 1759, 2088, 4172, 2035, 2033, 899, 2367, + 2369, 1476, 2370, 2031, 2373, 2374, 2032, 2142, 2377, 2120, + 2023, 800, 2381, 4159, 2028, 1480, 2385, 2326, 1869, 2391, + 2392, 2083, 2394, 1832, 2238, 2756, 2022, 817, 1480, 2027, + 1869, 3055, 2021, 2073, 2089, 2079, 817, 2104, 2105, 3402, + 2318, 4962, 3020, 3022, 1214, 5097, 4024, 2427, 2064, 2065, + 1529, 200, 245, 3846, 1906, 2452, 2452, 1819, 2452, 1785, + 1784, 2462, 2463, 817, 817, 2316, 2527, 1266, 2321, 1783, + 2385, 2538, 2099, 2101, 1869, 2542, 2543, 801, 2121, 1234, + 1819, 2117, 778, 1422, 2325, 4706, 843, 842, 835, 4705, + 4310, 5267, 5268, 4107, 901, 2340, 778, 900, 1869, 4711, + 4712, 1419, 3553, 245, 3742, 2324, 835, 2327, 2777, 2752, + 2753, 200, 245, 1188, 2147, 2148, 2149, 2150, 2151, 2152, + 2153, 2154, 2155, 2156, 2157, 2158, 2479, 238, 4271, 2102, + 2163, 2534, 2532, 4718, 2179, 2180, 2533, 1215, 2600, 2602, + 200, 245, 817, 2385, 1869, 3687, 2609, 245, 817, 905, + 905, 2329, 2381, 1270, 79, 2616, 3241, 2618, 2619, 2620, + 2204, 4363, 1164, 2624, 812, 2239, 813, 1808, 1762, 3410, + 263, 2481, 79, 263, 263, 1264, 263, 835, 238, 2159, + 2160, 1217, 1218, 1219, 2914, 2177, 2178, 238, 2263, 2181, + 899, 4211, 2253, 1756, 3056, 2395, 2454, 1888, 2460, 4215, + 2365, 2536, 2393, 4025, 1950, 1969, 2409, 1951, 2268, 2269, + 3061, 2585, 2547, 2366, 3059, 1171, 238, 2125, 2916, 2915, + 2577, 2578, 238, 1754, 1755, 4286, 1168, 2590, 2591, 3710, + 3711, 1166, 1165, 2913, 2660, 3720, 3722, 3723, 3724, 3721, + 2678, 2561, 2345, 79, 2364, 3021, 2014, 2554, 1160, 2556, + 2319, 2408, 2339, 1162, 1259, 3104, 1266, 2390, 2418, 2605, + 2575, 2576, 2011, 2012, 2379, 2611, 1161, 4627, 2317, 2404, + 3436, 778, 2338, 1258, 2342, 1569, 2563, 1570, 1568, 2346, + 4936, 200, 245, 817, 1462, 2427, 901, 817, 1463, 900, + 2570, 200, 245, 5308, 2694, 5355, 2696, 2546, 3403, 2632, + 2700, 2420, 2635, 2636, 2739, 2638, 3437, 3438, 2705, 2706, + 2707, 4214, 2710, 2541, 1832, 246, 2621, 2586, 2656, 1795, + 3251, 1968, 1945, 1167, 1948, 1949, 2608, 200, 245, 4108, + 2673, 2411, 2417, 4179, 3881, 2424, 2411, 1954, 1955, 1956, + 1957, 1958, 1959, 1832, 5093, 2428, 2422, 2423, 2415, 2821, + 1869, 2736, 889, 2820, 2341, 77, 1281, 2419, 77, 77, + 2642, 77, 5354, 2540, 5344, 2535, 246, 238, 2016, 5342, + 1235, 3709, 1232, 4178, 1466, 246, 5071, 2015, 4055, 2375, + 2376, 1567, 2564, 2120, 4965, 2662, 2382, 2383, 2622, 1164, + 2553, 1263, 2555, 4967, 1567, 4968, 2688, 2396, 2397, 2398, + 2649, 1466, 1263, 238, 246, 1139, 1140, 1141, 1142, 2722, + 246, 4961, 3568, 2333, 2548, 946, 947, 948, 949, 950, + 2594, 1466, 2108, 1467, 2657, 2599, 2661, 2764, 2607, 2725, + 2612, 2613, 2614, 2046, 834, 2727, 1169, 2729, 2606, 1567, + 3139, 2704, 5329, 1567, 4068, 5348, 2629, 5325, 1567, 2665, + 1567, 2595, 4174, 1163, 5296, 1567, 2593, 1530, 1166, 1165, + 1986, 834, 4379, 200, 245, 2877, 2275, 1530, 833, 2278, + 2279, 2280, 2647, 2939, 2284, 2285, 2286, 2287, 2289, 2290, + 2291, 2292, 2293, 2294, 2295, 2296, 2298, 2299, 2300, 2301, + 2302, 5293, 4969, 829, 4344, 833, 200, 245, 831, 200, + 245, 199, 232, 201, 3528, 3534, 3535, 3536, 3529, 3533, + 3530, 3532, 3531, 1528, 1270, 2730, 2667, 5290, 4267, 899, + 829, 2682, 5288, 1264, 5278, 831, 832, 1569, 5326, 1570, + 1568, 4179, 828, 5326, 3590, 4227, 5263, 2681, 2831, 238, + 5297, 2834, 830, 2836, 2684, 246, 2680, 2664, 1225, 1223, + 2843, 1224, 2687, 832, 5224, 246, 5209, 1706, 3013, 828, + 200, 245, 2226, 2856, 5172, 3551, 1417, 3076, 1567, 830, + 3052, 3055, 2666, 3013, 1143, 238, 1527, 5294, 4179, 1228, + 2894, 2716, 2896, 3013, 2898, 2899, 3880, 2723, 2902, 3589, + 2724, 246, 2713, 2739, 5171, 2622, 817, 1832, 817, 1832, + 2794, 2109, 5170, 5291, 1266, 3273, 2938, 4140, 2745, 2917, + 5279, 3553, 4138, 2731, 4089, 901, 2924, 2925, 900, 954, + 2783, 2720, 5210, 817, 817, 2742, 1480, 5160, 2936, 5138, + 2739, 1569, 2726, 1570, 1568, 5137, 3544, 817, 817, 817, + 5225, 4086, 5210, 2859, 2861, 2862, 2863, 3989, 2865, 3986, + 5173, 2875, 1233, 3942, 2797, 200, 245, 199, 232, 201, + 2970, 2970, 2976, 3574, 3052, 3055, 3389, 1528, 3919, 2985, + 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 2763, 2876, + 1567, 3916, 2765, 1855, 3218, 2738, 3548, 2770, 1567, 3160, + 2793, 2787, 2452, 2778, 1706, 1569, 5068, 1570, 1568, 2549, + 2163, 2768, 2769, 3031, 1229, 2163, 2773, 2774, 1569, 5018, + 1570, 1568, 2887, 2795, 1569, 5139, 1570, 1568, 2874, 3068, + 2873, 2745, 2004, 200, 245, 3023, 2882, 246, 2830, 2829, + 5009, 238, 2828, 1569, 3056, 1570, 1568, 4923, 2686, 3051, + 3036, 3050, 2580, 3047, 3053, 2544, 1569, 3590, 1570, 1568, + 1803, 2190, 2766, 2767, 3920, 3040, 3273, 2771, 2772, 1530, + 246, 2868, 4922, 246, 2879, 2880, 4585, 3917, 4921, 2907, + 1231, 2909, 4920, 2719, 1270, 1303, 1304, 1305, 1264, 4919, + 4962, 4870, 2795, 4869, 4963, 817, 2100, 4835, 1569, 2222, + 1570, 1568, 3365, 2738, 4379, 2745, 2219, 3075, 3054, 238, + 2221, 2218, 2220, 2224, 2225, 2872, 778, 778, 2223, 5327, + 1302, 4804, 4927, 1299, 1413, 1569, 1567, 1570, 1568, 4748, + 1869, 817, 4323, 2795, 246, 4373, 4366, 3877, 3056, 3554, + 3788, 1134, 3592, 3051, 3036, 3050, 2973, 3047, 3053, 3573, + 3398, 3276, 2049, 4801, 3168, 3169, 4746, 2869, 2795, 2897, + 4646, 817, 1230, 2901, 2795, 3275, 800, 4466, 2795, 1266, + 3242, 2931, 2816, 1923, 2866, 2795, 3184, 2745, 3186, 2745, + 2954, 263, 2641, 2795, 2791, 2959, 3042, 3057, 3058, 3044, + 3043, 2928, 2418, 2418, 3048, 4645, 2799, 2986, 2955, 4571, + 4570, 1569, 3054, 1570, 1568, 3179, 1227, 1567, 1139, 1140, + 1141, 1142, 4468, 4416, 4389, 3012, 4386, 2970, 2970, 3227, + 3119, 3146, 3550, 3147, 2728, 2683, 3238, 1137, 3155, 246, + 2627, 1649, 2977, 2978, 3244, 1139, 1140, 1141, 1142, 2981, + 3011, 2343, 3152, 3153, 4360, 2579, 4647, 4260, 3249, 1999, + 4256, 3006, 3252, 3255, 1137, 4148, 3030, 3140, 3257, 1583, + 2867, 4050, 1869, 2987, 2988, 2989, 2990, 2991, 2992, 2993, + 2229, 2230, 2231, 2232, 2233, 2234, 2227, 2228, 3171, 3270, + 2371, 2981, 2736, 3868, 3814, 4089, 4086, 1624, 3048, 1869, + 1434, 1869, 1428, 1431, 3812, 1399, 1413, 246, 2046, 4417, + 4089, 4073, 4086, 3578, 3287, 1394, 2782, 2781, 3576, 3570, + 3189, 1296, 1297, 1298, 1301, 3838, 1300, 1226, 835, 2372, + 1891, 3363, 1221, 3350, 3342, 5006, 3288, 3248, 3246, 1222, + 1567, 3250, 2087, 4261, 3159, 1264, 4257, 3222, 4490, 2063, + 3194, 4149, 1940, 1939, 3260, 1869, 1413, 3571, 1462, 3135, + 3321, 3129, 1463, 3209, 3267, 3268, 3141, 1605, 1604, 5309, + 3259, 2082, 2630, 1432, 3216, 4193, 77, 3330, 3219, 1567, + 3577, 5007, 1869, 3322, 3207, 5298, 3271, 1143, 2090, 3205, + 3571, 2093, 2094, 3156, 79, 3203, 990, 1000, 5295, 3579, + 3014, 3316, 956, 2973, 3577, 3571, 991, 1477, 992, 996, + 999, 995, 993, 994, 1143, 3215, 1859, 1567, 2980, 1567, + 1567, 3366, 1567, 4519, 2981, 2878, 1266, 1860, 3331, 3176, + 3789, 834, 3299, 5292, 3183, 1582, 1581, 1591, 1592, 1593, + 1594, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1583, 3210, + 2839, 3258, 1603, 1867, 3223, 3555, 3396, 4628, 1848, 1850, + 5239, 3400, 2838, 2819, 3404, 833, 2810, 2823, 2809, 2808, + 3208, 817, 817, 817, 997, 3204, 2796, 3226, 3225, 3236, + 1867, 3204, 2744, 3345, 835, 2008, 3013, 3852, 3074, 3351, + 829, 1413, 3503, 3245, 3284, 831, 1605, 1604, 3302, 1869, + 3304, 4977, 1832, 4629, 2981, 998, 4046, 4357, 1832, 2538, + 3279, 2877, 4896, 3336, 4895, 1603, 3340, 3372, 2970, 3374, + 3375, 3319, 3339, 832, 3368, 1857, 4355, 4834, 3346, 828, + 1478, 3382, 1510, 3297, 1416, 3272, 1567, 4851, 2120, 830, + 4774, 3277, 3585, 3588, 3269, 4708, 1430, 1429, 1567, 1567, + 79, 4518, 1567, 4358, 1567, 1567, 4707, 4691, 3383, 1605, + 1604, 4656, 2795, 4593, 2243, 2242, 3566, 4367, 2745, 4334, + 4180, 2009, 4356, 1462, 1819, 3829, 1819, 1463, 1650, 2243, + 2242, 4170, 4162, 3581, 3582, 3623, 3629, 4150, 4091, 4047, + 4088, 4019, 3306, 3317, 3644, 1413, 3384, 3385, 3646, 3647, + 3648, 3289, 3290, 1413, 3751, 2059, 3292, 3293, 3750, 3580, + 3575, 3658, 1569, 3540, 1570, 1568, 3526, 3394, 1413, 1413, + 1413, 2100, 3285, 4196, 1413, 3673, 3962, 3674, 3675, 4852, + 3676, 1856, 3678, 3151, 3381, 4048, 2900, 1462, 2676, 3543, + 5, 1463, 2675, 3673, 1584, 1585, 1586, 1587, 1588, 1589, + 1590, 1583, 2674, 2479, 1789, 3188, 2452, 1788, 3325, 1415, + 2194, 3965, 2788, 1310, 1311, 1928, 3428, 2630, 1315, 3443, + 3732, 3314, 3315, 5135, 3522, 4853, 3332, 1796, 3308, 2412, + 3541, 3295, 2288, 3296, 5134, 2055, 5011, 778, 2194, 1796, + 2409, 1569, 3562, 1570, 1568, 2538, 1795, 2281, 2481, 1413, + 1413, 4722, 3198, 3965, 2174, 1375, 1371, 1372, 1373, 1374, + 1869, 5188, 3313, 4860, 3312, 3311, 3309, 1570, 1568, 3769, + 2171, 2173, 2170, 4803, 2172, 77, 1462, 4802, 2060, 3552, + 1463, 817, 3307, 3504, 3505, 1568, 1413, 3737, 2390, 3785, + 3520, 3962, 4721, 1819, 4051, 3564, 3549, 3679, 3677, 3661, + 3282, 263, 3659, 5346, 3565, 5337, 263, 1586, 1587, 1588, + 1589, 1590, 1583, 3583, 3651, 3584, 3587, 2169, 3632, 5316, + 7, 4697, 6, 3600, 3601, 3598, 3599, 5037, 5038, 3663, + 1796, 3964, 1923, 2166, 2168, 2165, 3810, 2167, 5035, 5036, + 4696, 3855, 3610, 3611, 3230, 3615, 3616, 3617, 3612, 1569, + 3310, 1570, 1568, 3821, 3229, 3631, 1462, 3634, 2056, 5177, + 1463, 5212, 3255, 4900, 4901, 5136, 3653, 3770, 5130, 3743, + 3656, 4587, 3655, 3655, 3660, 4594, 4595, 3655, 1569, 3666, + 1570, 1568, 5041, 3377, 1869, 3378, 4376, 3840, 1569, 3080, + 1570, 1568, 3083, 3084, 3085, 3086, 3087, 3088, 3089, 3090, + 5305, 3756, 3093, 3094, 3095, 3096, 3097, 3098, 3099, 3100, + 3101, 3102, 3103, 3811, 3105, 3106, 3107, 3108, 3109, 3706, + 3110, 1569, 3693, 1570, 1568, 3787, 3778, 3162, 3163, 1569, + 3790, 1570, 1568, 4588, 1569, 3794, 1570, 1568, 4194, 5040, + 3824, 3746, 1928, 3827, 3828, 5039, 3752, 1581, 1591, 1592, + 1593, 1594, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1583, + 3834, 3329, 4321, 1626, 3443, 2258, 3777, 5304, 1569, 3774, + 1570, 1568, 3831, 3731, 3779, 3784, 1625, 3301, 3913, 5034, + 2259, 1569, 3807, 1570, 1568, 3444, 77, 3783, 5033, 2812, + 3190, 77, 2695, 3729, 5032, 2698, 2699, 5031, 3791, 2703, + 3792, 1569, 5030, 1570, 1568, 1569, 3948, 1570, 1568, 3951, + 2958, 3727, 2714, 2715, 3955, 5029, 817, 1832, 5027, 3932, + 5026, 3873, 2717, 2718, 4322, 3967, 3969, 3970, 3972, 5025, + 3974, 3975, 3885, 3657, 3887, 3730, 3890, 3891, 2803, 5024, + 3842, 3892, 3893, 3894, 3895, 3896, 1413, 3897, 3898, 3899, + 3900, 3901, 3902, 3903, 3904, 3728, 3906, 3907, 3908, 3909, + 1569, 2811, 1570, 1568, 3826, 1569, 3837, 1570, 1568, 3749, + 5023, 3716, 5022, 3726, 1929, 5020, 3836, 3870, 5019, 3914, + 3849, 5008, 3918, 2792, 3921, 3922, 3422, 4911, 1569, 3645, + 1570, 1568, 4873, 4854, 3867, 3850, 4828, 3652, 3851, 1591, + 1592, 1593, 1594, 1584, 1585, 1586, 1587, 1588, 1589, 1590, + 1583, 4800, 3652, 3664, 3665, 4764, 4717, 5147, 3669, 3863, + 3864, 3997, 3999, 1574, 1575, 1576, 1577, 1578, 1579, 1580, + 1572, 4631, 4012, 3715, 3860, 4630, 3862, 1569, 817, 1570, + 1568, 4396, 3869, 4359, 1569, 3861, 1570, 1568, 3930, 5054, + 4320, 1991, 3941, 4027, 4303, 1413, 4008, 4327, 3822, 817, + 3801, 817, 2538, 1569, 3525, 1570, 1568, 1413, 4795, 1569, + 1413, 1570, 1568, 3800, 3740, 4533, 1569, 3714, 1570, 1568, + 4531, 3713, 2970, 3945, 4059, 2970, 3946, 3712, 4062, 3958, + 4063, 3931, 4522, 3768, 3768, 1569, 4049, 1570, 1568, 3704, + 1819, 2985, 1569, 4072, 1570, 1568, 3698, 1569, 3697, 1570, + 1568, 4521, 3696, 3695, 3694, 4520, 4035, 3390, 3247, 1569, + 3211, 1570, 1568, 3148, 2886, 2691, 4023, 4461, 2651, 2650, + 3444, 3623, 4245, 3990, 2648, 2644, 2643, 3629, 1569, 4065, + 1570, 1568, 1569, 4016, 1570, 1568, 2597, 4026, 3068, 2354, + 4235, 2351, 2000, 4874, 1569, 3540, 1570, 1568, 1729, 1569, + 4333, 1570, 1568, 3994, 5287, 4126, 3233, 4126, 4130, 3235, + 4130, 4130, 5280, 1264, 3234, 1413, 1953, 1569, 1397, 1570, + 1568, 1973, 4000, 1970, 4826, 4827, 1974, 4505, 4141, 4117, + 2790, 5237, 3543, 1966, 5196, 5114, 1869, 1869, 5112, 3923, + 2321, 1964, 1965, 4808, 3882, 4058, 4061, 1582, 1581, 1591, + 1592, 1593, 1594, 1584, 1585, 1586, 1587, 1588, 1589, 1590, + 1583, 5081, 4989, 4097, 4099, 4022, 1569, 4598, 1570, 1568, + 4983, 1569, 4070, 1570, 1568, 3875, 4974, 4972, 3510, 1396, + 1073, 4955, 4142, 4143, 817, 4946, 4041, 1817, 5331, 4043, + 2409, 4910, 4040, 4054, 1266, 4060, 4052, 4057, 3997, 3874, + 2973, 4909, 1569, 3871, 1570, 1568, 4067, 4888, 3015, 4071, + 1569, 1832, 1570, 1568, 2538, 2538, 3552, 4887, 4878, 4877, + 4087, 4831, 4815, 4090, 4813, 4799, 1569, 3364, 1570, 1568, + 1569, 4765, 1570, 1568, 1867, 1867, 3362, 4701, 4700, 3321, + 4056, 4125, 3361, 4127, 4699, 4135, 4602, 4197, 3042, 4591, + 1571, 3044, 3043, 4092, 1569, 3359, 1570, 1568, 1607, 3358, + 1851, 4576, 4575, 1569, 5274, 1570, 1568, 4573, 1618, 1569, + 4566, 1570, 1568, 815, 4131, 4132, 4136, 3357, 4564, 4543, + 4542, 4124, 1569, 4139, 1570, 1568, 1569, 4541, 1570, 1568, + 4537, 4536, 4509, 3356, 1628, 4507, 4503, 817, 5272, 4501, + 4479, 4147, 3355, 4093, 1569, 4476, 1570, 1568, 4155, 3354, + 4470, 3736, 4315, 3353, 5049, 4305, 4288, 4233, 3685, 3686, + 1569, 3352, 1570, 1568, 4272, 4243, 4805, 4240, 4236, 1569, + 3987, 1570, 1568, 4210, 3702, 3703, 1569, 4168, 1570, 1568, + 1569, 4167, 1570, 1568, 3349, 4165, 4164, 4151, 1569, 4152, + 1570, 1568, 4161, 4146, 4160, 4175, 4176, 4218, 4163, 4145, + 4020, 4169, 4166, 3348, 3984, 3976, 3966, 3747, 3347, 3956, + 4207, 1569, 3949, 1570, 1568, 3947, 2891, 3848, 3845, 3341, + 3820, 3799, 3776, 4173, 3326, 3744, 4213, 1210, 3320, 5349, + 1569, 3741, 1570, 1568, 3738, 1569, 3725, 1570, 1568, 3717, + 3707, 4274, 3705, 3701, 3700, 4275, 1569, 2624, 1570, 1568, + 3699, 1569, 3604, 1570, 1568, 1569, 3298, 1570, 1568, 4289, + 2871, 4291, 3429, 3411, 3399, 4794, 4297, 3391, 3623, 3629, + 1717, 1073, 1072, 4793, 1306, 3228, 3217, 3177, 4224, 3652, + 1413, 2870, 2918, 1569, 2905, 1570, 1568, 1569, 2864, 1570, + 1568, 3652, 4285, 4229, 3652, 4250, 2904, 2754, 4252, 2655, + 2654, 4298, 815, 2646, 2387, 817, 2538, 4223, 1569, 4244, + 1570, 1568, 2353, 2350, 2336, 1569, 2833, 1570, 1568, 4342, + 2832, 4781, 4212, 2335, 4292, 4133, 4294, 2098, 2001, 1657, + 4348, 1653, 1652, 4264, 3261, 2189, 1401, 1147, 2243, 2242, + 3266, 4313, 4314, 1569, 4280, 1570, 1568, 1569, 4775, 1570, + 1568, 200, 245, 3858, 3859, 4574, 5262, 4540, 2452, 1819, + 4370, 4526, 1569, 5260, 1570, 1568, 4516, 2427, 4471, 245, + 199, 232, 201, 4381, 4364, 4352, 4350, 3623, 4265, 3255, + 3629, 5261, 4391, 4331, 4343, 4269, 4345, 4273, 5259, 5347, + 4155, 4268, 4277, 4378, 2297, 4266, 4263, 4262, 4259, 3652, + 4258, 245, 199, 232, 201, 4246, 4242, 4239, 4199, 4198, + 4188, 4418, 202, 4182, 1413, 4300, 4304, 4299, 4079, 4066, + 3988, 4340, 4328, 4311, 4126, 4308, 1922, 238, 1413, 1413, + 3985, 4465, 3940, 3878, 3865, 1869, 3857, 3856, 3854, 906, + 3618, 3206, 3202, 3201, 238, 5338, 3200, 4330, 3165, 3164, + 4474, 2844, 4349, 2837, 2956, 2827, 4309, 2826, 3443, 4372, + 2825, 2824, 2822, 817, 2818, 2538, 2817, 2815, 4365, 1819, + 1413, 2806, 4405, 4406, 4407, 4408, 238, 245, 4377, 2957, + 4491, 4467, 2802, 2801, 2721, 263, 2653, 2308, 2306, 2305, + 2304, 4369, 1949, 2303, 2257, 2256, 2247, 4452, 4368, 1890, + 5303, 3552, 3552, 1954, 1955, 1956, 1957, 1958, 1959, 5301, + 3650, 5273, 4511, 5202, 4388, 5201, 5200, 4487, 4387, 4385, + 4393, 4445, 5176, 5169, 5167, 5074, 5053, 1647, 5048, 4940, + 4939, 4410, 4938, 1867, 4918, 4912, 4886, 4742, 4480, 4720, + 4714, 4655, 4632, 4459, 4458, 4455, 3552, 4454, 4453, 4403, + 4400, 4398, 238, 4336, 4287, 4464, 4283, 4241, 4462, 4082, + 4460, 4076, 1969, 1972, 4469, 1944, 1963, 1960, 1946, 1941, + 4477, 3981, 3978, 3977, 2427, 4475, 3905, 4556, 3866, 4478, + 4481, 4562, 1134, 3739, 3733, 4485, 4472, 4568, 3662, 4483, + 3569, 4486, 4514, 3563, 3559, 4482, 1806, 3387, 3175, 2066, + 4558, 4484, 3150, 3111, 2998, 2979, 2930, 2929, 2885, 2775, + 2164, 238, 2668, 4506, 4496, 2421, 2332, 4525, 2044, 1961, + 4527, 1728, 1707, 1702, 4508, 2086, 1701, 1413, 1869, 1869, + 1700, 1699, 4603, 4534, 1698, 1413, 1697, 1696, 1695, 1694, + 4530, 4042, 4532, 1693, 1692, 4524, 4565, 1691, 4567, 1690, + 1689, 1688, 1687, 1413, 1686, 1685, 1684, 4634, 4523, 4528, + 1683, 1682, 1681, 1680, 1679, 1678, 1677, 4644, 4538, 1676, + 77, 1675, 4633, 1674, 4600, 4546, 1673, 1672, 1671, 4397, + 1670, 4399, 1669, 1668, 1667, 4552, 1666, 1665, 1664, 1413, + 1663, 1413, 4599, 4605, 1660, 4609, 4559, 1659, 1658, 4649, + 2132, 2133, 2134, 2135, 4609, 1656, 1655, 4638, 1654, 4652, + 4579, 4654, 1651, 4582, 4601, 1644, 1643, 1641, 1640, 1002, + 172, 1639, 1638, 1869, 3444, 1637, 1867, 2187, 4592, 172, + 1636, 1635, 1634, 1633, 4615, 1632, 1631, 1630, 4611, 1629, + 4625, 4612, 817, 4617, 1413, 1413, 1413, 4624, 2191, 1413, + 1413, 4622, 2195, 2196, 2197, 2198, 2673, 4372, 4640, 4606, + 1607, 4607, 1623, 2237, 4747, 1622, 1621, 1620, 1619, 1532, + 1493, 1398, 2248, 5067, 4648, 3596, 3597, 5065, 5063, 4578, + 5060, 4690, 4744, 4456, 2945, 2709, 1440, 5315, 4760, 4761, + 4739, 5216, 5214, 5156, 4452, 4695, 4158, 810, 3786, 4692, + 2276, 2277, 3745, 3527, 3170, 1869, 172, 4756, 4702, 4724, + 4725, 4726, 2962, 1531, 4740, 4741, 1460, 3010, 4445, 3608, + 3003, 2187, 3001, 4080, 3609, 3004, 4750, 3002, 2307, 1400, + 2309, 2310, 2311, 2312, 2313, 4796, 4797, 82, 817, 1210, + 2322, 1491, 4789, 3607, 1408, 2996, 3606, 3008, 4749, 3009, + 2999, 4773, 4809, 3552, 4811, 3000, 2995, 4084, 4419, 3605, + 3602, 3007, 2994, 5314, 5094, 4958, 3823, 4085, 3825, 4957, + 1443, 1445, 4463, 3669, 4767, 4931, 4488, 4772, 3830, 4752, + 5343, 5339, 4768, 4694, 4361, 3832, 3833, 3813, 1129, 4812, + 3572, 4814, 1790, 2406, 2407, 2401, 2402, 2403, 4780, 3025, + 4018, 4782, 4347, 1867, 4122, 4844, 4123, 4184, 4186, 4187, + 4790, 4535, 4791, 3915, 3768, 808, 3781, 3078, 4083, 4411, + 3027, 3026, 4817, 4312, 4792, 3567, 4185, 4489, 2519, 2414, + 1923, 3681, 1937, 4644, 4644, 1137, 1986, 1795, 4863, 3682, + 3683, 3684, 3162, 3163, 3815, 4855, 1413, 3283, 2912, 2911, + 1982, 1220, 1986, 2920, 2919, 2615, 4839, 4836, 1265, 4830, + 4842, 2531, 1526, 4818, 5072, 4915, 4872, 172, 4840, 4572, + 4036, 3992, 3991, 4857, 3633, 3231, 4843, 3029, 2953, 2425, + 1566, 2378, 172, 5229, 172, 4845, 4657, 4847, 4514, 2243, + 2242, 2322, 4689, 1726, 1727, 5203, 2322, 2322, 1129, 1724, + 1725, 1722, 1723, 4861, 4862, 1720, 1721, 4914, 4144, 4698, + 4868, 4858, 3132, 3125, 3024, 2539, 1521, 1520, 4613, 1559, + 2677, 2176, 2589, 1139, 1140, 1141, 1142, 3614, 1263, 1492, + 1137, 1492, 2921, 1413, 2679, 2053, 1869, 1469, 1468, 4928, + 1451, 1137, 1137, 4584, 3281, 4934, 2693, 5183, 4856, 5181, + 5120, 5091, 4583, 3280, 5090, 5088, 4993, 4941, 4650, 4529, + 4502, 2631, 4494, 4384, 2634, 4383, 4206, 2637, 4205, 1711, + 2639, 3063, 3032, 1889, 4493, 4913, 4191, 3886, 3360, 3652, + 1466, 4563, 4925, 5218, 5217, 5217, 4929, 4930, 4290, 4653, + 5132, 5133, 5187, 4973, 4276, 4255, 3835, 3768, 4924, 3406, + 4966, 4978, 3405, 3397, 3182, 3178, 4337, 4338, 4339, 2804, + 4985, 2131, 1436, 1407, 5218, 4716, 3552, 5205, 5204, 5129, + 5127, 5125, 4942, 1139, 1140, 1141, 1142, 3426, 1263, 3424, + 4581, 1263, 2881, 2125, 1867, 2125, 4960, 1977, 4980, 2175, + 4981, 4254, 4964, 1582, 1581, 1591, 1592, 1593, 1594, 1584, + 1585, 1586, 1587, 1588, 1589, 1590, 1583, 1139, 1140, 1141, + 1142, 811, 1484, 91, 2, 5242, 5243, 1, 3933, 4982, + 5021, 2883, 2330, 1718, 1138, 1845, 3142, 1413, 2581, 1873, + 4970, 4971, 4988, 2334, 1144, 3016, 3017, 3613, 3019, 2598, + 4994, 1446, 3412, 4995, 2741, 5004, 3757, 5028, 4997, 5010, + 3123, 2934, 4011, 1807, 4990, 1216, 5013, 5014, 2249, 1413, + 2013, 1427, 5043, 2010, 1491, 1426, 1424, 1869, 5070, 2192, + 2270, 1004, 2965, 3734, 3708, 4380, 5228, 5275, 5175, 5231, + 2659, 5078, 2039, 988, 5082, 1210, 1210, 1802, 4208, 3808, + 4947, 5179, 4949, 4771, 2746, 5042, 1564, 4053, 869, 1050, + 1016, 5075, 5076, 1824, 5051, 1642, 2663, 3888, 5079, 3883, + 1015, 4325, 1838, 5069, 3516, 4935, 4848, 870, 2640, 4944, + 5113, 4769, 1938, 1943, 5058, 3028, 5100, 4865, 5044, 4693, + 4118, 3642, 5080, 1875, 1976, 5016, 4401, 1869, 5059, 5061, + 5062, 5064, 5066, 5087, 5085, 4785, 4783, 4784, 3912, 4932, + 5110, 4753, 5106, 5108, 913, 2560, 776, 4743, 5115, 2960, + 5111, 2708, 5107, 5109, 4658, 1867, 4917, 1186, 4306, 2944, + 1187, 1179, 3538, 2784, 3537, 2143, 1573, 2789, 2162, 4247, + 5123, 5121, 4248, 5122, 1617, 2798, 958, 5140, 2786, 3513, + 4439, 3775, 90, 1869, 89, 88, 5131, 271, 1007, 270, + 3552, 4806, 4596, 5077, 985, 984, 983, 982, 981, 980, + 2435, 2434, 4934, 2436, 2433, 2431, 2430, 1814, 1813, 4190, + 4492, 3180, 3181, 3672, 2807, 4412, 3667, 2470, 2467, 1836, + 2468, 3035, 2814, 3065, 4177, 1867, 2466, 4181, 5153, 5148, + 2125, 4230, 4517, 5161, 5055, 5165, 5162, 5056, 5163, 4713, + 5164, 3718, 5166, 4513, 2400, 5182, 3060, 5184, 5185, 2487, + 3688, 1413, 2835, 5180, 5178, 5174, 2484, 2840, 2841, 2842, + 2483, 3680, 2845, 2846, 2847, 2848, 2849, 2850, 2851, 2852, + 4709, 2854, 2855, 4703, 2857, 2858, 5193, 2516, 5194, 5195, + 5000, 1867, 4217, 5252, 5126, 4219, 4220, 5199, 5255, 5128, + 4621, 4620, 4222, 5247, 5124, 4619, 4390, 3628, 3913, 4618, + 4608, 4420, 5207, 5206, 5227, 5208, 4421, 2254, 5211, 4428, + 1356, 2952, 1325, 5213, 5234, 5215, 1320, 1322, 1323, 1321, + 3305, 4171, 3041, 5226, 4030, 5223, 3435, 3434, 3432, 1413, + 3431, 5250, 5250, 5250, 1413, 5282, 1768, 5254, 5257, 4984, + 5238, 5116, 4577, 5100, 5241, 3442, 3440, 1450, 2045, 5245, + 2041, 5246, 1441, 5258, 1395, 2975, 5043, 3959, 5264, 5265, + 1734, 1732, 5271, 5277, 3603, 2997, 2587, 3780, 1815, 1812, + 5219, 5220, 5221, 5222, 4077, 1811, 1294, 1293, 2592, 1267, + 239, 1884, 172, 172, 172, 1265, 240, 171, 1126, 4745, + 5300, 5289, 5300, 4281, 810, 4346, 3759, 3133, 3232, 3622, + 4820, 2405, 1180, 2942, 5302, 126, 48, 144, 125, 1202, + 2254, 1203, 218, 69, 217, 68, 20, 5234, 142, 216, + 67, 5310, 5250, 5319, 53, 5250, 5319, 5307, 5250, 5319, + 5254, 4651, 5322, 5257, 5321, 5324, 5323, 5317, 52, 214, + 121, 120, 5277, 5332, 5335, 119, 5336, 118, 141, 213, + 66, 1184, 255, 254, 5328, 257, 5330, 5340, 5341, 256, + 253, 2125, 3191, 3192, 252, 1197, 1926, 1192, 251, 5092, + 4616, 5168, 51, 50, 219, 49, 127, 70, 47, 5352, + 46, 2692, 3979, 2052, 4301, 1582, 1581, 1591, 1592, 1593, + 1594, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1583, 3427, + 5351, 2926, 5353, 1822, 1823, 45, 1825, 40, 14, 1829, + 12, 1833, 1834, 1835, 43, 41, 25, 24, 2018, 23, + 31, 30, 13, 39, 37, 1606, 36, 2322, 4371, 2322, + 163, 162, 35, 161, 160, 159, 1173, 158, 157, 156, + 155, 34, 22, 61, 60, 59, 4846, 58, 2322, 2322, + 57, 56, 1897, 1898, 8, 4374, 1901, 1902, 1903, 1904, + 1905, 148, 1907, 1908, 1909, 147, 1911, 149, 1914, 145, + 1916, 1917, 1918, 140, 138, 33, 139, 136, 137, 130, + 129, 128, 4875, 4876, 122, 102, 101, 100, 115, 4880, + 4881, 4882, 4883, 4884, 4885, 1922, 114, 113, 4889, 4890, + 4891, 4892, 4893, 4894, 112, 111, 110, 2517, 108, 4897, + 4898, 4899, 2477, 109, 868, 2525, 99, 2359, 2360, 2361, + 98, 97, 96, 95, 135, 134, 1199, 131, 1191, 117, + 124, 123, 106, 116, 107, 105, 104, 1196, 1194, 103, + 94, 93, 92, 133, 132, 2519, 2486, 3237, 146, 3240, + 220, 71, 197, 196, 2399, 195, 2520, 2521, 1185, 194, + 193, 191, 192, 2413, 190, 189, 188, 187, 186, 4926, + 185, 62, 63, 64, 65, 209, 4510, 208, 3879, 210, + 222, 221, 2485, 212, 215, 211, 206, 204, 1129, 207, + 2464, 2465, 3262, 3263, 205, 5197, 1714, 1201, 203, 83, + 11, 2494, 1190, 143, 21, 18, 1189, 3, 0, 0, + 0, 0, 1178, 0, 0, 0, 0, 0, 0, 0, + 2517, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1183, 1582, 1581, 1591, 1592, 1593, 1594, 1584, 1585, + 1586, 1587, 1588, 1589, 1590, 1583, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2519, 0, + 0, 3300, 0, 0, 3303, 0, 4996, 0, 0, 1445, + 0, 0, 0, 2125, 0, 1445, 3323, 3324, 3768, 1195, + 1818, 0, 2510, 1181, 0, 3327, 3328, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3872, 0, 0, + 0, 3333, 3334, 3335, 4904, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2494, 0, 0, 0, 1878, 0, + 0, 1887, 1200, 0, 0, 0, 4636, 4637, 810, 0, + 0, 0, 0, 0, 0, 0, 0, 5052, 0, 0, + 3371, 0, 3373, 0, 0, 3376, 0, 2132, 0, 1182, + 2322, 1582, 1581, 1591, 1592, 1593, 1594, 1584, 1585, 1586, + 1587, 1588, 1589, 1590, 1583, 0, 0, 0, 0, 172, + 2472, 2478, 2476, 0, 0, 0, 2473, 0, 0, 0, + 0, 2498, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2504, 0, 0, 2510, 0, 0, 0, 0, + 2488, 0, 2471, 0, 0, 0, 0, 0, 0, 0, + 1443, 0, 2492, 2526, 2689, 0, 2493, 2495, 2497, 0, + 2499, 2500, 2501, 2505, 2506, 2507, 2509, 2512, 2513, 2514, + 3294, 1198, 0, 0, 0, 0, 0, 2502, 2511, 2503, + 0, 0, 4751, 0, 0, 0, 0, 0, 0, 2480, + 0, 0, 0, 0, 1582, 1581, 1591, 1592, 1593, 1594, + 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1583, 0, 0, + 0, 0, 0, 2517, 0, 1177, 0, 0, 2477, 172, + 0, 2525, 172, 172, 0, 0, 0, 0, 0, 0, + 0, 2518, 0, 0, 2498, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 2504, 0, 0, 0, 0, - 0, 0, 2026, 0, 2492, 0, 0, 0, 3872, 225, - 0, 0, 0, 0, 0, 0, 0, 0, 2519, 2518, - 4837, 0, 0, 0, 2506, 0, 0, 0, 0, 2470, - 2471, 0, 200, 245, 199, 232, 201, 0, 0, 0, - 0, 0, 0, 0, 3906, 0, 0, 2511, 0, 172, - 0, 0, 233, 0, 0, 0, 172, 0, 238, 225, - 0, 0, 1069, 234, 2015, 2486, 0, 0, 0, 2485, - 0, 0, 0, 0, 2451, 2478, 202, 0, 0, 0, - 0, 0, 0, 169, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2504, 0, 0, 0, 1814, 154, 0, - 0, 0, 2492, 0, 0, 0, 0, 0, 238, 0, - 0, 0, 0, 1355, 0, 0, 2519, 2518, 2520, 2513, - 0, 0, 0, 2494, 0, 0, 0, 200, 245, 0, - 0, 0, 0, 0, 2500, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2355, - 2356, 2357, 2592, 0, 2488, 2522, 0, 2515, 2489, 2491, - 2493, 0, 2495, 2496, 2497, 2501, 2502, 2503, 2505, 2508, - 2509, 2510, 0, 2478, 0, 0, 0, 0, 3549, 2498, - 2507, 2499, 0, 0, 0, 0, 2395, 172, 0, 0, - 172, 172, 0, 172, 0, 2409, 0, 0, 179, 180, - 0, 181, 182, 238, 0, 0, 183, 0, 0, 184, - 0, 0, 0, 2490, 0, 0, 2520, 0, 0, 0, - 0, 0, 2460, 2461, 0, 2513, 0, 0, 0, 0, - 0, 0, 0, 2514, 0, 0, 198, 230, 242, 231, - 0, 150, 0, 0, 0, 0, 246, 172, 2318, 0, - 0, 0, 0, 0, 2318, 0, 0, 1320, 0, 4060, - 2032, 224, 223, 2515, 0, 0, 172, 0, 2487, 0, - 0, 0, 4070, 0, 0, 4071, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 178, 198, 230, 242, 231, - 84, 150, 0, 172, 2506, 0, 246, 0, 0, 0, - 0, 1441, 0, 2511, 0, 0, 0, 1441, 0, 0, - 152, 224, 223, 0, 0, 0, 0, 85, 0, 2490, - 0, 2486, 0, 0, 0, 2485, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 178, 0, 0, 0, 0, - 0, 4130, 0, 0, 0, 0, 0, 0, 0, 2504, - 0, 0, 0, 0, 0, 0, 0, 0, 2492, 0, - 0, 0, 151, 0, 0, 0, 2487, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 226, 227, - 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 246, 0, 2494, 0, 0, 3550, 0, 0, 0, - 2506, 0, 0, 0, 2500, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 4150, 0, - 0, 0, 1602, 0, 2488, 2522, 0, 0, 2489, 2491, - 2493, 0, 2495, 2496, 2497, 2501, 2502, 2503, 2505, 2508, - 2509, 2510, 1439, 0, 0, 0, 2685, 0, 0, 2498, - 2507, 2499, 0, 0, 235, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2519, 2486, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2520, 2521, 0, 2492, 2526, 0, 0, 2493, + 2495, 2497, 0, 2499, 2500, 2501, 2505, 2506, 2507, 2509, + 2512, 2513, 2514, 2474, 2475, 3291, 0, 0, 2485, 0, + 2502, 2511, 2503, 0, 0, 0, 0, 0, 0, 0, + 0, 2515, 0, 0, 0, 0, 0, 2494, 0, 1582, + 1581, 1591, 1592, 1593, 1594, 1584, 1585, 1586, 1587, 1588, + 1589, 1590, 1583, 2490, 0, 0, 1174, 2489, 0, 0, + 1172, 1175, 0, 0, 0, 0, 0, 0, 1176, 0, + 0, 0, 0, 0, 2518, 0, 0, 0, 0, 0, + 0, 2508, 0, 2322, 0, 0, 0, 0, 0, 0, + 2496, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2589, 2523, 2522, 0, 0, 0, 0, + 0, 0, 1290, 0, 0, 0, 2805, 0, 2510, 1582, + 1581, 1591, 1592, 1593, 1594, 1584, 1585, 1586, 1587, 1588, + 1589, 1590, 1583, 0, 0, 0, 0, 3793, 0, 3795, + 0, 0, 0, 0, 2515, 0, 0, 2779, 0, 2603, + 2604, 0, 0, 0, 0, 0, 2610, 1606, 0, 0, + 0, 2482, 0, 0, 1922, 2617, 2490, 0, 0, 0, + 2489, 1582, 1581, 1591, 1592, 1593, 1594, 1584, 1585, 1586, + 1587, 1588, 1589, 1590, 1583, 0, 0, 0, 0, 0, + 0, 0, 0, 2906, 2508, 2908, 4943, 1291, 0, 0, + 0, 0, 0, 2496, 2524, 0, 3636, 3637, 2476, 0, + 0, 0, 3635, 0, 0, 0, 0, 2498, 0, 0, + 2932, 2933, 0, 0, 0, 0, 0, 0, 2504, 0, + 0, 0, 0, 0, 2949, 2950, 2951, 0, 0, 0, + 0, 2669, 0, 0, 3853, 0, 0, 0, 2492, 2526, + 0, 0, 2493, 2495, 2497, 0, 2499, 2500, 2501, 2505, + 2506, 2507, 2509, 2512, 2513, 2514, 0, 0, 0, 0, + 0, 0, 3876, 2502, 2511, 2503, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2480, 0, 1284, 0, 1276, + 1280, 1282, 1582, 1581, 1591, 1592, 1593, 1594, 1584, 1585, + 1586, 1587, 1588, 1589, 1590, 1583, 0, 0, 3910, 1569, + 0, 1570, 1568, 0, 0, 1287, 0, 0, 0, 1279, + 0, 172, 200, 245, 199, 232, 201, 2518, 172, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 233, 0, 0, 0, 2455, 0, 0, 225, + 0, 0, 0, 234, 2491, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 202, 0, 0, 1818, + 1285, 0, 0, 169, 0, 0, 0, 0, 0, 2474, + 2475, 0, 1838, 0, 0, 0, 0, 0, 154, 0, + 0, 0, 1288, 0, 0, 0, 0, 2515, 238, 1289, + 0, 2226, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1875, 2490, + 0, 0, 0, 2489, 2596, 925, 924, 931, 921, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 928, 929, + 0, 930, 934, 0, 1277, 915, 0, 2508, 1445, 0, + 0, 0, 0, 0, 0, 939, 2496, 0, 0, 172, + 0, 0, 172, 172, 0, 172, 0, 2491, 1286, 0, + 2523, 2522, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1200, 0, 0, 0, 0, 179, 180, + 0, 181, 182, 0, 0, 0, 183, 0, 0, 184, + 0, 0, 0, 943, 0, 0, 945, 0, 0, 0, + 1278, 944, 2322, 0, 0, 0, 0, 0, 2322, 172, + 0, 0, 0, 4064, 0, 0, 0, 2482, 0, 0, + 0, 0, 0, 0, 0, 0, 4074, 2517, 172, 4075, + 0, 0, 0, 0, 0, 200, 245, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, + 2524, 0, 0, 0, 0, 2519, 198, 230, 242, 231, + 84, 150, 0, 0, 0, 0, 246, 0, 0, 0, + 0, 0, 1283, 0, 0, 0, 3553, 0, 0, 0, + 152, 224, 223, 0, 0, 4134, 0, 85, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 178, 0, 0, 2222, 0, + 0, 2494, 0, 0, 0, 2219, 1273, 0, 0, 2221, + 2218, 2220, 2224, 2225, 0, 0, 0, 2223, 0, 0, + 0, 0, 151, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2517, 0, 0, 0, 0, 0, 226, 227, + 228, 0, 0, 0, 0, 0, 0, 0, 916, 918, + 917, 0, 4154, 0, 0, 0, 0, 0, 0, 0, + 923, 0, 0, 0, 1606, 0, 0, 0, 0, 0, + 2519, 0, 927, 0, 0, 0, 0, 0, 0, 942, + 0, 0, 2510, 0, 0, 0, 920, 0, 0, 0, + 2491, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2517, 0, + 0, 0, 0, 0, 235, 0, 0, 1292, 3407, 3408, + 3409, 1272, 1274, 0, 0, 0, 2494, 0, 0, 1275, 0, 0, 0, 0, 0, 164, 0, 0, 0, 229, - 0, 165, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2494, - 0, 0, 853, 2514, 0, 0, 0, 0, 0, 0, - 2500, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4443, 0, 0, - 2488, 2522, 0, 4422, 2489, 2491, 2493, 166, 2495, 2496, - 2497, 2501, 2502, 2503, 2505, 2508, 2509, 2510, 0, 4230, - 75, 0, 0, 79, 0, 2498, 2507, 2499, 0, 4233, - 4234, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2511, 0, 4436, 849, 850, 0, 0, - 0, 0, 0, 0, 2033, 241, 2034, 895, 0, 4425, - 0, 2486, 0, 0, 0, 2485, 4247, 0, 0, 4249, - 4419, 0, 0, 79, 0, 4445, 4446, 0, 0, 2514, - 0, 4420, 0, 0, 0, 0, 0, 0, 0, 2504, - 0, 0, 2487, 0, 0, 0, 0, 0, 2492, 0, - 0, 0, 0, 0, 176, 241, 177, 0, 0, 0, - 0, 921, 920, 927, 917, 0, 0, 0, 0, 72, - 4421, 0, 4428, 0, 924, 925, 0, 926, 930, 0, - 4150, 911, 0, 0, 0, 0, 0, 0, 172, 0, - 0, 935, 0, 172, 0, 0, 0, 1261, 0, 2511, - 172, 172, 168, 897, 0, 0, 896, 1814, 1814, 1814, - 1814, 1814, 1814, 1814, 1814, 0, 0, 2486, 3551, 0, - 0, 2485, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 939, - 0, 0, 941, 0, 0, 2504, 0, 940, 0, 0, - 0, 167, 168, 55, 2492, 0, 0, 0, 0, 73, - 882, 0, 0, 0, 9, 2222, 0, 0, 0, 0, - 854, 0, 0, 0, 0, 2902, 0, 2904, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4444, 0, 3046, 856, 74, 0, - 173, 174, 2928, 2929, 175, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2945, 2946, 2947, 0, - 0, 4432, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 853, 0, 0, 0, 0, - 0, 0, 0, 4429, 4433, 4431, 4430, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2318, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 878, 0, 880, 877, 0, 2318, - 0, 881, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4439, 4440, 0, 0, 0, 0, 0, 172, 849, - 850, 0, 2487, 0, 912, 914, 913, 0, 0, 0, - 895, 0, 0, 0, 0, 0, 919, 876, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 923, 848, - 0, 0, 0, 0, 1261, 938, 0, 0, 0, 0, - 855, 890, 916, 0, 0, 0, 906, 0, 0, 0, - 0, 0, 0, 172, 1834, 0, 4535, 0, 0, 0, - 0, 0, 886, 0, 4447, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4423, 0, 0, - 4438, 0, 2218, 0, 0, 0, 0, 0, 0, 2215, - 1871, 0, 0, 2217, 2214, 2216, 2220, 2221, 887, 891, - 841, 2219, 0, 0, 0, 0, 897, 0, 2487, 896, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 873, - 1441, 871, 875, 894, 0, 0, 0, 872, 869, 867, - 0, 874, 858, 859, 857, 0, 847, 860, 861, 862, - 863, 842, 0, 0, 892, 0, 893, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4631, 888, 889, 0, - 0, 0, 0, 882, 0, 0, 0, 0, 1624, 0, - 0, 0, 0, 854, 0, 1198, 0, 1199, 0, 0, - 1565, 0, 1566, 1564, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 884, 0, 918, 922, 928, - 856, 929, 931, 0, 843, 932, 933, 934, 0, 0, - 0, 936, 937, 879, 0, 0, 0, 1180, 0, 0, - 868, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1193, 0, 1188, 0, 0, 0, 0, 2203, 2204, - 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212, 2213, 2225, - 2226, 2227, 2228, 2229, 2230, 2223, 2224, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2222, 0, 0, 0, 0, 878, 0, 880, - 877, 0, 4751, 0, 881, 0, 0, 0, 0, 0, - 0, 0, 0, 4437, 0, 0, 0, 0, 0, 0, - 0, 0, 1169, 0, 0, 0, 0, 0, 4442, 883, - 0, 0, 0, 0, 0, 851, 852, 172, 0, 840, - 844, 0, 0, 0, 0, 0, 0, 845, 0, 0, - 876, 0, 0, 0, 0, 0, 0, 0, 846, 0, - 0, 0, 848, 0, 0, 4426, 4427, 172, 0, 0, - 0, 0, 0, 855, 890, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 915, 0, 0, - 4659, 0, 0, 0, 0, 886, 0, 0, 0, 0, - 0, 1814, 0, 1814, 0, 0, 0, 0, 0, 0, - 0, 0, 1195, 0, 1187, 0, 0, 0, 0, 0, - 0, 0, 0, 1192, 1190, 0, 0, 0, 0, 0, - 0, 887, 891, 0, 4680, 942, 943, 944, 945, 946, - 3403, 3404, 3405, 0, 1181, 0, 0, 0, 1918, 0, - 0, 0, 873, 0, 871, 875, 894, 0, 0, 0, - 872, 869, 867, 0, 874, 858, 859, 857, 0, 847, - 860, 861, 862, 863, 842, 0, 4658, 892, 0, 893, - 0, 0, 0, 1197, 0, 0, 0, 0, 1186, 0, - 888, 889, 1185, 921, 920, 927, 917, 0, 1174, 0, - 0, 0, 0, 0, 0, 0, 924, 925, 0, 926, - 930, 0, 3582, 911, 0, 0, 0, 1179, 0, 2218, - 0, 0, 0, 935, 0, 0, 2215, 0, 884, 4912, - 2217, 2214, 2216, 2220, 2221, 0, 0, 843, 2219, 0, - 0, 0, 0, 0, 0, 0, 879, 0, 0, 0, - 0, 0, 0, 868, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1191, 0, 0, 0, 1177, - 1814, 939, 0, 0, 941, 0, 0, 0, 172, 940, - 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 165, 0, 0, 0, 0, 2519, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2207, 2208, + 2209, 2210, 2211, 2212, 2213, 2214, 2215, 2216, 2217, 2229, + 2230, 2231, 2232, 2233, 2234, 2227, 2228, 0, 0, 246, + 0, 2498, 0, 4234, 3554, 0, 0, 0, 0, 0, + 3586, 0, 2504, 4237, 4238, 0, 0, 0, 0, 0, + 0, 166, 2494, 4841, 0, 0, 0, 2510, 0, 0, + 0, 0, 2492, 2526, 75, 0, 2493, 2495, 2497, 0, + 2499, 2500, 2501, 2505, 2506, 2507, 2509, 2512, 2513, 2514, + 4251, 0, 0, 4253, 0, 0, 0, 2502, 2511, 2503, + 0, 922, 926, 932, 0, 933, 935, 0, 0, 936, + 937, 938, 0, 0, 0, 940, 941, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2510, 0, 0, 0, 0, 0, 0, + 0, 2518, 0, 0, 4154, 0, 0, 0, 176, 241, + 177, 0, 0, 0, 0, 0, 2498, 0, 0, 0, + 172, 0, 0, 72, 0, 172, 0, 2504, 0, 1265, + 0, 0, 172, 172, 0, 0, 0, 0, 0, 1818, + 1818, 1818, 1818, 1818, 1818, 1818, 1818, 2492, 2526, 0, + 0, 2493, 2495, 2497, 0, 2499, 2500, 2501, 2505, 2506, + 2507, 2509, 2512, 2513, 2514, 0, 0, 0, 0, 0, + 0, 2515, 2502, 2511, 2503, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3782, 0, + 0, 0, 2498, 2490, 0, 0, 0, 2489, 0, 0, + 0, 0, 0, 2504, 0, 167, 168, 55, 0, 0, + 0, 0, 0, 73, 0, 0, 0, 0, 9, 0, + 0, 2508, 0, 2492, 2526, 919, 2518, 2493, 2495, 2497, + 2496, 2499, 2500, 2501, 2505, 2506, 2507, 2509, 2512, 2513, + 2514, 0, 0, 0, 0, 857, 0, 0, 2502, 2511, + 2503, 0, 74, 0, 173, 174, 0, 0, 175, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 946, 947, 948, 949, 950, 0, 0, + 0, 0, 0, 0, 0, 0, 2322, 0, 0, 857, + 0, 0, 0, 0, 0, 0, 2515, 0, 0, 0, + 3555, 0, 2518, 2322, 0, 0, 200, 245, 199, 232, + 201, 0, 0, 0, 0, 0, 0, 0, 2490, 853, + 854, 0, 2489, 0, 0, 0, 2030, 0, 0, 0, + 899, 0, 0, 225, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 2508, 0, 0, 0, + 0, 0, 0, 0, 0, 2496, 0, 0, 0, 0, + 0, 0, 0, 853, 854, 0, 0, 0, 0, 0, + 0, 0, 2515, 0, 899, 0, 1265, 0, 0, 0, + 0, 0, 238, 0, 0, 0, 1073, 0, 2019, 0, + 4539, 0, 0, 0, 2490, 172, 0, 0, 2489, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2508, 3957, 0, 0, 901, 0, 0, 900, + 0, 2496, 0, 4447, 0, 0, 0, 0, 0, 4426, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 901, 0, 0, 900, 0, 0, 0, 0, 0, 0, + 0, 4440, 0, 886, 0, 0, 0, 0, 0, 0, + 4635, 0, 0, 858, 2491, 4429, 0, 0, 0, 0, + 0, 0, 1628, 0, 0, 0, 4423, 0, 0, 0, + 0, 4449, 4450, 0, 0, 0, 0, 4424, 0, 0, + 860, 0, 0, 0, 0, 0, 0, 886, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 858, 0, 0, + 0, 0, 0, 0, 0, 4021, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4425, 0, 4432, 0, + 198, 230, 242, 231, 860, 150, 4037, 0, 4038, 0, + 246, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2036, 224, 223, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 882, 0, 884, + 881, 0, 0, 0, 885, 0, 0, 0, 0, 178, + 0, 0, 0, 0, 0, 0, 4755, 0, 0, 2491, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 882, 0, 884, 881, 0, 0, 0, 885, 0, + 880, 0, 0, 0, 0, 0, 0, 2226, 0, 172, + 0, 0, 852, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 859, 894, 0, 0, 0, 0, 0, + 4448, 0, 3050, 0, 0, 0, 0, 0, 0, 172, + 0, 0, 0, 0, 880, 2491, 0, 0, 0, 890, + 0, 0, 0, 0, 0, 0, 852, 4436, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 859, 894, 0, + 0, 0, 0, 1818, 0, 1818, 0, 0, 0, 4433, + 4437, 4435, 4434, 0, 0, 891, 895, 845, 0, 0, + 0, 0, 0, 890, 0, 0, 0, 0, 0, 0, + 0, 1445, 0, 0, 0, 0, 877, 0, 875, 879, + 898, 0, 1922, 0, 876, 873, 871, 0, 878, 862, + 863, 861, 0, 851, 864, 865, 866, 867, 846, 891, + 895, 896, 0, 897, 0, 0, 0, 4443, 4444, 0, + 0, 0, 0, 0, 892, 893, 0, 0, 0, 0, + 877, 0, 875, 879, 898, 0, 0, 0, 876, 873, + 871, 0, 878, 862, 863, 861, 0, 851, 864, 865, + 866, 867, 846, 0, 0, 896, 0, 897, 0, 4663, + 0, 0, 888, 0, 0, 0, 0, 0, 892, 893, + 0, 847, 0, 4916, 0, 0, 0, 0, 0, 0, + 883, 0, 0, 0, 0, 0, 0, 872, 0, 0, + 4451, 0, 0, 0, 4226, 0, 0, 0, 0, 0, + 0, 0, 0, 4684, 0, 0, 888, 4427, 0, 0, + 4442, 79, 0, 0, 2222, 847, 0, 0, 0, 0, + 0, 2219, 1818, 0, 883, 2221, 2218, 2220, 2224, 2225, + 172, 872, 0, 2223, 0, 172, 0, 925, 924, 931, + 921, 0, 2037, 241, 2038, 4662, 0, 0, 0, 0, + 928, 929, 0, 930, 934, 0, 0, 915, 925, 924, + 931, 921, 0, 0, 0, 0, 0, 939, 0, 0, + 0, 928, 929, 0, 930, 934, 887, 0, 915, 0, + 0, 0, 855, 856, 0, 0, 844, 848, 939, 0, + 0, 0, 0, 0, 849, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 850, 0, 0, 0, 0, + 0, 0, 0, 5012, 0, 943, 0, 0, 945, 0, + 887, 0, 0, 944, 0, 0, 855, 856, 0, 0, + 844, 848, 0, 0, 0, 0, 0, 0, 849, 0, + 168, 0, 0, 0, 0, 0, 0, 0, 0, 850, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1445, 0, 0, 5050, 0, 0, 0, 0, + 0, 0, 0, 0, 2207, 2208, 2209, 2210, 2211, 2212, + 2213, 2214, 2215, 2216, 2217, 2229, 2230, 2231, 2232, 2233, + 2234, 2227, 2228, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4441, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4659, 0, 4446, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4430, 4431, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 916, 918, 917, 0, 0, 0, 0, 0, 0, 0, + 0, 5145, 923, 0, 0, 0, 5149, 0, 0, 0, + 0, 916, 918, 917, 927, 0, 0, 0, 0, 0, + 1445, 942, 0, 923, 0, 0, 0, 0, 920, 0, + 0, 0, 910, 0, 0, 927, 0, 4664, 4665, 0, + 0, 0, 942, 0, 0, 0, 0, 0, 0, 920, + 0, 0, 0, 0, 4660, 4661, 0, 4668, 4667, 4666, + 4682, 4683, 4685, 4669, 4670, 4673, 4675, 4674, 4671, 4672, + 4676, 4678, 4679, 4680, 4677, 0, 4681, 0, 0, 0, + 0, 0, 4686, 0, 1265, 0, 172, 0, 0, 4688, + 0, 0, 0, 4687, 0, 5145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1196, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1818, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1178, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 883, 0, 0, 0, 0, 0, 851, 852, - 0, 0, 840, 844, 0, 0, 0, 0, 0, 0, - 845, 0, 0, 0, 0, 0, 0, 4655, 0, 5008, - 0, 846, 0, 0, 0, 2203, 2204, 2205, 2206, 2207, - 2208, 2209, 2210, 2211, 2212, 2213, 2225, 2226, 2227, 2228, - 2229, 2230, 2223, 2224, 0, 0, 0, 0, 0, 0, - 3778, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1194, 0, 0, 0, 0, 0, 0, - 0, 5046, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 912, 914, 913, 0, - 0, 0, 0, 0, 0, 0, 0, 1173, 919, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 4660, 4661, - 923, 0, 0, 0, 0, 0, 0, 938, 0, 0, - 0, 0, 0, 0, 916, 4656, 4657, 0, 4664, 4663, - 4662, 4678, 4679, 4681, 4665, 4666, 4669, 4671, 4670, 4667, - 4668, 4672, 4674, 4675, 4676, 4673, 0, 4677, 0, 0, - 0, 0, 0, 4682, 0, 0, 0, 0, 0, 0, - 4684, 0, 0, 0, 4683, 0, 0, 0, 0, 0, + 0, 0, 0, 5145, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 922, 926, 932, 0, 933, 935, 0, + 0, 936, 937, 938, 0, 0, 0, 940, 941, 0, + 0, 0, 0, 0, 922, 926, 932, 0, 933, 935, + 0, 0, 936, 937, 938, 0, 0, 0, 940, 941, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 5141, 0, 0, - 0, 0, 5145, 0, 0, 0, 0, 0, 1170, 0, - 0, 0, 1168, 1171, 0, 0, 0, 0, 0, 0, - 1172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5334, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4723, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1261, 0, 172, 3953, 0, 0, 0, 918, - 922, 928, 0, 929, 931, 0, 0, 932, 933, 934, - 0, 5141, 0, 936, 937, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1814, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 5141, - 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 172, 0, 0, 0, 0, 919, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 919, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4017, 0, 0, + 0, 0, 0, 0, 0, 4798, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 946, 947, 948, 949, 950, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 4033, 0, - 4034, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 915, - 0, 0, 0, 5319, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 942, 943, 944, - 945, 946, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4156, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1441, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1818, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 4152, - 0, 0, 0, 0, 0, 0, 4222, 0, 0, 172, - 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1818, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1814, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1441, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1814, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 4152, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1441, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 200, 245, 1019, 0, 0, 0, 0, 0, 0, - 0, 172, 500, 0, 0, 643, 677, 666, 755, 630, - 0, 0, 0, 0, 0, 0, 970, 0, 0, 0, - 394, 0, 0, 463, 681, 662, 673, 663, 506, 648, - 649, 650, 657, 406, 651, 787, 653, 622, 654, 623, - 655, 656, 1605, 680, 629, 542, 482, 0, 697, 0, - 0, 1092, 1101, 0, 0, 0, 0, 0, 0, 0, - 0, 1088, 0, 0, 0, 0, 0, 961, 0, 0, - 999, 1069, 1068, 986, 996, 0, 0, 365, 269, 624, - 751, 626, 625, 987, 0, 988, 992, 995, 991, 989, - 990, 0, 1083, 0, 0, 0, 0, 0, 0, 953, - 965, 0, 971, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 962, 963, - 0, 0, 0, 0, 1020, 0, 964, 0, 966, 0, - 0, 0, 0, 543, 571, 0, 584, 0, 432, 433, - 1015, 993, 997, 0, 0, 0, 0, 350, 550, 568, - 366, 537, 582, 371, 545, 561, 361, 499, 533, 0, - 0, 352, 566, 544, 477, 351, 0, 526, 391, 408, - 388, 497, 994, 0, 1018, 1022, 387, 1107, 1016, 576, - 354, 0, 575, 496, 469, 562, 567, 478, 471, 0, - 353, 564, 476, 470, 446, 398, 1108, 447, 448, 449, - 450, 451, 452, 412, 512, 467, 513, 413, 484, 483, - 485, 414, 415, 416, 417, 418, 419, 420, 421, 422, - 423, 0, 0, 0, 0, 0, 606, 607, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4719, 0, 743, 1013, 246, 748, 0, 578, 0, - 0, 1090, 0, 0, 172, 548, 0, 0, 453, 0, - 0, 0, 1017, 0, 529, 502, 1104, 0, 0, 527, - 465, 563, 514, 569, 551, 577, 521, 515, 344, 552, - 390, 479, 362, 364, 776, 392, 395, 399, 400, 490, - 491, 508, 536, 555, 556, 557, 389, 376, 528, 377, - 409, 378, 345, 381, 380, 382, 538, 383, 347, 509, - 560, 0, 405, 524, 474, 348, 473, 510, 559, 558, - 363, 586, 593, 594, 685, 0, 599, 790, 791, 792, - 608, 0, 516, 359, 356, 0, 0, 4794, 385, 511, - 372, 374, 375, 373, 505, 507, 613, 614, 615, 617, - 0, 618, 619, 0, 0, 0, 0, 620, 686, 704, - 670, 639, 601, 694, 636, 640, 641, 426, 427, 428, - 429, 707, 0, 0, 0, 592, 454, 455, 0, 397, - 396, 475, 349, 0, 0, 443, 425, 517, 355, 393, - 445, 431, 456, 457, 458, 459, 460, 0, 461, 462, - 403, 339, 340, 784, 1087, 498, 709, 746, 747, 631, - 0, 1103, 1082, 1084, 1085, 1089, 1093, 1094, 1095, 1096, - 1097, 1099, 1102, 1106, 783, 0, 687, 701, 788, 700, - 780, 504, 0, 535, 698, 645, 0, 691, 664, 665, - 0, 692, 660, 696, 0, 633, 0, 602, 605, 635, - 722, 723, 724, 346, 604, 726, 727, 728, 729, 730, - 731, 732, 725, 1105, 668, 644, 671, 583, 647, 646, - 0, 0, 682, 1021, 683, 684, 486, 487, 488, 489, - 1091, 710, 370, 603, 519, 520, 0, 669, 172, 0, - 0, 0, 0, 0, 0, 0, 674, 675, 672, 793, - 0, 733, 734, 0, 0, 597, 598, 402, 0, 616, - 410, 369, 503, 404, 581, 434, 0, 609, 676, 610, - 522, 523, 737, 742, 738, 739, 741, 762, 493, 424, - 430, 539, 444, 466, 525, 580, 501, 530, 367, 570, - 541, 472, 661, 689, 1114, 1086, 1113, 1115, 1116, 1112, - 1117, 1118, 1098, 975, 0, 1028, 1029, 1110, 1109, 1111, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 718, 717, 716, 715, 714, 713, 712, 711, 0, - 0, 658, 384, 781, 775, 782, 763, 766, 765, 740, - 982, 341, 638, 464, 518, 401, 705, 706, 0, 761, - 1076, 1039, 1040, 1041, 972, 1042, 1036, 1037, 973, 1038, - 1077, 1026, 1073, 1074, 1001, 1031, 1043, 1072, 1044, 1075, - 1002, 1078, 1119, 1120, 1050, 1034, 302, 1121, 1047, 1079, - 1071, 1070, 1045, 1027, 1080, 1081, 1009, 1004, 1048, 1049, - 1035, 1056, 1057, 1058, 1061, 974, 1062, 1063, 1064, 1065, - 1066, 1060, 1059, 1023, 1024, 1025, 1051, 1052, 1054, 1055, - 1030, 549, 1005, 1006, 1007, 1008, 0, 0, 587, 588, - 589, 612, 0, 590, 572, 637, 411, 342, 553, 579, - 778, 779, 0, 0, 0, 0, 0, 0, 0, 688, - 699, 735, 736, 0, 749, 750, 752, 754, 1067, 756, - 546, 547, 764, 0, 0, 435, 357, 358, 494, 495, - 532, 0, 436, 437, 438, 442, 439, 440, 441, 1053, - 759, 760, 757, 468, 531, 554, 540, 777, 481, 0, - 785, 627, 628, 786, 745, 744, 343, 0, 1032, 1033, - 702, 703, 1019, 0, 1100, 480, 634, 0, 967, 0, - 0, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 0, 0, 0, 0, 970, 0, 0, 0, 394, - 0, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 1010, 680, 629, 542, 482, 0, 697, 0, 0, - 1092, 1101, 0, 0, 0, 0, 0, 0, 0, 0, - 1088, 0, 0, 0, 0, 0, 961, 0, 0, 999, - 1069, 1068, 986, 996, 0, 0, 365, 269, 624, 751, - 626, 625, 987, 0, 988, 992, 995, 991, 989, 990, - 0, 1083, 0, 0, 0, 0, 0, 0, 953, 965, - 0, 971, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 962, 963, 0, - 0, 0, 0, 1020, 0, 964, 0, 966, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 1015, - 993, 997, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 994, 0, 1018, 1022, 387, 1107, 1016, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 1108, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 1013, 0, 748, 0, 578, 0, 0, - 1090, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 1017, 0, 529, 502, 1104, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 2247, 2246, 2248, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 1087, 498, 709, 746, 747, 631, 0, - 1103, 1082, 1084, 1085, 1089, 1093, 1094, 1095, 1096, 1097, - 1099, 1102, 1106, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 1105, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 1021, 683, 684, 486, 487, 488, 489, 1091, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 1114, 1086, 1113, 1115, 1116, 1112, 1117, - 1118, 1098, 975, 0, 1028, 1029, 1110, 1109, 1111, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 982, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 1076, - 1039, 1040, 1041, 972, 1042, 1036, 1037, 973, 1038, 1077, - 1026, 1073, 1074, 1001, 1031, 1043, 1072, 1044, 1075, 1002, - 1078, 1119, 1120, 1050, 1034, 302, 1121, 1047, 1079, 1071, - 1070, 1045, 1027, 1080, 1081, 1009, 1004, 1048, 1049, 1035, - 1056, 1057, 1058, 1061, 974, 1062, 1063, 1064, 1065, 1066, - 1060, 1059, 1023, 1024, 1025, 1051, 1052, 1054, 1055, 1030, - 549, 1005, 1006, 1007, 1008, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 1067, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 1053, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 1032, 1033, 702, - 703, 0, 0, 1100, 480, 634, 0, 967, 200, 245, - 1019, 0, 0, 0, 0, 0, 0, 0, 0, 500, - 0, 0, 643, 677, 666, 755, 630, 0, 0, 0, - 0, 0, 0, 970, 0, 0, 0, 394, 0, 0, - 463, 681, 662, 673, 663, 506, 648, 649, 650, 657, - 406, 651, 787, 653, 622, 654, 623, 655, 656, 1010, - 680, 629, 542, 482, 0, 697, 0, 0, 1092, 1101, - 0, 0, 0, 0, 0, 0, 0, 0, 1088, 0, - 0, 0, 0, 0, 961, 0, 0, 999, 1069, 1068, - 986, 996, 0, 0, 365, 269, 624, 751, 626, 625, - 987, 0, 988, 992, 995, 991, 989, 990, 0, 1083, - 0, 0, 0, 0, 0, 0, 953, 965, 0, 971, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 962, 963, 0, 0, 0, - 0, 1020, 0, 964, 0, 966, 0, 0, 0, 0, - 543, 571, 0, 584, 0, 432, 433, 1015, 993, 997, - 0, 0, 0, 0, 350, 550, 568, 366, 537, 582, - 371, 545, 561, 361, 499, 533, 0, 0, 352, 566, - 544, 477, 351, 0, 526, 391, 408, 388, 497, 994, - 0, 1018, 1022, 387, 1107, 1016, 576, 354, 0, 575, - 496, 469, 562, 567, 478, 471, 0, 353, 564, 476, - 470, 446, 398, 1108, 447, 448, 449, 450, 451, 452, - 412, 512, 467, 513, 413, 484, 483, 485, 414, 415, - 416, 417, 418, 419, 420, 421, 422, 423, 0, 0, - 0, 0, 0, 606, 607, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 743, 1013, 0, 748, 0, 578, 0, 0, 1090, 0, - 0, 0, 548, 0, 0, 453, 0, 0, 0, 1017, - 0, 529, 502, 1104, 0, 0, 527, 465, 563, 514, - 569, 551, 577, 521, 515, 344, 552, 390, 479, 362, - 364, 776, 392, 395, 399, 400, 490, 491, 508, 536, - 555, 556, 557, 389, 376, 528, 377, 409, 378, 345, - 381, 380, 382, 538, 383, 347, 509, 560, 0, 405, - 524, 474, 348, 473, 510, 559, 558, 363, 586, 593, - 594, 685, 0, 599, 790, 791, 792, 608, 0, 516, - 359, 356, 0, 0, 0, 385, 511, 372, 374, 375, - 373, 505, 507, 613, 614, 615, 617, 0, 618, 619, - 0, 0, 0, 0, 620, 686, 704, 670, 639, 601, - 694, 636, 640, 641, 426, 427, 428, 429, 707, 0, - 0, 0, 592, 454, 455, 0, 397, 396, 475, 349, - 0, 0, 443, 425, 517, 355, 393, 445, 431, 456, - 457, 458, 459, 460, 0, 461, 462, 403, 339, 340, - 784, 1087, 498, 709, 746, 747, 631, 0, 1103, 1082, - 1084, 1085, 1089, 1093, 1094, 1095, 1096, 1097, 1099, 1102, - 1106, 783, 0, 687, 701, 788, 700, 780, 504, 0, - 535, 698, 645, 0, 691, 664, 665, 0, 692, 660, - 696, 0, 633, 0, 602, 605, 635, 722, 723, 724, - 346, 604, 726, 727, 728, 729, 730, 731, 732, 725, - 1105, 668, 644, 671, 583, 647, 646, 0, 0, 682, - 1021, 683, 684, 486, 487, 488, 489, 1091, 710, 370, - 603, 519, 520, 0, 669, 0, 0, 0, 0, 0, - 0, 0, 0, 674, 675, 672, 793, 0, 733, 734, - 0, 0, 597, 598, 402, 0, 616, 410, 369, 503, - 404, 581, 434, 0, 609, 676, 610, 522, 523, 737, - 742, 738, 739, 741, 762, 493, 424, 430, 539, 444, - 466, 525, 580, 501, 530, 367, 570, 541, 472, 661, - 689, 1114, 1086, 1113, 1115, 1116, 1112, 1117, 1118, 1098, - 975, 0, 1028, 1029, 1110, 1109, 1111, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 718, 717, - 716, 715, 714, 713, 712, 711, 0, 0, 658, 384, - 781, 775, 782, 763, 766, 765, 740, 982, 341, 638, - 464, 518, 401, 705, 706, 0, 761, 1076, 1039, 1040, - 1041, 972, 1042, 1036, 1037, 973, 1038, 1077, 1026, 1073, - 1074, 1001, 1031, 1043, 1072, 1044, 1075, 1002, 1078, 1119, - 1120, 1050, 1034, 302, 1121, 1047, 1079, 1071, 1070, 1045, - 1027, 1080, 1081, 1009, 1004, 1048, 1049, 1035, 1056, 1057, - 1058, 1061, 974, 1062, 1063, 1064, 1065, 1066, 1060, 1059, - 1023, 1024, 1025, 1051, 1052, 1054, 1055, 1030, 549, 1005, - 1006, 1007, 1008, 0, 0, 587, 588, 589, 612, 0, - 590, 572, 637, 411, 342, 553, 579, 778, 779, 0, - 0, 0, 0, 0, 0, 0, 688, 699, 735, 736, - 0, 749, 750, 752, 754, 1067, 756, 546, 547, 764, - 0, 0, 435, 357, 358, 494, 495, 532, 0, 436, - 437, 438, 442, 439, 440, 441, 1053, 759, 760, 757, - 468, 531, 554, 540, 777, 481, 0, 785, 627, 628, - 786, 745, 744, 343, 0, 1032, 1033, 702, 703, 1019, - 0, 1100, 480, 634, 0, 967, 0, 0, 500, 0, - 0, 643, 677, 666, 755, 630, 0, 0, 0, 0, - 0, 0, 970, 0, 0, 0, 394, 2319, 0, 463, - 681, 662, 673, 663, 506, 648, 649, 650, 657, 406, - 651, 787, 653, 622, 654, 623, 655, 656, 1010, 680, - 629, 542, 482, 0, 697, 0, 0, 1092, 1101, 0, - 0, 0, 0, 0, 0, 0, 0, 1088, 0, 2568, - 0, 0, 0, 961, 0, 0, 999, 1069, 1068, 986, - 996, 0, 0, 365, 269, 624, 751, 626, 625, 987, - 0, 988, 992, 995, 991, 989, 990, 0, 1083, 0, - 0, 0, 0, 0, 0, 953, 965, 0, 971, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 962, 963, 0, 0, 0, 0, - 1020, 0, 964, 0, 966, 0, 0, 0, 0, 543, - 571, 0, 584, 0, 432, 433, 2569, 993, 997, 0, - 0, 0, 0, 350, 550, 568, 366, 537, 582, 371, - 545, 561, 361, 499, 533, 0, 0, 352, 566, 544, - 477, 351, 0, 526, 391, 408, 388, 497, 994, 0, - 1018, 1022, 387, 1107, 1016, 576, 354, 0, 575, 496, - 469, 562, 567, 478, 471, 0, 353, 564, 476, 470, - 446, 398, 1108, 447, 448, 449, 450, 451, 452, 412, - 512, 467, 513, 413, 484, 483, 485, 414, 415, 416, - 417, 418, 419, 420, 421, 422, 423, 0, 0, 0, - 0, 0, 606, 607, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 743, - 1013, 0, 748, 0, 578, 0, 0, 1090, 0, 0, - 0, 548, 0, 0, 453, 0, 0, 0, 1017, 0, - 529, 502, 1104, 0, 0, 527, 465, 563, 514, 569, - 551, 577, 521, 515, 344, 552, 390, 479, 362, 364, - 776, 392, 395, 399, 400, 490, 491, 508, 536, 555, - 556, 557, 389, 376, 528, 377, 409, 378, 345, 381, - 380, 382, 538, 383, 347, 509, 560, 0, 405, 524, - 474, 348, 473, 510, 559, 558, 363, 586, 593, 594, - 685, 0, 599, 790, 791, 792, 608, 0, 516, 359, - 356, 0, 0, 0, 385, 511, 372, 374, 375, 373, - 505, 507, 613, 614, 615, 617, 0, 618, 619, 0, - 0, 0, 0, 620, 686, 704, 670, 639, 601, 694, - 636, 640, 641, 426, 427, 428, 429, 707, 0, 0, - 0, 592, 454, 455, 0, 397, 396, 475, 349, 0, - 0, 443, 425, 517, 355, 393, 445, 431, 456, 457, - 458, 459, 460, 0, 461, 462, 403, 339, 340, 784, - 1087, 498, 709, 746, 747, 631, 0, 1103, 1082, 1084, - 1085, 1089, 1093, 1094, 1095, 1096, 1097, 1099, 1102, 1106, - 783, 0, 687, 701, 788, 700, 780, 504, 0, 535, - 698, 645, 0, 691, 664, 665, 0, 692, 660, 696, - 0, 633, 0, 602, 605, 635, 722, 723, 724, 346, - 604, 726, 727, 728, 729, 730, 731, 732, 725, 1105, - 668, 644, 671, 583, 647, 646, 0, 0, 682, 1021, - 683, 684, 486, 487, 488, 489, 1091, 710, 370, 603, - 519, 520, 0, 669, 0, 0, 0, 0, 0, 0, - 0, 0, 674, 675, 672, 793, 0, 733, 734, 0, - 0, 597, 598, 402, 0, 616, 410, 369, 503, 404, - 581, 434, 0, 609, 676, 610, 522, 523, 737, 742, - 738, 739, 741, 762, 493, 424, 430, 539, 444, 466, - 525, 580, 501, 530, 367, 570, 541, 472, 661, 689, - 1114, 1086, 1113, 1115, 1116, 1112, 1117, 1118, 1098, 975, - 0, 1028, 1029, 1110, 1109, 1111, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 718, 717, 716, - 715, 714, 713, 712, 711, 0, 0, 658, 384, 781, - 775, 782, 763, 766, 765, 740, 982, 341, 638, 464, - 518, 401, 705, 706, 0, 761, 1076, 1039, 1040, 1041, - 972, 1042, 1036, 1037, 973, 1038, 1077, 1026, 1073, 1074, - 1001, 1031, 1043, 1072, 1044, 1075, 1002, 1078, 1119, 1120, - 1050, 1034, 302, 1121, 1047, 1079, 1071, 1070, 1045, 1027, - 1080, 1081, 1009, 1004, 1048, 1049, 1035, 1056, 1057, 1058, - 1061, 974, 1062, 1063, 1064, 1065, 1066, 1060, 1059, 1023, - 1024, 1025, 1051, 1052, 1054, 1055, 1030, 549, 1005, 1006, - 1007, 1008, 0, 0, 587, 588, 589, 612, 0, 590, - 572, 637, 411, 342, 553, 579, 778, 779, 0, 0, - 0, 0, 0, 0, 0, 688, 699, 735, 736, 0, - 749, 750, 752, 754, 1067, 756, 546, 547, 764, 0, - 0, 435, 357, 358, 494, 495, 532, 0, 436, 437, - 438, 442, 439, 440, 441, 1053, 759, 760, 757, 468, - 531, 554, 540, 777, 481, 0, 785, 627, 628, 786, - 745, 744, 343, 0, 1032, 1033, 702, 703, 1019, 0, - 1100, 480, 634, 0, 967, 0, 0, 500, 0, 0, - 643, 677, 666, 755, 630, 0, 0, 0, 0, 0, - 0, 970, 0, 0, 0, 394, 5318, 0, 463, 681, - 662, 673, 663, 506, 648, 649, 650, 657, 406, 651, - 787, 653, 622, 654, 623, 655, 656, 1010, 680, 629, - 542, 482, 0, 697, 0, 0, 1092, 1101, 0, 0, - 0, 0, 0, 0, 0, 0, 1088, 0, 0, 0, - 0, 0, 961, 0, 0, 999, 1069, 1068, 986, 996, - 0, 0, 365, 269, 624, 751, 626, 625, 987, 0, - 988, 992, 995, 991, 989, 990, 0, 1083, 0, 0, - 0, 0, 0, 0, 953, 965, 0, 971, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 962, 963, 0, 0, 0, 0, 1020, - 0, 964, 0, 966, 0, 0, 0, 0, 543, 571, - 0, 584, 0, 432, 433, 1015, 993, 997, 0, 0, - 0, 0, 350, 550, 568, 366, 537, 582, 371, 545, - 561, 361, 499, 533, 0, 0, 352, 566, 544, 477, - 351, 0, 526, 391, 408, 388, 497, 994, 0, 1018, - 1022, 387, 1107, 1016, 576, 354, 0, 575, 496, 469, - 562, 567, 478, 471, 0, 353, 564, 476, 470, 446, - 398, 1108, 447, 448, 449, 450, 451, 452, 412, 512, - 467, 513, 413, 484, 483, 485, 414, 415, 416, 417, - 418, 419, 420, 421, 422, 423, 0, 0, 0, 0, - 0, 606, 607, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 743, 1013, - 0, 748, 0, 578, 0, 0, 1090, 0, 0, 0, - 548, 0, 0, 453, 0, 0, 0, 1017, 0, 529, - 502, 1104, 0, 0, 527, 465, 563, 514, 569, 551, - 577, 521, 515, 344, 552, 390, 479, 362, 364, 776, - 392, 395, 399, 400, 490, 491, 508, 536, 555, 556, - 557, 389, 376, 528, 377, 409, 378, 345, 381, 380, - 382, 538, 383, 347, 509, 560, 0, 405, 524, 474, - 348, 473, 510, 559, 558, 363, 586, 593, 594, 685, - 0, 599, 790, 791, 792, 608, 0, 516, 359, 356, - 0, 0, 0, 385, 511, 372, 374, 375, 373, 505, - 507, 613, 614, 615, 617, 0, 618, 619, 0, 0, - 0, 0, 620, 686, 704, 670, 639, 601, 694, 636, - 640, 641, 426, 427, 428, 429, 707, 0, 0, 0, - 592, 454, 455, 0, 397, 396, 475, 349, 0, 0, - 443, 425, 517, 355, 393, 445, 431, 456, 457, 458, - 459, 460, 0, 461, 462, 403, 339, 340, 784, 1087, - 498, 709, 746, 747, 631, 0, 1103, 1082, 1084, 1085, - 1089, 1093, 1094, 1095, 1096, 1097, 1099, 1102, 1106, 783, - 0, 687, 701, 788, 700, 780, 504, 0, 535, 698, - 645, 0, 691, 664, 665, 0, 692, 660, 696, 0, - 633, 0, 602, 605, 635, 722, 723, 724, 346, 604, - 726, 727, 728, 729, 730, 731, 732, 725, 1105, 668, - 644, 671, 583, 647, 646, 0, 0, 682, 1021, 683, - 684, 486, 487, 488, 489, 1091, 710, 370, 603, 519, - 520, 0, 669, 0, 0, 0, 0, 0, 0, 0, - 0, 674, 675, 672, 793, 0, 733, 734, 0, 0, - 597, 598, 402, 0, 616, 410, 369, 503, 404, 581, - 434, 0, 609, 676, 610, 522, 523, 737, 742, 738, - 739, 741, 762, 493, 424, 430, 539, 444, 466, 525, - 580, 501, 530, 367, 570, 541, 472, 661, 689, 1114, - 1086, 1113, 1115, 1116, 1112, 1117, 1118, 1098, 975, 0, - 1028, 1029, 1110, 1109, 1111, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 718, 717, 716, 715, - 714, 713, 712, 711, 0, 0, 658, 384, 781, 775, - 782, 763, 766, 765, 740, 982, 341, 638, 464, 518, - 401, 705, 706, 0, 761, 1076, 1039, 1040, 1041, 972, - 1042, 1036, 1037, 973, 1038, 1077, 1026, 1073, 1074, 1001, - 1031, 1043, 1072, 1044, 1075, 1002, 1078, 1119, 1120, 1050, - 1034, 302, 1121, 1047, 1079, 1071, 1070, 1045, 1027, 1080, - 1081, 1009, 1004, 1048, 1049, 1035, 1056, 1057, 1058, 1061, - 974, 1062, 1063, 1064, 1065, 1066, 1060, 1059, 1023, 1024, - 1025, 1051, 1052, 1054, 1055, 1030, 549, 1005, 1006, 1007, - 1008, 0, 0, 587, 588, 589, 612, 0, 590, 572, - 637, 411, 342, 553, 579, 778, 779, 0, 0, 0, - 0, 0, 0, 0, 688, 699, 735, 736, 0, 749, - 750, 752, 754, 1067, 756, 546, 547, 764, 0, 0, - 435, 357, 358, 494, 495, 532, 0, 436, 437, 438, - 442, 439, 440, 441, 1053, 759, 760, 757, 468, 531, - 554, 540, 777, 481, 0, 785, 627, 628, 786, 745, - 744, 343, 0, 1032, 1033, 702, 703, 1019, 0, 1100, - 480, 634, 0, 967, 0, 0, 500, 0, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 0, - 970, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 1010, 680, 629, 542, - 482, 0, 697, 0, 0, 1092, 1101, 0, 0, 0, - 0, 0, 0, 0, 0, 1088, 0, 0, 0, 0, - 0, 961, 0, 0, 999, 1069, 1068, 986, 996, 0, - 0, 365, 269, 624, 751, 626, 625, 987, 0, 988, - 992, 995, 991, 989, 990, 0, 1083, 0, 0, 0, - 0, 0, 0, 953, 965, 0, 971, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 962, 963, 0, 0, 0, 0, 1020, 0, - 964, 0, 966, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 1015, 993, 997, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 994, 0, 1018, 1022, - 387, 1107, 1016, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 1108, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 1013, 0, - 748, 0, 578, 0, 0, 1090, 0, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 1017, 0, 529, 502, - 1104, 5142, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 1087, 498, - 709, 746, 747, 631, 0, 1103, 1082, 1084, 1085, 1089, - 1093, 1094, 1095, 1096, 1097, 1099, 1102, 1106, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 1105, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 1021, 683, 684, - 486, 487, 488, 489, 1091, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 1114, 1086, - 1113, 1115, 1116, 1112, 1117, 1118, 1098, 975, 0, 1028, - 1029, 1110, 1109, 1111, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 982, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 1076, 1039, 1040, 1041, 972, 1042, - 1036, 1037, 973, 1038, 1077, 1026, 1073, 1074, 1001, 1031, - 1043, 1072, 1044, 1075, 1002, 1078, 1119, 1120, 1050, 1034, - 302, 1121, 1047, 1079, 1071, 1070, 1045, 1027, 1080, 1081, - 1009, 1004, 1048, 1049, 1035, 1056, 1057, 1058, 1061, 974, - 1062, 1063, 1064, 1065, 1066, 1060, 1059, 1023, 1024, 1025, - 1051, 1052, 1054, 1055, 1030, 549, 1005, 1006, 1007, 1008, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 1067, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 1053, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 744, - 343, 0, 1032, 1033, 702, 703, 1019, 0, 1100, 480, - 634, 0, 967, 0, 0, 500, 0, 0, 643, 677, - 666, 755, 630, 0, 0, 0, 0, 0, 0, 970, - 0, 0, 0, 394, 0, 0, 463, 681, 662, 673, - 663, 506, 648, 649, 650, 657, 406, 651, 787, 653, - 622, 654, 623, 655, 656, 1010, 680, 629, 542, 482, - 0, 697, 0, 0, 1092, 1101, 0, 0, 0, 0, - 0, 0, 0, 0, 1088, 0, 0, 0, 0, 0, - 961, 0, 0, 999, 1069, 1068, 986, 996, 0, 0, - 365, 269, 624, 751, 626, 625, 987, 0, 988, 992, - 995, 991, 989, 990, 0, 1083, 0, 0, 0, 0, - 0, 0, 953, 965, 0, 971, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 962, 963, 1917, 0, 0, 0, 1020, 0, 964, - 0, 966, 0, 0, 0, 0, 543, 571, 0, 584, - 0, 432, 433, 1015, 993, 997, 0, 0, 0, 0, - 350, 550, 568, 366, 537, 582, 371, 545, 561, 361, - 499, 533, 0, 0, 352, 566, 544, 477, 351, 0, - 526, 391, 408, 388, 497, 994, 0, 1018, 1022, 387, - 1107, 1016, 576, 354, 0, 575, 496, 469, 562, 567, - 478, 471, 0, 353, 564, 476, 470, 446, 398, 1108, - 447, 448, 449, 450, 451, 452, 412, 512, 467, 513, - 413, 484, 483, 485, 414, 415, 416, 417, 418, 419, - 420, 421, 422, 423, 0, 0, 0, 0, 0, 606, - 607, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 743, 1013, 0, 748, - 0, 578, 0, 0, 1090, 0, 0, 0, 548, 0, - 0, 453, 0, 0, 0, 1017, 0, 529, 502, 1104, - 0, 0, 527, 465, 563, 514, 569, 551, 577, 521, - 515, 344, 552, 390, 479, 362, 364, 776, 392, 395, - 399, 400, 490, 491, 508, 536, 555, 556, 557, 389, - 376, 528, 377, 409, 378, 345, 381, 380, 382, 538, - 383, 347, 509, 560, 0, 405, 524, 474, 348, 473, - 510, 559, 558, 363, 586, 593, 594, 685, 0, 599, - 790, 791, 792, 608, 0, 516, 359, 356, 0, 0, - 0, 385, 511, 372, 374, 375, 373, 505, 507, 613, - 614, 615, 617, 0, 618, 619, 0, 0, 0, 0, - 620, 686, 704, 670, 639, 601, 694, 636, 640, 641, - 426, 427, 428, 429, 707, 0, 0, 0, 592, 454, - 455, 0, 397, 396, 475, 349, 0, 0, 443, 425, - 517, 355, 393, 445, 431, 456, 457, 458, 459, 460, - 0, 461, 462, 403, 339, 340, 784, 1087, 498, 709, - 746, 747, 631, 0, 1103, 1082, 1084, 1085, 1089, 1093, - 1094, 1095, 1096, 1097, 1099, 1102, 1106, 783, 0, 687, - 701, 788, 700, 780, 504, 0, 535, 698, 645, 0, - 691, 664, 665, 0, 692, 660, 696, 0, 633, 0, - 602, 605, 635, 722, 723, 724, 346, 604, 726, 727, - 728, 729, 730, 731, 732, 725, 1105, 668, 644, 671, - 583, 647, 646, 0, 0, 682, 1021, 683, 684, 486, - 487, 488, 489, 1091, 710, 370, 603, 519, 520, 0, - 669, 0, 0, 0, 0, 0, 0, 0, 0, 674, - 675, 672, 793, 0, 733, 734, 0, 0, 597, 598, - 402, 0, 616, 410, 369, 503, 404, 581, 434, 0, - 609, 676, 610, 522, 523, 737, 742, 738, 739, 741, - 762, 493, 424, 430, 539, 444, 466, 525, 580, 501, - 530, 367, 570, 541, 472, 661, 689, 1114, 1086, 1113, - 1115, 1116, 1112, 1117, 1118, 1098, 975, 0, 1028, 1029, - 1110, 1109, 1111, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 718, 717, 716, 715, 714, 713, - 712, 711, 0, 0, 658, 384, 781, 775, 782, 763, - 766, 765, 740, 982, 341, 638, 464, 518, 401, 705, - 706, 0, 761, 1076, 1039, 1040, 1041, 972, 1042, 1036, - 1037, 973, 1038, 1077, 1026, 1073, 1074, 1001, 1031, 1043, - 1072, 1044, 1075, 1002, 1078, 1119, 1120, 1050, 1034, 302, - 1121, 1047, 1079, 1071, 1070, 1045, 1027, 1080, 1081, 1009, - 1004, 1048, 1049, 1035, 1056, 1057, 1058, 1061, 974, 1062, - 1063, 1064, 1065, 1066, 1060, 1059, 1023, 1024, 1025, 1051, - 1052, 1054, 1055, 1030, 549, 1005, 1006, 1007, 1008, 0, - 0, 587, 588, 589, 612, 0, 590, 572, 637, 411, - 342, 553, 579, 778, 779, 0, 0, 0, 0, 0, - 0, 0, 688, 699, 735, 736, 0, 749, 750, 752, - 754, 1067, 756, 546, 547, 764, 0, 0, 435, 357, - 358, 494, 495, 532, 0, 436, 437, 438, 442, 439, - 440, 441, 1053, 759, 760, 757, 468, 531, 554, 540, - 777, 481, 0, 785, 627, 628, 786, 745, 744, 343, - 0, 1032, 1033, 702, 703, 1019, 0, 1100, 480, 634, - 0, 967, 0, 0, 500, 0, 0, 643, 677, 666, - 755, 630, 0, 0, 0, 0, 0, 0, 970, 0, - 0, 0, 394, 2319, 0, 463, 681, 662, 673, 663, - 506, 648, 649, 650, 657, 406, 651, 787, 653, 622, - 654, 623, 655, 656, 1010, 680, 629, 542, 482, 0, - 697, 0, 0, 1092, 1101, 0, 0, 0, 0, 0, - 0, 0, 0, 1088, 0, 0, 0, 0, 0, 961, - 0, 0, 999, 1069, 1068, 986, 996, 0, 0, 365, - 269, 624, 751, 626, 625, 987, 0, 988, 992, 995, - 991, 989, 990, 0, 1083, 0, 0, 0, 0, 0, - 0, 953, 965, 0, 971, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 962, 963, 0, 0, 0, 0, 1020, 0, 964, 0, - 966, 0, 0, 0, 0, 543, 571, 0, 584, 0, - 432, 433, 1015, 993, 997, 0, 0, 0, 0, 350, - 550, 568, 366, 537, 582, 371, 545, 561, 361, 499, - 533, 0, 0, 352, 566, 544, 477, 351, 0, 526, - 391, 408, 388, 497, 994, 0, 1018, 1022, 387, 1107, - 1016, 576, 354, 0, 575, 496, 469, 562, 567, 478, - 471, 0, 353, 564, 476, 470, 446, 398, 1108, 447, - 448, 449, 450, 451, 452, 412, 512, 467, 513, 413, - 484, 483, 485, 414, 415, 416, 417, 418, 419, 420, - 421, 422, 423, 0, 0, 0, 0, 0, 606, 607, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 743, 1013, 0, 748, 0, - 578, 0, 0, 1090, 0, 0, 0, 548, 0, 0, - 453, 0, 0, 0, 1017, 0, 529, 502, 1104, 0, - 0, 527, 465, 563, 514, 569, 551, 577, 521, 515, - 344, 552, 390, 479, 362, 364, 776, 392, 395, 399, - 400, 490, 491, 508, 536, 555, 556, 557, 389, 376, - 528, 377, 409, 378, 345, 381, 380, 382, 538, 383, - 347, 509, 560, 0, 405, 524, 474, 348, 473, 510, - 559, 558, 363, 586, 593, 594, 685, 0, 599, 790, - 791, 792, 608, 0, 516, 359, 356, 0, 0, 0, - 385, 511, 372, 374, 375, 373, 505, 507, 613, 614, - 615, 617, 0, 618, 619, 0, 0, 0, 0, 620, - 686, 704, 670, 639, 601, 694, 636, 640, 641, 426, - 427, 428, 429, 707, 0, 0, 0, 592, 454, 455, - 0, 397, 396, 475, 349, 0, 0, 443, 425, 517, - 355, 393, 445, 431, 456, 457, 458, 459, 460, 0, - 461, 462, 403, 339, 340, 784, 1087, 498, 709, 746, - 747, 631, 0, 1103, 1082, 1084, 1085, 1089, 1093, 1094, - 1095, 1096, 1097, 1099, 1102, 1106, 783, 0, 687, 701, - 788, 700, 780, 504, 0, 535, 698, 645, 0, 691, - 664, 665, 0, 692, 660, 696, 0, 633, 0, 602, - 605, 635, 722, 723, 724, 346, 604, 726, 727, 728, - 729, 730, 731, 732, 725, 1105, 668, 644, 671, 583, - 647, 646, 0, 0, 682, 1021, 683, 684, 486, 487, - 488, 489, 1091, 710, 370, 603, 519, 520, 0, 669, - 0, 0, 0, 0, 0, 0, 0, 0, 674, 675, - 672, 793, 0, 733, 734, 0, 0, 597, 598, 402, - 0, 616, 410, 369, 503, 404, 581, 434, 0, 609, - 676, 610, 522, 523, 737, 742, 738, 739, 741, 762, - 493, 424, 430, 539, 444, 466, 525, 580, 501, 530, - 367, 570, 541, 472, 661, 689, 1114, 1086, 1113, 1115, - 1116, 1112, 1117, 1118, 1098, 975, 0, 1028, 1029, 1110, - 1109, 1111, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 718, 717, 716, 715, 714, 713, 712, - 711, 0, 0, 658, 384, 781, 775, 782, 763, 766, - 765, 740, 982, 341, 638, 464, 518, 401, 705, 706, - 0, 761, 1076, 1039, 1040, 1041, 972, 1042, 1036, 1037, - 973, 1038, 1077, 1026, 1073, 1074, 1001, 1031, 1043, 1072, - 1044, 1075, 1002, 1078, 1119, 1120, 1050, 1034, 302, 1121, - 1047, 1079, 1071, 1070, 1045, 1027, 1080, 1081, 1009, 1004, - 1048, 1049, 1035, 1056, 1057, 1058, 1061, 974, 1062, 1063, - 1064, 1065, 1066, 1060, 1059, 1023, 1024, 1025, 1051, 1052, - 1054, 1055, 1030, 549, 1005, 1006, 1007, 1008, 0, 0, - 587, 588, 589, 612, 0, 590, 572, 637, 411, 342, - 553, 579, 778, 779, 0, 0, 0, 0, 0, 0, - 0, 688, 699, 735, 736, 0, 749, 750, 752, 754, - 1067, 756, 546, 547, 764, 0, 0, 435, 357, 358, - 494, 495, 532, 0, 436, 437, 438, 442, 439, 440, - 441, 1053, 759, 760, 757, 468, 531, 554, 540, 777, - 481, 0, 785, 627, 628, 786, 745, 744, 343, 0, - 1032, 1033, 702, 703, 0, 0, 1100, 480, 634, 1019, - 967, 0, 2809, 0, 0, 0, 0, 0, 500, 0, - 0, 643, 677, 666, 755, 630, 0, 0, 0, 0, - 0, 0, 970, 0, 0, 0, 394, 0, 0, 463, - 681, 662, 673, 663, 506, 648, 649, 650, 657, 406, - 651, 787, 653, 622, 654, 623, 655, 656, 1010, 680, - 629, 542, 482, 0, 697, 0, 0, 1092, 1101, 0, - 0, 0, 0, 0, 0, 0, 0, 1088, 0, 0, - 0, 0, 0, 961, 0, 0, 999, 1069, 1068, 986, - 996, 0, 0, 365, 269, 624, 751, 626, 625, 987, - 0, 988, 992, 995, 991, 989, 990, 0, 1083, 0, - 0, 0, 0, 0, 0, 953, 965, 0, 971, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 962, 963, 0, 0, 0, 0, - 1020, 0, 964, 0, 966, 0, 0, 0, 0, 543, - 571, 0, 584, 0, 432, 433, 1015, 993, 997, 0, - 0, 0, 0, 350, 550, 568, 366, 537, 582, 371, - 545, 561, 361, 499, 533, 0, 0, 352, 566, 544, - 477, 351, 0, 526, 391, 408, 388, 497, 994, 0, - 1018, 1022, 387, 1107, 1016, 576, 354, 0, 575, 496, - 469, 562, 567, 478, 471, 0, 353, 564, 476, 470, - 446, 398, 1108, 447, 448, 449, 450, 451, 452, 412, - 512, 467, 513, 413, 484, 483, 485, 414, 415, 416, - 417, 418, 419, 420, 421, 422, 423, 0, 0, 0, - 0, 0, 606, 607, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 743, - 1013, 0, 748, 0, 578, 0, 0, 1090, 0, 0, - 0, 548, 0, 0, 453, 0, 0, 0, 1017, 0, - 529, 502, 1104, 0, 0, 527, 465, 563, 514, 569, - 551, 577, 521, 515, 344, 552, 390, 479, 362, 364, - 776, 392, 395, 399, 400, 490, 491, 508, 536, 555, - 556, 557, 389, 376, 528, 377, 409, 378, 345, 381, - 380, 382, 538, 383, 347, 509, 560, 0, 405, 524, - 474, 348, 473, 510, 559, 558, 363, 586, 593, 594, - 685, 0, 599, 790, 791, 792, 608, 0, 516, 359, - 356, 0, 0, 0, 385, 511, 372, 374, 375, 373, - 505, 507, 613, 614, 615, 617, 0, 618, 619, 0, - 0, 0, 0, 620, 686, 704, 670, 639, 601, 694, - 636, 640, 641, 426, 427, 428, 429, 707, 0, 0, - 0, 592, 454, 455, 0, 397, 396, 475, 349, 0, - 0, 443, 425, 517, 355, 393, 445, 431, 456, 457, - 458, 459, 460, 0, 461, 462, 403, 339, 340, 784, - 1087, 498, 709, 746, 747, 631, 0, 1103, 1082, 1084, - 1085, 1089, 1093, 1094, 1095, 1096, 1097, 1099, 1102, 1106, - 783, 0, 687, 701, 788, 700, 780, 504, 0, 535, - 698, 645, 0, 691, 664, 665, 0, 692, 660, 696, - 0, 633, 0, 602, 605, 635, 722, 723, 724, 346, - 604, 726, 727, 728, 729, 730, 731, 732, 725, 1105, - 668, 644, 671, 583, 647, 646, 0, 0, 682, 1021, - 683, 684, 486, 487, 488, 489, 1091, 710, 370, 603, - 519, 520, 0, 669, 0, 0, 0, 0, 0, 0, - 0, 0, 674, 675, 672, 793, 0, 733, 734, 0, - 0, 597, 598, 402, 0, 616, 410, 369, 503, 404, - 581, 434, 0, 609, 676, 610, 522, 523, 737, 742, - 738, 739, 741, 762, 493, 424, 430, 539, 444, 466, - 525, 580, 501, 530, 367, 570, 541, 472, 661, 689, - 1114, 1086, 1113, 1115, 1116, 1112, 1117, 1118, 1098, 975, - 0, 1028, 1029, 1110, 1109, 1111, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 718, 717, 716, - 715, 714, 713, 712, 711, 0, 0, 658, 384, 781, - 775, 782, 763, 766, 765, 740, 982, 341, 638, 464, - 518, 401, 705, 706, 0, 761, 1076, 1039, 1040, 1041, - 972, 1042, 1036, 1037, 973, 1038, 1077, 1026, 1073, 1074, - 1001, 1031, 1043, 1072, 1044, 1075, 1002, 1078, 1119, 1120, - 1050, 1034, 302, 1121, 1047, 1079, 1071, 1070, 1045, 1027, - 1080, 1081, 1009, 1004, 1048, 1049, 1035, 1056, 1057, 1058, - 1061, 974, 1062, 1063, 1064, 1065, 1066, 1060, 1059, 1023, - 1024, 1025, 1051, 1052, 1054, 1055, 1030, 549, 1005, 1006, - 1007, 1008, 0, 0, 587, 588, 589, 612, 0, 590, - 572, 637, 411, 342, 553, 579, 778, 779, 0, 0, - 0, 0, 0, 0, 0, 688, 699, 735, 736, 0, - 749, 750, 752, 754, 1067, 756, 546, 547, 764, 0, - 0, 435, 357, 358, 494, 495, 532, 0, 436, 437, - 438, 442, 439, 440, 441, 1053, 759, 760, 757, 468, - 531, 554, 540, 777, 481, 0, 785, 627, 628, 786, - 745, 744, 343, 0, 1032, 1033, 702, 703, 1019, 0, - 1100, 480, 634, 0, 967, 0, 0, 500, 0, 0, - 643, 677, 666, 755, 630, 0, 0, 0, 0, 0, - 0, 970, 0, 0, 0, 394, 0, 0, 463, 681, - 662, 673, 663, 506, 648, 649, 650, 657, 406, 651, - 787, 653, 622, 654, 623, 655, 656, 1010, 680, 629, - 542, 482, 0, 697, 0, 0, 1092, 1101, 0, 0, - 0, 0, 0, 0, 0, 0, 1088, 0, 0, 0, - 0, 0, 961, 0, 0, 999, 1069, 1068, 986, 996, - 0, 0, 365, 269, 624, 751, 626, 625, 987, 0, - 988, 992, 995, 991, 989, 990, 0, 1083, 0, 0, - 0, 0, 0, 0, 953, 965, 0, 971, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 962, 963, 2310, 0, 0, 0, 1020, - 0, 964, 0, 966, 0, 0, 0, 0, 543, 571, - 0, 584, 0, 432, 433, 1015, 993, 997, 0, 0, - 0, 0, 350, 550, 568, 366, 537, 582, 371, 545, - 561, 361, 499, 533, 0, 0, 352, 566, 544, 477, - 351, 0, 526, 391, 408, 388, 497, 994, 0, 1018, - 1022, 387, 1107, 1016, 576, 354, 0, 575, 496, 469, - 562, 567, 478, 471, 0, 353, 564, 476, 470, 446, - 398, 1108, 447, 448, 449, 450, 451, 452, 412, 512, - 467, 513, 413, 484, 483, 485, 414, 415, 416, 417, - 418, 419, 420, 421, 422, 423, 0, 0, 0, 0, - 0, 606, 607, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 743, 1013, - 0, 748, 0, 578, 0, 0, 1090, 0, 0, 0, - 548, 0, 0, 453, 0, 0, 0, 1017, 0, 529, - 502, 1104, 0, 0, 527, 465, 563, 514, 569, 551, - 577, 521, 515, 344, 552, 390, 479, 362, 364, 776, - 392, 395, 399, 400, 490, 491, 508, 536, 555, 556, - 557, 389, 376, 528, 377, 409, 378, 345, 381, 380, - 382, 538, 383, 347, 509, 560, 0, 405, 524, 474, - 348, 473, 510, 559, 558, 363, 586, 593, 594, 685, - 0, 599, 790, 791, 792, 608, 0, 516, 359, 356, - 0, 0, 0, 385, 511, 372, 374, 375, 373, 505, - 507, 613, 614, 615, 617, 0, 618, 619, 0, 0, - 0, 0, 620, 686, 704, 670, 639, 601, 694, 636, - 640, 641, 426, 427, 428, 429, 707, 0, 0, 0, - 592, 454, 455, 0, 397, 396, 475, 349, 0, 0, - 443, 425, 517, 355, 393, 445, 431, 456, 457, 458, - 459, 460, 0, 461, 462, 403, 339, 340, 784, 1087, - 498, 709, 746, 747, 631, 0, 1103, 1082, 1084, 1085, - 1089, 1093, 1094, 1095, 1096, 1097, 1099, 1102, 1106, 783, - 0, 687, 701, 788, 700, 780, 504, 0, 535, 698, - 645, 0, 691, 664, 665, 0, 692, 660, 696, 0, - 633, 0, 602, 605, 635, 722, 723, 724, 346, 604, - 726, 727, 728, 729, 730, 731, 732, 725, 1105, 668, - 644, 671, 583, 647, 646, 0, 0, 682, 1021, 683, - 684, 486, 487, 488, 489, 1091, 710, 370, 603, 519, - 520, 0, 669, 0, 0, 0, 0, 0, 0, 0, - 0, 674, 675, 672, 793, 0, 733, 734, 0, 0, - 597, 598, 402, 0, 616, 410, 369, 503, 404, 581, - 434, 0, 609, 676, 610, 522, 523, 737, 742, 738, - 739, 741, 762, 493, 424, 430, 539, 444, 466, 525, - 580, 501, 530, 367, 570, 541, 472, 661, 689, 1114, - 1086, 1113, 1115, 1116, 1112, 1117, 1118, 1098, 975, 0, - 1028, 1029, 1110, 1109, 1111, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 718, 717, 716, 715, - 714, 713, 712, 711, 0, 0, 658, 384, 781, 775, - 782, 763, 766, 765, 740, 982, 341, 638, 464, 518, - 401, 705, 706, 0, 761, 1076, 1039, 1040, 1041, 972, - 1042, 1036, 1037, 973, 1038, 1077, 1026, 1073, 1074, 1001, - 1031, 1043, 1072, 1044, 1075, 1002, 1078, 1119, 1120, 1050, - 1034, 302, 1121, 1047, 1079, 1071, 1070, 1045, 1027, 1080, - 1081, 1009, 1004, 1048, 1049, 1035, 1056, 1057, 1058, 1061, - 974, 1062, 1063, 1064, 1065, 1066, 1060, 1059, 1023, 1024, - 1025, 1051, 1052, 1054, 1055, 1030, 549, 1005, 1006, 1007, - 1008, 0, 0, 587, 588, 589, 612, 0, 590, 572, - 637, 411, 342, 553, 579, 778, 779, 0, 0, 0, - 0, 0, 0, 0, 688, 699, 735, 736, 0, 749, - 750, 752, 754, 1067, 756, 546, 547, 764, 0, 0, - 435, 357, 358, 494, 495, 532, 0, 436, 437, 438, - 442, 439, 440, 441, 1053, 759, 760, 757, 468, 531, - 554, 540, 777, 481, 0, 785, 627, 628, 786, 745, - 744, 343, 0, 1032, 1033, 702, 703, 1019, 0, 1100, - 480, 634, 0, 967, 0, 0, 500, 0, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 0, - 970, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 1010, 680, 629, 542, - 482, 0, 697, 0, 0, 1092, 1101, 0, 0, 0, - 0, 0, 0, 0, 0, 1088, 0, 0, 0, 0, - 0, 961, 0, 0, 999, 1069, 1068, 986, 996, 0, - 0, 365, 269, 624, 751, 626, 625, 987, 0, 988, - 992, 995, 991, 989, 990, 0, 1083, 0, 0, 0, - 0, 0, 0, 953, 965, 0, 971, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 962, 963, 0, 0, 0, 0, 1020, 0, - 964, 0, 966, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 1015, 993, 997, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 994, 0, 1018, 1022, - 387, 1107, 1016, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 1108, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 1013, 0, - 748, 0, 578, 0, 0, 1090, 0, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 1017, 0, 529, 502, - 1104, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 1087, 498, - 709, 746, 747, 631, 0, 1103, 1082, 1084, 1085, 1089, - 1093, 1094, 1095, 1096, 1097, 1099, 1102, 1106, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 1105, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 1021, 683, 684, - 486, 487, 488, 489, 1091, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 1114, 1086, - 1113, 1115, 1116, 1112, 1117, 1118, 1098, 975, 0, 1028, - 1029, 1110, 1109, 1111, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 982, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 1076, 1039, 1040, 1041, 972, 1042, - 1036, 1037, 973, 1038, 1077, 1026, 1073, 1074, 1001, 1031, - 1043, 1072, 1044, 1075, 1002, 1078, 1119, 1120, 1050, 1034, - 302, 1121, 1047, 1079, 1071, 1070, 1045, 1027, 1080, 1081, - 1009, 1004, 1048, 1049, 1035, 1056, 1057, 1058, 1061, 974, - 1062, 1063, 1064, 1065, 1066, 1060, 1059, 1023, 1024, 1025, - 1051, 1052, 1054, 1055, 1030, 549, 1005, 1006, 1007, 1008, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 1067, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 1053, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 744, - 343, 0, 1032, 1033, 702, 703, 1019, 0, 1100, 480, - 634, 0, 967, 0, 0, 500, 0, 0, 643, 677, - 666, 755, 630, 0, 0, 0, 0, 0, 0, 970, - 0, 0, 0, 394, 0, 0, 463, 681, 662, 673, - 663, 506, 648, 649, 650, 657, 406, 651, 787, 653, - 622, 654, 623, 655, 656, 1010, 680, 629, 542, 482, - 0, 697, 0, 0, 1092, 1101, 0, 0, 0, 0, - 0, 0, 0, 0, 1088, 0, 0, 0, 0, 0, - 961, 0, 0, 999, 1069, 1068, 986, 996, 0, 0, - 365, 269, 624, 751, 626, 625, 987, 0, 988, 992, - 995, 991, 989, 990, 0, 1083, 0, 0, 0, 0, - 0, 0, 953, 965, 0, 971, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 962, 963, 0, 0, 0, 0, 1020, 0, 964, - 0, 966, 0, 0, 0, 0, 543, 571, 0, 584, - 0, 432, 433, 1015, 993, 997, 0, 0, 0, 0, - 350, 550, 568, 366, 537, 582, 371, 545, 561, 361, - 499, 533, 0, 0, 352, 566, 544, 477, 351, 0, - 526, 391, 408, 388, 497, 994, 0, 1018, 1022, 387, - 1107, 1016, 576, 354, 0, 575, 496, 469, 562, 567, - 478, 471, 0, 353, 564, 476, 470, 446, 398, 1108, - 447, 448, 449, 450, 451, 452, 412, 512, 467, 513, - 413, 484, 483, 485, 414, 415, 416, 417, 418, 419, - 420, 421, 422, 423, 0, 0, 0, 0, 0, 606, - 607, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 743, 1013, 0, 748, - 0, 578, 0, 0, 1090, 0, 0, 0, 548, 0, - 0, 453, 0, 0, 0, 1017, 0, 529, 502, 1104, - 0, 0, 527, 465, 563, 514, 569, 551, 577, 521, - 515, 344, 552, 390, 479, 362, 364, 776, 392, 395, - 399, 400, 490, 491, 508, 536, 555, 556, 557, 389, - 376, 528, 377, 409, 378, 345, 381, 380, 382, 538, - 383, 347, 509, 560, 0, 405, 524, 474, 348, 473, - 510, 559, 558, 363, 586, 593, 594, 685, 0, 599, - 790, 791, 792, 608, 0, 516, 359, 356, 0, 0, - 0, 385, 511, 372, 374, 375, 373, 505, 507, 613, - 614, 615, 617, 0, 618, 619, 0, 0, 0, 0, - 620, 686, 704, 670, 639, 601, 694, 636, 640, 641, - 426, 427, 428, 429, 707, 0, 0, 0, 592, 454, - 455, 0, 397, 396, 475, 349, 0, 0, 443, 425, - 517, 355, 393, 445, 431, 456, 457, 458, 459, 460, - 0, 461, 462, 403, 339, 340, 784, 1087, 498, 709, - 746, 747, 631, 0, 1103, 1082, 1084, 1085, 1089, 1093, - 1094, 1095, 1096, 1097, 1099, 1102, 1106, 783, 0, 687, - 701, 788, 700, 780, 504, 0, 535, 698, 645, 0, - 691, 664, 665, 0, 692, 660, 696, 0, 633, 0, - 602, 605, 635, 722, 723, 724, 346, 604, 726, 727, - 728, 729, 730, 731, 732, 725, 1105, 668, 644, 671, - 583, 647, 646, 0, 0, 682, 1021, 683, 684, 486, - 487, 488, 489, 1091, 710, 370, 603, 519, 520, 0, - 669, 0, 0, 0, 0, 0, 0, 0, 0, 674, - 675, 672, 793, 0, 733, 734, 0, 0, 597, 598, - 402, 0, 616, 410, 369, 503, 404, 581, 434, 0, - 609, 676, 610, 522, 523, 737, 742, 738, 739, 741, - 762, 493, 424, 430, 539, 444, 466, 525, 580, 501, - 530, 367, 570, 541, 472, 661, 689, 1114, 1086, 1113, - 1115, 1116, 1112, 1117, 1118, 1098, 975, 0, 1028, 1029, - 1110, 1109, 1111, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 718, 717, 716, 715, 714, 713, - 712, 711, 0, 0, 658, 384, 781, 775, 782, 763, - 766, 765, 740, 982, 341, 638, 464, 518, 401, 705, - 706, 0, 761, 1076, 1039, 1040, 1041, 972, 1042, 1036, - 1037, 973, 1038, 1077, 1026, 1073, 1074, 1001, 1031, 1043, - 1072, 1044, 1075, 1002, 1078, 1119, 1120, 1050, 1034, 302, - 1121, 1047, 1079, 1071, 1070, 1045, 1027, 1080, 1081, 1009, - 1004, 1048, 1049, 1035, 1056, 1057, 1058, 1061, 974, 1062, - 1063, 1064, 1065, 1066, 1060, 1059, 1023, 1024, 1025, 1051, - 1052, 1054, 1055, 1030, 549, 1005, 1006, 1007, 1008, 0, - 0, 587, 588, 589, 612, 0, 590, 572, 637, 411, - 342, 553, 579, 778, 779, 0, 0, 0, 0, 0, - 0, 0, 688, 699, 735, 736, 0, 749, 750, 752, - 754, 1067, 756, 546, 547, 764, 0, 0, 435, 357, - 358, 494, 495, 532, 0, 436, 437, 438, 442, 439, - 440, 441, 4753, 759, 4754, 4755, 468, 531, 554, 540, - 777, 481, 0, 785, 627, 628, 786, 745, 744, 343, - 0, 1032, 1033, 702, 703, 1019, 0, 1100, 480, 634, - 0, 967, 0, 0, 500, 0, 0, 643, 677, 666, - 755, 630, 0, 0, 0, 0, 0, 0, 970, 0, - 0, 0, 394, 0, 0, 463, 681, 662, 673, 663, - 506, 648, 649, 650, 657, 406, 651, 787, 653, 622, - 654, 623, 655, 656, 1010, 680, 629, 542, 482, 0, - 697, 0, 0, 1092, 1101, 0, 0, 0, 0, 0, - 0, 0, 0, 1088, 0, 0, 0, 0, 0, 961, - 0, 0, 999, 1069, 1068, 986, 996, 0, 0, 365, - 269, 624, 751, 626, 625, 3375, 0, 3376, 992, 995, - 991, 989, 990, 0, 1083, 0, 0, 0, 0, 0, - 0, 953, 965, 0, 971, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 962, 963, 0, 0, 0, 0, 1020, 0, 964, 0, - 966, 0, 0, 0, 0, 543, 571, 0, 584, 0, - 432, 433, 1015, 993, 997, 0, 0, 0, 0, 350, - 550, 568, 366, 537, 582, 371, 545, 561, 361, 499, - 533, 0, 0, 352, 566, 544, 477, 351, 0, 526, - 391, 408, 388, 497, 994, 0, 1018, 1022, 387, 1107, - 1016, 576, 354, 0, 575, 496, 469, 562, 567, 478, - 471, 0, 353, 564, 476, 470, 446, 398, 1108, 447, - 448, 449, 450, 451, 452, 412, 512, 467, 513, 413, - 484, 483, 485, 414, 415, 416, 417, 418, 419, 420, - 421, 422, 423, 0, 0, 0, 0, 0, 606, 607, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 743, 1013, 0, 748, 0, - 578, 0, 0, 1090, 0, 0, 0, 548, 0, 0, - 453, 0, 0, 0, 1017, 0, 529, 502, 1104, 0, - 0, 527, 465, 563, 514, 569, 551, 577, 521, 515, - 344, 552, 390, 479, 362, 364, 776, 392, 395, 399, - 400, 490, 491, 508, 536, 555, 556, 557, 389, 376, - 528, 377, 409, 378, 345, 381, 380, 382, 538, 383, - 347, 509, 560, 0, 405, 524, 474, 348, 473, 510, - 559, 558, 363, 586, 593, 594, 685, 0, 599, 790, - 791, 792, 608, 0, 516, 359, 356, 0, 0, 0, - 385, 511, 372, 374, 375, 373, 505, 507, 613, 614, - 615, 617, 0, 618, 619, 0, 0, 0, 0, 620, - 686, 704, 670, 639, 601, 694, 636, 640, 641, 426, - 427, 428, 429, 707, 0, 0, 0, 592, 454, 455, - 0, 397, 396, 475, 349, 0, 0, 443, 425, 517, - 355, 393, 445, 431, 456, 457, 458, 459, 460, 0, - 461, 462, 403, 339, 340, 784, 1087, 498, 709, 746, - 747, 631, 0, 1103, 1082, 1084, 1085, 1089, 1093, 1094, - 1095, 1096, 1097, 1099, 1102, 1106, 783, 0, 687, 701, - 788, 700, 780, 504, 0, 535, 698, 645, 0, 691, - 664, 665, 0, 692, 660, 696, 0, 633, 0, 602, - 605, 635, 722, 723, 724, 346, 604, 726, 727, 728, - 729, 730, 731, 732, 725, 1105, 668, 644, 671, 583, - 647, 646, 0, 0, 682, 1021, 683, 684, 486, 487, - 488, 489, 1091, 710, 370, 603, 519, 520, 0, 669, - 0, 0, 0, 0, 0, 0, 0, 0, 674, 675, - 672, 793, 0, 733, 734, 0, 0, 597, 598, 402, - 0, 616, 410, 369, 503, 404, 581, 434, 0, 609, - 676, 610, 522, 523, 737, 742, 738, 739, 741, 762, - 493, 424, 430, 539, 444, 466, 525, 580, 501, 530, - 367, 570, 541, 472, 661, 689, 1114, 1086, 1113, 1115, - 1116, 1112, 1117, 1118, 1098, 975, 0, 1028, 1029, 1110, - 1109, 1111, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 718, 717, 716, 715, 714, 713, 712, - 711, 0, 0, 658, 384, 781, 775, 782, 763, 766, - 765, 740, 982, 341, 638, 464, 518, 401, 705, 706, - 0, 761, 1076, 1039, 1040, 1041, 972, 1042, 1036, 1037, - 973, 1038, 1077, 1026, 1073, 1074, 1001, 1031, 1043, 1072, - 1044, 1075, 1002, 1078, 1119, 1120, 1050, 1034, 302, 1121, - 1047, 1079, 1071, 1070, 1045, 1027, 1080, 1081, 1009, 1004, - 1048, 1049, 1035, 1056, 1057, 1058, 1061, 974, 1062, 1063, - 1064, 1065, 1066, 1060, 1059, 1023, 1024, 1025, 1051, 1052, - 1054, 1055, 1030, 549, 1005, 1006, 1007, 1008, 0, 0, - 587, 588, 589, 612, 0, 590, 572, 637, 411, 342, - 553, 579, 778, 779, 0, 0, 0, 0, 0, 0, - 0, 688, 699, 735, 736, 0, 749, 750, 752, 754, - 1067, 756, 546, 547, 764, 0, 0, 435, 357, 358, - 494, 495, 532, 0, 436, 437, 438, 442, 439, 440, - 441, 1053, 759, 760, 757, 468, 531, 554, 540, 777, - 481, 0, 785, 627, 628, 786, 745, 744, 343, 0, - 1032, 1033, 702, 703, 1019, 0, 1100, 480, 634, 0, - 967, 0, 0, 500, 0, 0, 643, 677, 666, 755, - 630, 0, 0, 2140, 0, 0, 0, 970, 0, 0, - 0, 394, 0, 0, 463, 681, 662, 673, 663, 506, - 648, 649, 650, 657, 406, 651, 787, 653, 622, 654, - 623, 655, 656, 1010, 680, 629, 542, 482, 0, 697, - 0, 0, 1092, 1101, 0, 0, 0, 0, 0, 0, - 0, 0, 1088, 0, 0, 0, 0, 0, 961, 0, - 0, 999, 1069, 1068, 986, 996, 0, 0, 365, 269, - 624, 751, 626, 625, 987, 0, 988, 992, 995, 991, - 989, 990, 0, 1083, 0, 0, 0, 0, 0, 0, - 0, 965, 0, 971, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 962, - 963, 0, 0, 0, 0, 1020, 0, 964, 0, 966, - 0, 0, 0, 0, 543, 571, 0, 584, 0, 432, - 433, 1015, 993, 997, 0, 0, 0, 0, 350, 550, - 568, 366, 537, 582, 371, 545, 561, 361, 499, 533, - 0, 0, 352, 566, 544, 477, 351, 0, 526, 391, - 408, 388, 497, 994, 0, 1018, 1022, 387, 1107, 1016, - 576, 354, 0, 575, 496, 469, 562, 567, 478, 471, - 0, 353, 564, 476, 470, 446, 398, 1108, 447, 448, - 449, 450, 451, 452, 412, 512, 467, 513, 413, 484, - 483, 485, 414, 415, 416, 417, 418, 419, 420, 421, - 422, 423, 0, 0, 0, 0, 0, 606, 607, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 743, 1013, 0, 748, 0, 578, - 0, 0, 1090, 0, 0, 0, 548, 0, 0, 453, - 0, 0, 0, 1017, 0, 529, 502, 1104, 0, 0, - 527, 465, 563, 514, 569, 551, 577, 521, 515, 344, - 552, 390, 479, 362, 364, 776, 392, 395, 399, 400, - 490, 491, 508, 536, 555, 556, 557, 389, 376, 528, - 377, 409, 378, 345, 381, 380, 382, 538, 383, 347, - 509, 560, 0, 405, 524, 474, 348, 473, 510, 559, - 558, 363, 586, 2141, 2142, 685, 0, 599, 790, 791, - 792, 608, 0, 516, 359, 356, 0, 0, 0, 385, - 511, 372, 374, 375, 373, 505, 507, 613, 614, 615, - 617, 0, 618, 619, 0, 0, 0, 0, 620, 686, - 704, 670, 639, 601, 694, 636, 640, 641, 426, 427, - 428, 429, 707, 0, 0, 0, 592, 454, 455, 0, - 397, 396, 475, 349, 0, 0, 443, 425, 517, 355, - 393, 445, 431, 456, 457, 458, 459, 460, 0, 461, - 462, 403, 339, 340, 784, 1087, 498, 709, 746, 747, - 631, 0, 1103, 1082, 1084, 1085, 1089, 1093, 1094, 1095, - 1096, 1097, 1099, 1102, 1106, 783, 0, 687, 701, 788, - 700, 780, 504, 0, 535, 698, 645, 0, 691, 664, - 665, 0, 692, 660, 696, 0, 633, 0, 602, 605, - 635, 722, 723, 724, 346, 604, 726, 727, 728, 729, - 730, 731, 732, 725, 1105, 668, 644, 671, 583, 647, - 646, 0, 0, 682, 1021, 683, 684, 486, 487, 488, - 489, 1091, 710, 370, 603, 519, 520, 0, 669, 0, - 0, 0, 0, 0, 0, 0, 0, 674, 675, 672, - 793, 0, 733, 734, 0, 0, 597, 598, 402, 0, - 616, 410, 369, 503, 404, 581, 434, 0, 609, 676, - 610, 522, 523, 737, 742, 738, 739, 741, 762, 493, - 424, 430, 539, 444, 466, 525, 580, 501, 530, 367, - 570, 541, 472, 661, 689, 1114, 1086, 1113, 1115, 1116, - 1112, 1117, 1118, 1098, 975, 0, 1028, 1029, 1110, 1109, - 1111, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 718, 717, 716, 715, 714, 713, 712, 711, - 0, 0, 658, 384, 781, 775, 782, 763, 766, 765, - 740, 982, 341, 638, 464, 518, 401, 705, 706, 0, - 761, 1076, 1039, 1040, 1041, 972, 1042, 1036, 1037, 973, - 1038, 1077, 1026, 1073, 1074, 1001, 1031, 1043, 1072, 1044, - 1075, 1002, 1078, 1119, 1120, 1050, 1034, 302, 1121, 1047, - 1079, 1071, 1070, 1045, 1027, 1080, 1081, 1009, 1004, 1048, - 1049, 1035, 1056, 1057, 1058, 1061, 974, 1062, 1063, 1064, - 1065, 1066, 1060, 1059, 1023, 1024, 1025, 1051, 1052, 1054, - 1055, 1030, 549, 1005, 1006, 1007, 1008, 0, 0, 587, - 588, 589, 612, 0, 590, 572, 637, 411, 342, 553, - 579, 778, 779, 0, 0, 0, 0, 0, 0, 0, - 688, 699, 735, 736, 0, 749, 750, 752, 754, 1067, - 756, 546, 547, 764, 0, 0, 435, 357, 358, 494, - 495, 532, 0, 436, 437, 438, 442, 439, 440, 441, - 1053, 759, 760, 757, 468, 531, 554, 540, 777, 481, - 0, 785, 627, 628, 786, 745, 744, 343, 0, 1032, - 1033, 702, 703, 1019, 0, 1100, 480, 634, 0, 967, - 0, 0, 500, 0, 0, 643, 677, 666, 755, 630, - 0, 0, 0, 0, 0, 0, 970, 0, 0, 0, - 394, 0, 0, 463, 681, 662, 673, 663, 506, 648, - 649, 650, 657, 406, 651, 787, 653, 622, 654, 623, - 655, 656, 1010, 680, 629, 542, 482, 0, 697, 0, - 0, 1092, 1101, 0, 0, 0, 0, 0, 0, 0, - 0, 1088, 0, 0, 0, 0, 0, 1623, 0, 0, - 999, 1069, 1068, 986, 996, 0, 0, 365, 269, 624, - 751, 626, 625, 987, 0, 988, 992, 995, 991, 989, - 990, 0, 1083, 0, 0, 0, 0, 0, 0, 953, - 965, 0, 971, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 962, 963, - 0, 0, 0, 0, 1020, 0, 964, 0, 966, 0, - 0, 0, 0, 543, 571, 0, 584, 0, 432, 433, - 1015, 993, 997, 0, 0, 0, 0, 350, 550, 568, - 366, 537, 582, 371, 545, 561, 361, 499, 533, 0, - 0, 352, 566, 544, 477, 351, 0, 526, 391, 408, - 388, 497, 994, 0, 1018, 1022, 387, 1107, 1016, 576, - 354, 0, 575, 496, 469, 562, 567, 478, 471, 0, - 353, 564, 476, 470, 446, 398, 1108, 447, 448, 449, - 450, 451, 452, 412, 512, 467, 513, 413, 484, 483, - 485, 414, 415, 416, 417, 418, 419, 420, 421, 422, - 423, 0, 0, 0, 0, 0, 606, 607, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 743, 1013, 0, 748, 0, 578, 0, - 0, 1090, 0, 0, 0, 548, 0, 0, 453, 0, - 0, 0, 1017, 0, 529, 502, 1104, 0, 0, 527, - 465, 563, 514, 569, 551, 577, 521, 515, 344, 552, - 390, 479, 362, 364, 776, 392, 395, 399, 400, 490, - 491, 508, 536, 555, 556, 557, 389, 376, 528, 377, - 409, 378, 345, 381, 380, 382, 538, 383, 347, 509, - 560, 0, 405, 524, 474, 348, 473, 510, 559, 558, - 363, 586, 593, 594, 685, 0, 599, 790, 791, 792, - 608, 0, 516, 359, 356, 0, 0, 0, 385, 511, - 372, 374, 375, 373, 505, 507, 613, 614, 615, 617, - 0, 618, 619, 0, 0, 0, 0, 620, 686, 704, - 670, 639, 601, 694, 636, 640, 641, 426, 427, 428, - 429, 707, 0, 0, 0, 592, 454, 455, 0, 397, - 396, 475, 349, 0, 0, 443, 425, 517, 355, 393, - 445, 431, 456, 457, 458, 459, 460, 0, 461, 462, - 403, 339, 340, 784, 1087, 498, 709, 746, 747, 631, - 0, 1103, 1082, 1084, 1085, 1089, 1093, 1094, 1095, 1096, - 1097, 1099, 1102, 1106, 783, 0, 687, 701, 788, 700, - 780, 504, 0, 535, 698, 645, 0, 691, 664, 665, - 0, 692, 660, 696, 0, 633, 0, 602, 605, 635, - 722, 723, 724, 346, 604, 726, 727, 728, 729, 730, - 731, 732, 725, 1105, 668, 644, 671, 583, 647, 646, - 0, 0, 682, 1021, 683, 684, 486, 487, 488, 489, - 1091, 710, 370, 603, 519, 520, 0, 669, 0, 0, - 0, 0, 0, 0, 0, 0, 674, 675, 672, 793, - 0, 733, 734, 0, 0, 597, 598, 402, 0, 616, - 410, 369, 503, 404, 581, 434, 0, 609, 676, 610, - 522, 523, 737, 742, 738, 739, 741, 762, 493, 424, - 430, 539, 444, 466, 525, 580, 501, 530, 367, 570, - 541, 472, 661, 689, 1114, 1086, 1113, 1115, 1116, 1112, - 1117, 1118, 1098, 975, 0, 1028, 1029, 1110, 1109, 1111, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 718, 717, 716, 715, 714, 713, 712, 711, 0, - 0, 658, 384, 781, 775, 782, 763, 766, 765, 740, - 982, 341, 638, 464, 518, 401, 705, 706, 0, 761, - 1076, 1039, 1040, 1041, 972, 1042, 1036, 1037, 973, 1038, - 1077, 1026, 1073, 1074, 1001, 1031, 1043, 1072, 1044, 1075, - 1002, 1078, 1119, 1120, 1050, 1034, 302, 1121, 1047, 1079, - 1071, 1070, 1045, 1027, 1080, 1081, 1009, 1004, 1048, 1049, - 1035, 1056, 1057, 1058, 1061, 974, 1062, 1063, 1064, 1065, - 1066, 1060, 1059, 1023, 1024, 1025, 1051, 1052, 1054, 1055, - 1030, 549, 1005, 1006, 1007, 1008, 0, 0, 587, 588, - 589, 612, 0, 590, 572, 637, 411, 342, 553, 579, - 778, 779, 0, 0, 0, 0, 0, 0, 0, 688, - 699, 735, 736, 0, 749, 750, 752, 754, 1067, 756, - 546, 547, 764, 0, 0, 435, 357, 358, 494, 495, - 532, 0, 436, 437, 438, 442, 439, 440, 441, 1053, - 759, 760, 757, 468, 531, 554, 540, 777, 481, 0, - 785, 627, 628, 786, 745, 744, 343, 0, 1032, 1033, - 702, 703, 1019, 0, 1100, 480, 634, 0, 967, 0, - 0, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 0, 0, 0, 0, 970, 0, 0, 0, 394, - 0, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 1010, 680, 629, 542, 482, 0, 697, 0, 0, - 1092, 1101, 0, 0, 0, 0, 0, 0, 0, 0, - 1088, 0, 0, 0, 0, 0, 961, 0, 0, 999, - 1069, 1068, 986, 996, 0, 0, 365, 269, 624, 751, - 626, 625, 987, 0, 988, 992, 995, 991, 989, 990, - 0, 1083, 0, 0, 0, 0, 0, 0, 0, 965, - 0, 971, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 962, 963, 0, - 0, 0, 0, 1020, 0, 964, 0, 966, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 1015, - 993, 997, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 994, 0, 1018, 1022, 387, 1107, 1016, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 1108, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 1013, 0, 748, 0, 578, 0, 0, - 1090, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 1017, 0, 529, 502, 1104, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 1087, 498, 709, 746, 747, 631, 0, - 1103, 1082, 1084, 1085, 1089, 1093, 1094, 1095, 1096, 1097, - 1099, 1102, 1106, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 1105, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 1021, 683, 684, 486, 487, 488, 489, 1091, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 1114, 1086, 1113, 1115, 1116, 1112, 1117, - 1118, 1098, 975, 0, 1028, 1029, 1110, 1109, 1111, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 982, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 1076, - 1039, 1040, 1041, 972, 1042, 1036, 1037, 973, 1038, 1077, - 1026, 1073, 1074, 1001, 1031, 1043, 1072, 1044, 1075, 1002, - 1078, 1119, 1120, 1050, 1034, 302, 1121, 1047, 1079, 1071, - 1070, 1045, 1027, 1080, 1081, 1009, 1004, 1048, 1049, 1035, - 1056, 1057, 1058, 1061, 974, 1062, 1063, 1064, 1065, 1066, - 1060, 1059, 1023, 1024, 1025, 1051, 1052, 1054, 1055, 1030, - 549, 1005, 1006, 1007, 1008, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 1067, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 1053, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 1032, 1033, 702, - 703, 0, 0, 1100, 480, 634, 0, 967, 200, 245, - 199, 232, 201, 0, 0, 0, 0, 0, 0, 500, - 0, 0, 643, 677, 666, 755, 630, 0, 233, 0, - 0, 0, 0, 0, 0, 225, 0, 394, 0, 234, - 463, 681, 662, 673, 663, 506, 648, 649, 650, 657, - 406, 651, 652, 653, 622, 654, 623, 655, 656, 169, - 680, 629, 542, 482, 0, 697, 0, 0, 0, 0, - 0, 0, 0, 0, 154, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 238, 0, 0, 268, 0, 0, - 0, 0, 0, 0, 365, 269, 624, 751, 626, 625, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 368, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 260, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 543, 571, 0, 584, 0, 432, 433, 0, 0, 0, - 0, 0, 0, 0, 350, 550, 568, 366, 537, 582, - 371, 545, 561, 361, 499, 533, 0, 0, 352, 566, - 544, 477, 351, 0, 526, 391, 408, 388, 497, 0, - 0, 565, 595, 387, 585, 0, 576, 354, 0, 575, - 496, 469, 562, 567, 478, 471, 0, 353, 564, 476, - 470, 446, 398, 611, 447, 448, 449, 450, 451, 452, - 412, 512, 467, 513, 413, 484, 483, 485, 414, 415, - 416, 417, 418, 419, 420, 421, 422, 423, 0, 0, - 0, 0, 0, 606, 607, 0, 0, 0, 0, 0, - 0, 0, 198, 230, 242, 231, 84, 150, 0, 0, - 743, 0, 246, 748, 0, 578, 0, 0, 261, 0, - 0, 0, 548, 0, 0, 453, 152, 224, 223, 596, - 0, 529, 502, 274, 0, 0, 527, 465, 563, 514, - 569, 551, 577, 521, 515, 344, 552, 390, 479, 362, - 364, 283, 392, 395, 399, 400, 490, 491, 508, 536, - 555, 556, 557, 389, 376, 528, 377, 409, 378, 345, - 381, 380, 382, 538, 383, 347, 509, 560, 151, 405, - 524, 474, 348, 473, 510, 559, 558, 363, 586, 593, - 594, 685, 0, 599, 719, 720, 721, 608, 0, 516, - 359, 356, 0, 0, 0, 385, 511, 372, 374, 375, - 373, 505, 507, 613, 614, 615, 617, 0, 618, 619, - 0, 0, 0, 0, 620, 686, 704, 670, 639, 601, - 694, 636, 640, 641, 426, 427, 428, 429, 707, 0, - 0, 0, 592, 454, 455, 0, 397, 396, 475, 349, - 0, 0, 443, 425, 517, 355, 393, 445, 431, 456, - 457, 458, 459, 460, 0, 461, 462, 403, 339, 340, - 573, 386, 498, 709, 746, 747, 631, 0, 695, 632, - 642, 379, 667, 679, 678, 492, 591, 264, 690, 693, - 621, 275, 0, 687, 701, 659, 700, 276, 504, 0, - 535, 698, 645, 0, 691, 664, 665, 0, 692, 660, - 696, 0, 633, 0, 602, 605, 635, 722, 723, 724, - 346, 604, 726, 727, 728, 729, 730, 731, 732, 725, - 574, 668, 644, 671, 583, 647, 646, 0, 0, 682, - 600, 683, 684, 486, 487, 488, 489, 407, 710, 370, - 603, 519, 520, 166, 669, 0, 0, 0, 0, 0, - 0, 0, 0, 674, 675, 672, 273, 0, 733, 734, - 0, 0, 597, 598, 402, 0, 616, 410, 369, 503, - 404, 581, 434, 0, 609, 676, 610, 522, 523, 737, - 742, 738, 739, 741, 762, 493, 424, 430, 539, 444, - 466, 525, 580, 501, 530, 367, 570, 541, 472, 661, - 689, 0, 0, 0, 0, 0, 0, 0, 0, 79, - 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 718, 717, - 716, 715, 714, 713, 712, 711, 0, 0, 658, 384, - 281, 360, 282, 763, 766, 765, 740, 0, 341, 638, - 464, 518, 401, 705, 706, 72, 761, 284, 285, 286, - 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, - 296, 297, 298, 303, 304, 305, 306, 307, 308, 309, - 310, 708, 301, 302, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 324, 0, 0, - 0, 0, 333, 767, 768, 769, 770, 771, 0, 0, - 334, 335, 336, 0, 0, 299, 300, 327, 549, 328, - 329, 330, 331, 0, 0, 587, 588, 589, 612, 0, - 590, 572, 637, 411, 342, 553, 579, 277, 278, 55, - 262, 265, 267, 266, 0, 73, 688, 699, 735, 736, - 9, 749, 750, 752, 754, 753, 756, 546, 547, 764, - 0, 0, 435, 357, 358, 494, 495, 532, 0, 436, - 437, 438, 442, 439, 440, 441, 758, 759, 760, 757, - 468, 531, 554, 540, 272, 481, 173, 279, 627, 628, - 280, 745, 744, 343, 0, 337, 338, 702, 703, 200, - 245, 534, 480, 634, 0, 0, 0, 0, 0, 0, - 500, 0, 0, 643, 677, 666, 755, 630, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 394, 0, - 0, 463, 681, 662, 673, 663, 506, 648, 649, 650, - 657, 406, 651, 787, 653, 622, 654, 623, 655, 656, - 1266, 680, 629, 542, 482, 0, 697, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 238, 0, 0, 268, 0, - 0, 0, 0, 0, 0, 365, 269, 624, 751, 626, - 625, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 368, 3048, 3051, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 543, 571, 0, 584, 0, 432, 433, 0, 0, - 0, 0, 0, 0, 0, 350, 550, 568, 366, 537, - 582, 371, 545, 561, 361, 499, 533, 0, 0, 352, - 566, 544, 477, 351, 0, 526, 391, 408, 388, 497, - 0, 0, 565, 595, 387, 585, 0, 576, 354, 0, - 575, 496, 469, 562, 567, 478, 471, 0, 353, 564, - 476, 470, 446, 398, 611, 447, 448, 449, 450, 451, - 452, 412, 512, 467, 513, 413, 484, 483, 485, 414, - 415, 416, 417, 418, 419, 420, 421, 422, 423, 0, - 0, 0, 0, 0, 606, 607, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 743, 0, 246, 748, 3052, 578, 0, 0, 0, - 3047, 0, 3046, 548, 3043, 3049, 453, 0, 0, 0, - 596, 0, 529, 502, 789, 0, 0, 527, 465, 563, - 514, 569, 551, 577, 521, 515, 344, 552, 390, 479, - 362, 364, 776, 392, 395, 399, 400, 490, 491, 508, - 536, 555, 556, 557, 389, 376, 528, 377, 409, 378, - 345, 381, 380, 382, 538, 383, 347, 509, 560, 3050, - 405, 524, 474, 348, 473, 510, 559, 558, 363, 586, - 593, 594, 685, 0, 599, 790, 791, 792, 608, 0, - 516, 359, 356, 0, 0, 0, 385, 511, 372, 374, - 375, 373, 505, 507, 613, 614, 615, 617, 0, 618, - 619, 0, 0, 0, 0, 620, 686, 704, 670, 639, - 601, 694, 636, 640, 641, 426, 427, 428, 429, 707, - 0, 0, 0, 592, 454, 455, 0, 397, 396, 475, - 349, 0, 0, 443, 425, 517, 355, 393, 445, 431, - 456, 457, 458, 459, 460, 3044, 461, 462, 403, 339, - 340, 784, 386, 498, 709, 746, 747, 631, 0, 695, - 632, 642, 379, 667, 679, 678, 492, 591, 0, 690, - 693, 621, 783, 0, 687, 701, 788, 700, 780, 504, - 0, 535, 698, 645, 0, 691, 664, 665, 0, 692, - 660, 696, 0, 633, 0, 602, 605, 635, 722, 723, - 724, 346, 604, 726, 727, 728, 729, 730, 731, 732, - 725, 574, 668, 644, 671, 583, 647, 646, 0, 0, - 682, 600, 683, 684, 486, 487, 488, 489, 407, 710, - 370, 603, 519, 520, 0, 669, 0, 0, 0, 0, - 0, 0, 0, 0, 674, 675, 672, 793, 0, 733, - 734, 0, 0, 597, 598, 402, 0, 616, 410, 369, - 503, 404, 581, 434, 0, 609, 676, 610, 522, 523, - 737, 742, 738, 739, 741, 762, 493, 424, 430, 539, - 444, 466, 525, 580, 501, 530, 367, 570, 541, 472, - 661, 689, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 718, - 717, 716, 715, 714, 713, 712, 711, 0, 0, 658, - 384, 781, 775, 782, 763, 766, 765, 740, 0, 341, - 638, 464, 518, 401, 705, 706, 0, 761, 284, 285, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4156, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 200, 245, 1023, 0, 0, 0, + 0, 0, 0, 0, 0, 502, 0, 0, 647, 681, + 670, 759, 634, 172, 0, 0, 0, 0, 0, 974, + 0, 0, 0, 395, 0, 0, 465, 685, 666, 677, + 667, 508, 652, 653, 654, 661, 407, 655, 791, 657, + 626, 658, 627, 659, 660, 1609, 684, 633, 545, 484, + 0, 701, 0, 0, 1096, 1105, 0, 0, 0, 0, + 0, 0, 0, 0, 1092, 0, 0, 0, 0, 0, + 965, 0, 0, 1003, 1073, 1072, 990, 1000, 0, 0, + 366, 269, 628, 755, 630, 629, 991, 0, 992, 996, + 999, 995, 993, 994, 0, 1087, 0, 0, 0, 0, + 0, 0, 957, 969, 0, 975, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 966, 967, 0, 0, 0, 0, 1024, 0, 968, + 0, 970, 0, 0, 0, 0, 546, 574, 0, 588, + 0, 434, 435, 1019, 997, 1001, 0, 0, 0, 0, + 350, 553, 571, 367, 540, 586, 372, 548, 564, 362, + 501, 536, 0, 0, 352, 569, 547, 479, 351, 0, + 529, 392, 409, 389, 499, 998, 0, 1022, 1026, 388, + 1111, 1020, 579, 354, 0, 578, 498, 471, 565, 570, + 480, 473, 0, 353, 567, 478, 472, 448, 399, 1112, + 449, 450, 451, 452, 453, 454, 413, 514, 469, 515, + 414, 486, 485, 487, 415, 416, 417, 418, 419, 420, + 421, 422, 423, 424, 0, 0, 0, 0, 0, 610, + 611, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 747, 1017, 246, 752, + 0, 582, 0, 0, 1094, 0, 0, 0, 551, 0, + 0, 455, 0, 0, 0, 1021, 172, 532, 504, 1108, + 0, 0, 530, 467, 566, 516, 572, 554, 580, 523, + 517, 344, 555, 391, 481, 363, 365, 780, 393, 396, + 400, 401, 492, 493, 510, 539, 558, 559, 560, 390, + 377, 531, 378, 410, 379, 345, 382, 381, 383, 541, + 384, 347, 511, 563, 0, 406, 527, 476, 348, 475, + 512, 562, 561, 364, 590, 597, 598, 689, 0, 603, + 794, 795, 796, 612, 0, 518, 360, 357, 0, 0, + 0, 386, 513, 373, 375, 376, 374, 507, 509, 617, + 618, 619, 621, 0, 622, 623, 0, 0, 0, 0, + 624, 690, 708, 674, 643, 605, 698, 640, 644, 645, + 427, 428, 429, 430, 711, 0, 0, 0, 596, 456, + 457, 0, 398, 397, 477, 349, 0, 0, 445, 426, + 519, 355, 394, 447, 432, 458, 459, 460, 461, 462, + 0, 463, 464, 404, 339, 340, 788, 1091, 500, 713, + 750, 751, 635, 0, 1107, 1086, 1088, 1089, 1093, 1097, + 1098, 1099, 1100, 1101, 1103, 1106, 1110, 787, 0, 691, + 705, 792, 704, 784, 506, 0, 538, 702, 649, 0, + 695, 668, 669, 0, 696, 664, 700, 356, 433, 524, + 581, 0, 637, 0, 606, 609, 639, 726, 727, 728, + 346, 608, 730, 731, 732, 733, 734, 735, 736, 729, + 1109, 672, 648, 675, 587, 651, 650, 0, 0, 686, + 1025, 687, 688, 488, 489, 490, 491, 1095, 714, 371, + 607, 521, 522, 0, 673, 0, 0, 0, 0, 0, + 172, 0, 0, 678, 679, 676, 797, 0, 737, 738, + 0, 0, 601, 602, 403, 0, 620, 411, 370, 505, + 405, 585, 436, 0, 613, 680, 614, 525, 526, 741, + 746, 742, 743, 745, 766, 495, 425, 431, 542, 446, + 468, 528, 584, 503, 533, 368, 573, 544, 474, 665, + 693, 1118, 1090, 1117, 1119, 1120, 1116, 1121, 1122, 1102, + 979, 0, 1032, 1033, 1114, 1113, 1115, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 722, 721, + 720, 719, 718, 717, 716, 715, 0, 0, 662, 385, + 785, 779, 786, 767, 770, 769, 744, 986, 341, 642, + 466, 520, 402, 709, 710, 0, 765, 1080, 1043, 1044, + 1045, 976, 1046, 1040, 1041, 977, 1042, 1081, 1030, 1077, + 1078, 1005, 1035, 1047, 1076, 1048, 1079, 1006, 1082, 1123, + 1124, 1054, 1038, 302, 1125, 1051, 1083, 1075, 1074, 1049, + 1031, 1084, 1085, 1013, 1008, 1052, 1053, 1039, 1060, 1061, + 1062, 1065, 978, 1066, 1067, 1068, 1069, 1070, 1064, 1063, + 1027, 1028, 1029, 1055, 1056, 1058, 1059, 1034, 552, 1009, + 1010, 1011, 1012, 0, 0, 591, 592, 593, 616, 0, + 594, 575, 641, 412, 342, 556, 583, 782, 783, 0, + 0, 0, 0, 0, 0, 0, 692, 703, 739, 740, + 0, 753, 754, 756, 758, 1071, 760, 549, 550, 768, + 0, 0, 437, 358, 359, 496, 497, 535, 0, 438, + 439, 440, 444, 441, 442, 443, 1057, 763, 764, 761, + 470, 534, 557, 543, 781, 483, 0, 789, 631, 632, + 790, 749, 748, 343, 0, 1036, 1037, 706, 707, 1023, + 0, 1104, 482, 638, 0, 971, 0, 0, 502, 0, + 0, 647, 681, 670, 759, 634, 0, 0, 0, 0, + 0, 0, 974, 0, 0, 0, 395, 0, 0, 465, + 685, 666, 677, 667, 508, 652, 653, 654, 661, 407, + 655, 791, 657, 626, 658, 627, 659, 660, 1014, 684, + 633, 545, 484, 0, 701, 0, 0, 1096, 1105, 0, + 0, 0, 0, 0, 0, 0, 0, 1092, 0, 0, + 0, 0, 0, 965, 0, 0, 1003, 1073, 1072, 990, + 1000, 0, 0, 366, 269, 628, 755, 630, 629, 991, + 0, 992, 996, 999, 995, 993, 994, 0, 1087, 0, + 0, 0, 0, 0, 0, 957, 969, 0, 975, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 966, 967, 0, 0, 0, 0, + 1024, 0, 968, 0, 970, 0, 0, 0, 0, 546, + 574, 0, 588, 0, 434, 435, 1019, 997, 1001, 0, + 0, 0, 0, 350, 553, 571, 367, 540, 586, 372, + 548, 564, 362, 501, 536, 0, 0, 352, 569, 547, + 479, 351, 0, 529, 392, 409, 389, 499, 998, 0, + 1022, 1026, 388, 1111, 1020, 579, 354, 0, 578, 498, + 471, 565, 570, 480, 473, 0, 353, 567, 478, 472, + 448, 399, 1112, 449, 450, 451, 452, 453, 454, 413, + 514, 469, 515, 414, 486, 485, 487, 415, 416, 417, + 418, 419, 420, 421, 422, 423, 424, 0, 0, 0, + 0, 0, 610, 611, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 747, + 1017, 0, 752, 0, 582, 0, 0, 1094, 0, 0, + 0, 551, 0, 0, 455, 0, 0, 0, 1021, 0, + 532, 504, 1108, 0, 0, 530, 467, 566, 516, 572, + 554, 580, 523, 517, 344, 555, 391, 481, 363, 365, + 780, 393, 396, 400, 401, 492, 493, 510, 539, 558, + 559, 560, 390, 377, 531, 378, 410, 379, 345, 382, + 381, 383, 541, 384, 347, 511, 563, 0, 406, 527, + 476, 348, 475, 512, 562, 561, 364, 590, 597, 598, + 689, 0, 603, 794, 795, 796, 612, 0, 518, 360, + 357, 0, 0, 0, 386, 513, 373, 375, 376, 374, + 507, 509, 617, 618, 619, 621, 0, 622, 623, 0, + 0, 0, 0, 624, 690, 708, 674, 643, 605, 698, + 640, 644, 645, 427, 428, 429, 430, 711, 2251, 2250, + 2252, 596, 456, 457, 0, 398, 397, 477, 349, 0, + 0, 445, 426, 519, 355, 394, 447, 432, 458, 459, + 460, 461, 462, 0, 463, 464, 404, 339, 340, 788, + 1091, 500, 713, 750, 751, 635, 0, 1107, 1086, 1088, + 1089, 1093, 1097, 1098, 1099, 1100, 1101, 1103, 1106, 1110, + 787, 0, 691, 705, 792, 704, 784, 506, 0, 538, + 702, 649, 0, 695, 668, 669, 0, 696, 664, 700, + 356, 433, 524, 581, 0, 637, 0, 606, 609, 639, + 726, 727, 728, 346, 608, 730, 731, 732, 733, 734, + 735, 736, 729, 1109, 672, 648, 675, 587, 651, 650, + 0, 0, 686, 1025, 687, 688, 488, 489, 490, 491, + 1095, 714, 371, 607, 521, 522, 0, 673, 0, 0, + 0, 0, 0, 0, 0, 0, 678, 679, 676, 797, + 0, 737, 738, 0, 0, 601, 602, 403, 0, 620, + 411, 370, 505, 405, 585, 436, 0, 613, 680, 614, + 525, 526, 741, 746, 742, 743, 745, 766, 495, 425, + 431, 542, 446, 468, 528, 584, 503, 533, 368, 573, + 544, 474, 665, 693, 1118, 1090, 1117, 1119, 1120, 1116, + 1121, 1122, 1102, 979, 0, 1032, 1033, 1114, 1113, 1115, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 722, 721, 720, 719, 718, 717, 716, 715, 0, + 0, 662, 385, 785, 779, 786, 767, 770, 769, 744, + 986, 341, 642, 466, 520, 402, 709, 710, 0, 765, + 1080, 1043, 1044, 1045, 976, 1046, 1040, 1041, 977, 1042, + 1081, 1030, 1077, 1078, 1005, 1035, 1047, 1076, 1048, 1079, + 1006, 1082, 1123, 1124, 1054, 1038, 302, 1125, 1051, 1083, + 1075, 1074, 1049, 1031, 1084, 1085, 1013, 1008, 1052, 1053, + 1039, 1060, 1061, 1062, 1065, 978, 1066, 1067, 1068, 1069, + 1070, 1064, 1063, 1027, 1028, 1029, 1055, 1056, 1058, 1059, + 1034, 552, 1009, 1010, 1011, 1012, 0, 0, 591, 592, + 593, 616, 0, 594, 575, 641, 412, 342, 556, 583, + 782, 783, 0, 0, 0, 0, 0, 0, 0, 692, + 703, 739, 740, 0, 753, 754, 756, 758, 1071, 760, + 549, 550, 768, 0, 0, 437, 358, 359, 496, 497, + 535, 0, 438, 439, 440, 444, 441, 442, 443, 1057, + 763, 764, 761, 470, 534, 557, 543, 781, 483, 0, + 789, 631, 632, 790, 749, 748, 343, 0, 1036, 1037, + 706, 707, 0, 0, 1104, 482, 638, 0, 971, 200, + 245, 1023, 0, 0, 0, 0, 0, 0, 0, 0, + 502, 0, 0, 647, 681, 670, 759, 634, 0, 0, + 0, 0, 0, 0, 974, 0, 0, 0, 395, 0, + 0, 465, 685, 666, 677, 667, 508, 652, 653, 654, + 661, 407, 655, 791, 657, 626, 658, 627, 659, 660, + 1014, 684, 633, 545, 484, 0, 701, 0, 0, 1096, + 1105, 0, 0, 0, 0, 0, 0, 0, 0, 1092, + 0, 0, 0, 0, 0, 965, 0, 0, 1003, 1073, + 1072, 990, 1000, 0, 0, 366, 269, 628, 755, 630, + 629, 991, 0, 992, 996, 999, 995, 993, 994, 0, + 1087, 0, 0, 0, 0, 0, 0, 957, 969, 0, + 975, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 966, 967, 0, 0, + 0, 0, 1024, 0, 968, 0, 970, 0, 0, 0, + 0, 546, 574, 0, 588, 0, 434, 435, 1019, 997, + 1001, 0, 0, 0, 0, 350, 553, 571, 367, 540, + 586, 372, 548, 564, 362, 501, 536, 0, 0, 352, + 569, 547, 479, 351, 0, 529, 392, 409, 389, 499, + 998, 0, 1022, 1026, 388, 1111, 1020, 579, 354, 0, + 578, 498, 471, 565, 570, 480, 473, 0, 353, 567, + 478, 472, 448, 399, 1112, 449, 450, 451, 452, 453, + 454, 413, 514, 469, 515, 414, 486, 485, 487, 415, + 416, 417, 418, 419, 420, 421, 422, 423, 424, 0, + 0, 0, 0, 0, 610, 611, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 747, 1017, 0, 752, 0, 582, 0, 0, 1094, + 0, 0, 0, 551, 0, 0, 455, 0, 0, 0, + 1021, 0, 532, 504, 1108, 0, 0, 530, 467, 566, + 516, 572, 554, 580, 523, 517, 344, 555, 391, 481, + 363, 365, 780, 393, 396, 400, 401, 492, 493, 510, + 539, 558, 559, 560, 390, 377, 531, 378, 410, 379, + 345, 382, 381, 383, 541, 384, 347, 511, 563, 0, + 406, 527, 476, 348, 475, 512, 562, 561, 364, 590, + 597, 598, 689, 0, 603, 794, 795, 796, 612, 0, + 518, 360, 357, 0, 0, 0, 386, 513, 373, 375, + 376, 374, 507, 509, 617, 618, 619, 621, 0, 622, + 623, 0, 0, 0, 0, 624, 690, 708, 674, 643, + 605, 698, 640, 644, 645, 427, 428, 429, 430, 711, + 0, 0, 0, 596, 456, 457, 0, 398, 397, 477, + 349, 0, 0, 445, 426, 519, 355, 394, 447, 432, + 458, 459, 460, 461, 462, 0, 463, 464, 404, 339, + 340, 788, 1091, 500, 713, 750, 751, 635, 0, 1107, + 1086, 1088, 1089, 1093, 1097, 1098, 1099, 1100, 1101, 1103, + 1106, 1110, 787, 0, 691, 705, 792, 704, 784, 506, + 0, 538, 702, 649, 0, 695, 668, 669, 0, 696, + 664, 700, 356, 433, 524, 581, 0, 637, 0, 606, + 609, 639, 726, 727, 728, 346, 608, 730, 731, 732, + 733, 734, 735, 736, 729, 1109, 672, 648, 675, 587, + 651, 650, 0, 0, 686, 1025, 687, 688, 488, 489, + 490, 491, 1095, 714, 371, 607, 521, 522, 0, 673, + 0, 0, 0, 0, 0, 0, 0, 0, 678, 679, + 676, 797, 0, 737, 738, 0, 0, 601, 602, 403, + 0, 620, 411, 370, 505, 405, 585, 436, 0, 613, + 680, 614, 525, 526, 741, 746, 742, 743, 745, 766, + 495, 425, 431, 542, 446, 468, 528, 584, 503, 533, + 368, 573, 544, 474, 665, 693, 1118, 1090, 1117, 1119, + 1120, 1116, 1121, 1122, 1102, 979, 0, 1032, 1033, 1114, + 1113, 1115, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 722, 721, 720, 719, 718, 717, 716, + 715, 0, 0, 662, 385, 785, 779, 786, 767, 770, + 769, 744, 986, 341, 642, 466, 520, 402, 709, 710, + 0, 765, 1080, 1043, 1044, 1045, 976, 1046, 1040, 1041, + 977, 1042, 1081, 1030, 1077, 1078, 1005, 1035, 1047, 1076, + 1048, 1079, 1006, 1082, 1123, 1124, 1054, 1038, 302, 1125, + 1051, 1083, 1075, 1074, 1049, 1031, 1084, 1085, 1013, 1008, + 1052, 1053, 1039, 1060, 1061, 1062, 1065, 978, 1066, 1067, + 1068, 1069, 1070, 1064, 1063, 1027, 1028, 1029, 1055, 1056, + 1058, 1059, 1034, 552, 1009, 1010, 1011, 1012, 0, 0, + 591, 592, 593, 616, 0, 594, 575, 641, 412, 342, + 556, 583, 782, 783, 0, 0, 0, 0, 0, 0, + 0, 692, 703, 739, 740, 0, 753, 754, 756, 758, + 1071, 760, 549, 550, 768, 0, 0, 437, 358, 359, + 496, 497, 535, 0, 438, 439, 440, 444, 441, 442, + 443, 1057, 763, 764, 761, 470, 534, 557, 543, 781, + 483, 0, 789, 631, 632, 790, 749, 748, 343, 0, + 1036, 1037, 706, 707, 1023, 0, 1104, 482, 638, 0, + 971, 0, 0, 502, 0, 0, 647, 681, 670, 759, + 634, 0, 0, 0, 0, 0, 0, 974, 0, 0, + 0, 395, 2323, 0, 465, 685, 666, 677, 667, 508, + 652, 653, 654, 661, 407, 655, 791, 657, 626, 658, + 627, 659, 660, 1014, 684, 633, 545, 484, 0, 701, + 0, 0, 1096, 1105, 0, 0, 0, 0, 0, 0, + 0, 0, 1092, 0, 2572, 0, 0, 0, 965, 0, + 0, 1003, 1073, 1072, 990, 1000, 0, 0, 366, 269, + 628, 755, 630, 629, 991, 0, 992, 996, 999, 995, + 993, 994, 0, 1087, 0, 0, 0, 0, 0, 0, + 957, 969, 0, 975, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 966, + 967, 0, 0, 0, 0, 1024, 0, 968, 0, 970, + 0, 0, 0, 0, 546, 574, 0, 588, 0, 434, + 435, 2573, 997, 1001, 0, 0, 0, 0, 350, 553, + 571, 367, 540, 586, 372, 548, 564, 362, 501, 536, + 0, 0, 352, 569, 547, 479, 351, 0, 529, 392, + 409, 389, 499, 998, 0, 1022, 1026, 388, 1111, 1020, + 579, 354, 0, 578, 498, 471, 565, 570, 480, 473, + 0, 353, 567, 478, 472, 448, 399, 1112, 449, 450, + 451, 452, 453, 454, 413, 514, 469, 515, 414, 486, + 485, 487, 415, 416, 417, 418, 419, 420, 421, 422, + 423, 424, 0, 0, 0, 0, 0, 610, 611, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 747, 1017, 0, 752, 0, 582, + 0, 0, 1094, 0, 0, 0, 551, 0, 0, 455, + 0, 0, 0, 1021, 0, 532, 504, 1108, 0, 0, + 530, 467, 566, 516, 572, 554, 580, 523, 517, 344, + 555, 391, 481, 363, 365, 780, 393, 396, 400, 401, + 492, 493, 510, 539, 558, 559, 560, 390, 377, 531, + 378, 410, 379, 345, 382, 381, 383, 541, 384, 347, + 511, 563, 0, 406, 527, 476, 348, 475, 512, 562, + 561, 364, 590, 597, 598, 689, 0, 603, 794, 795, + 796, 612, 0, 518, 360, 357, 0, 0, 0, 386, + 513, 373, 375, 376, 374, 507, 509, 617, 618, 619, + 621, 0, 622, 623, 0, 0, 0, 0, 624, 690, + 708, 674, 643, 605, 698, 640, 644, 645, 427, 428, + 429, 430, 711, 0, 0, 0, 596, 456, 457, 0, + 398, 397, 477, 349, 0, 0, 445, 426, 519, 355, + 394, 447, 432, 458, 459, 460, 461, 462, 0, 463, + 464, 404, 339, 340, 788, 1091, 500, 713, 750, 751, + 635, 0, 1107, 1086, 1088, 1089, 1093, 1097, 1098, 1099, + 1100, 1101, 1103, 1106, 1110, 787, 0, 691, 705, 792, + 704, 784, 506, 0, 538, 702, 649, 0, 695, 668, + 669, 0, 696, 664, 700, 356, 433, 524, 581, 0, + 637, 0, 606, 609, 639, 726, 727, 728, 346, 608, + 730, 731, 732, 733, 734, 735, 736, 729, 1109, 672, + 648, 675, 587, 651, 650, 0, 0, 686, 1025, 687, + 688, 488, 489, 490, 491, 1095, 714, 371, 607, 521, + 522, 0, 673, 0, 0, 0, 0, 0, 0, 0, + 0, 678, 679, 676, 797, 0, 737, 738, 0, 0, + 601, 602, 403, 0, 620, 411, 370, 505, 405, 585, + 436, 0, 613, 680, 614, 525, 526, 741, 746, 742, + 743, 745, 766, 495, 425, 431, 542, 446, 468, 528, + 584, 503, 533, 368, 573, 544, 474, 665, 693, 1118, + 1090, 1117, 1119, 1120, 1116, 1121, 1122, 1102, 979, 0, + 1032, 1033, 1114, 1113, 1115, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 722, 721, 720, 719, + 718, 717, 716, 715, 0, 0, 662, 385, 785, 779, + 786, 767, 770, 769, 744, 986, 341, 642, 466, 520, + 402, 709, 710, 0, 765, 1080, 1043, 1044, 1045, 976, + 1046, 1040, 1041, 977, 1042, 1081, 1030, 1077, 1078, 1005, + 1035, 1047, 1076, 1048, 1079, 1006, 1082, 1123, 1124, 1054, + 1038, 302, 1125, 1051, 1083, 1075, 1074, 1049, 1031, 1084, + 1085, 1013, 1008, 1052, 1053, 1039, 1060, 1061, 1062, 1065, + 978, 1066, 1067, 1068, 1069, 1070, 1064, 1063, 1027, 1028, + 1029, 1055, 1056, 1058, 1059, 1034, 552, 1009, 1010, 1011, + 1012, 0, 0, 591, 592, 593, 616, 0, 594, 575, + 641, 412, 342, 556, 583, 782, 783, 0, 0, 0, + 0, 0, 0, 0, 692, 703, 739, 740, 0, 753, + 754, 756, 758, 1071, 760, 549, 550, 768, 0, 0, + 437, 358, 359, 496, 497, 535, 0, 438, 439, 440, + 444, 441, 442, 443, 1057, 763, 764, 761, 470, 534, + 557, 543, 781, 483, 0, 789, 631, 632, 790, 749, + 748, 343, 0, 1036, 1037, 706, 707, 1023, 0, 1104, + 482, 638, 0, 971, 0, 0, 502, 0, 0, 647, + 681, 670, 759, 634, 0, 0, 0, 0, 0, 0, + 974, 0, 0, 0, 395, 5333, 0, 465, 685, 666, + 677, 667, 508, 652, 653, 654, 661, 407, 655, 791, + 657, 626, 658, 627, 659, 660, 1014, 684, 633, 545, + 484, 0, 701, 0, 0, 1096, 1105, 0, 0, 0, + 0, 0, 0, 0, 0, 1092, 0, 0, 0, 0, + 0, 965, 0, 0, 1003, 1073, 1072, 990, 1000, 0, + 0, 366, 269, 628, 755, 630, 629, 991, 0, 992, + 996, 999, 995, 993, 994, 0, 1087, 0, 0, 0, + 0, 0, 0, 957, 969, 0, 975, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 966, 967, 0, 0, 0, 0, 1024, 0, + 968, 0, 970, 0, 0, 0, 0, 546, 574, 0, + 588, 0, 434, 435, 1019, 997, 1001, 0, 0, 0, + 0, 350, 553, 571, 367, 540, 586, 372, 548, 564, + 362, 501, 536, 0, 0, 352, 569, 547, 479, 351, + 0, 529, 392, 409, 389, 499, 998, 0, 1022, 1026, + 388, 1111, 1020, 579, 354, 0, 578, 498, 471, 565, + 570, 480, 473, 0, 353, 567, 478, 472, 448, 399, + 1112, 449, 450, 451, 452, 453, 454, 413, 514, 469, + 515, 414, 486, 485, 487, 415, 416, 417, 418, 419, + 420, 421, 422, 423, 424, 0, 0, 0, 0, 0, + 610, 611, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 747, 1017, 0, + 752, 0, 582, 0, 0, 1094, 0, 0, 0, 551, + 0, 0, 455, 0, 0, 0, 1021, 0, 532, 504, + 1108, 0, 0, 530, 467, 566, 516, 572, 554, 580, + 523, 517, 344, 555, 391, 481, 363, 365, 780, 393, + 396, 400, 401, 492, 493, 510, 539, 558, 559, 560, + 390, 377, 531, 378, 410, 379, 345, 382, 381, 383, + 541, 384, 347, 511, 563, 0, 406, 527, 476, 348, + 475, 512, 562, 561, 364, 590, 597, 598, 689, 0, + 603, 794, 795, 796, 612, 0, 518, 360, 357, 0, + 0, 0, 386, 513, 373, 375, 376, 374, 507, 509, + 617, 618, 619, 621, 0, 622, 623, 0, 0, 0, + 0, 624, 690, 708, 674, 643, 605, 698, 640, 644, + 645, 427, 428, 429, 430, 711, 0, 0, 0, 596, + 456, 457, 0, 398, 397, 477, 349, 0, 0, 445, + 426, 519, 355, 394, 447, 432, 458, 459, 460, 461, + 462, 0, 463, 464, 404, 339, 340, 788, 1091, 500, + 713, 750, 751, 635, 0, 1107, 1086, 1088, 1089, 1093, + 1097, 1098, 1099, 1100, 1101, 1103, 1106, 1110, 787, 0, + 691, 705, 792, 704, 784, 506, 0, 538, 702, 649, + 0, 695, 668, 669, 0, 696, 664, 700, 356, 433, + 524, 581, 0, 637, 0, 606, 609, 639, 726, 727, + 728, 346, 608, 730, 731, 732, 733, 734, 735, 736, + 729, 1109, 672, 648, 675, 587, 651, 650, 0, 0, + 686, 1025, 687, 688, 488, 489, 490, 491, 1095, 714, + 371, 607, 521, 522, 0, 673, 0, 0, 0, 0, + 0, 0, 0, 0, 678, 679, 676, 797, 0, 737, + 738, 0, 0, 601, 602, 403, 0, 620, 411, 370, + 505, 405, 585, 436, 0, 613, 680, 614, 525, 526, + 741, 746, 742, 743, 745, 766, 495, 425, 431, 542, + 446, 468, 528, 584, 503, 533, 368, 573, 544, 474, + 665, 693, 1118, 1090, 1117, 1119, 1120, 1116, 1121, 1122, + 1102, 979, 0, 1032, 1033, 1114, 1113, 1115, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 722, + 721, 720, 719, 718, 717, 716, 715, 0, 0, 662, + 385, 785, 779, 786, 767, 770, 769, 744, 986, 341, + 642, 466, 520, 402, 709, 710, 0, 765, 1080, 1043, + 1044, 1045, 976, 1046, 1040, 1041, 977, 1042, 1081, 1030, + 1077, 1078, 1005, 1035, 1047, 1076, 1048, 1079, 1006, 1082, + 1123, 1124, 1054, 1038, 302, 1125, 1051, 1083, 1075, 1074, + 1049, 1031, 1084, 1085, 1013, 1008, 1052, 1053, 1039, 1060, + 1061, 1062, 1065, 978, 1066, 1067, 1068, 1069, 1070, 1064, + 1063, 1027, 1028, 1029, 1055, 1056, 1058, 1059, 1034, 552, + 1009, 1010, 1011, 1012, 0, 0, 591, 592, 593, 616, + 0, 594, 575, 641, 412, 342, 556, 583, 782, 783, + 0, 0, 0, 0, 0, 0, 0, 692, 703, 739, + 740, 0, 753, 754, 756, 758, 1071, 760, 549, 550, + 768, 0, 0, 437, 358, 359, 496, 497, 535, 0, + 438, 439, 440, 444, 441, 442, 443, 1057, 763, 764, + 761, 470, 534, 557, 543, 781, 483, 0, 789, 631, + 632, 790, 749, 748, 343, 0, 1036, 1037, 706, 707, + 1023, 0, 1104, 482, 638, 0, 971, 0, 0, 502, + 0, 0, 647, 681, 670, 759, 634, 0, 0, 0, + 0, 0, 0, 974, 0, 0, 0, 395, 0, 0, + 465, 685, 666, 677, 667, 508, 652, 653, 654, 661, + 407, 655, 791, 657, 626, 658, 627, 659, 660, 1014, + 684, 633, 545, 484, 0, 701, 0, 0, 1096, 1105, + 0, 0, 0, 0, 0, 0, 0, 0, 1092, 0, + 0, 0, 0, 0, 965, 0, 0, 1003, 1073, 1072, + 990, 1000, 0, 0, 366, 269, 628, 755, 630, 629, + 991, 0, 992, 996, 999, 995, 993, 994, 0, 1087, + 0, 0, 0, 0, 0, 0, 957, 969, 0, 975, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 966, 967, 0, 0, 0, + 0, 1024, 0, 968, 0, 970, 0, 0, 0, 0, + 546, 574, 0, 588, 0, 434, 435, 1019, 997, 1001, + 0, 0, 0, 0, 350, 553, 571, 367, 540, 586, + 372, 548, 564, 362, 501, 536, 0, 0, 352, 569, + 547, 479, 351, 0, 529, 392, 409, 389, 499, 998, + 0, 1022, 1026, 388, 1111, 1020, 579, 354, 0, 578, + 498, 471, 565, 570, 480, 473, 0, 353, 567, 478, + 472, 448, 399, 1112, 449, 450, 451, 452, 453, 454, + 413, 514, 469, 515, 414, 486, 485, 487, 415, 416, + 417, 418, 419, 420, 421, 422, 423, 424, 0, 0, + 0, 0, 0, 610, 611, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 747, 1017, 0, 752, 0, 582, 0, 0, 1094, 0, + 0, 0, 551, 0, 0, 455, 0, 0, 0, 1021, + 0, 532, 504, 1108, 5146, 0, 530, 467, 566, 516, + 572, 554, 580, 523, 517, 344, 555, 391, 481, 363, + 365, 780, 393, 396, 400, 401, 492, 493, 510, 539, + 558, 559, 560, 390, 377, 531, 378, 410, 379, 345, + 382, 381, 383, 541, 384, 347, 511, 563, 0, 406, + 527, 476, 348, 475, 512, 562, 561, 364, 590, 597, + 598, 689, 0, 603, 794, 795, 796, 612, 0, 518, + 360, 357, 0, 0, 0, 386, 513, 373, 375, 376, + 374, 507, 509, 617, 618, 619, 621, 0, 622, 623, + 0, 0, 0, 0, 624, 690, 708, 674, 643, 605, + 698, 640, 644, 645, 427, 428, 429, 430, 711, 0, + 0, 0, 596, 456, 457, 0, 398, 397, 477, 349, + 0, 0, 445, 426, 519, 355, 394, 447, 432, 458, + 459, 460, 461, 462, 0, 463, 464, 404, 339, 340, + 788, 1091, 500, 713, 750, 751, 635, 0, 1107, 1086, + 1088, 1089, 1093, 1097, 1098, 1099, 1100, 1101, 1103, 1106, + 1110, 787, 0, 691, 705, 792, 704, 784, 506, 0, + 538, 702, 649, 0, 695, 668, 669, 0, 696, 664, + 700, 356, 433, 524, 581, 0, 637, 0, 606, 609, + 639, 726, 727, 728, 346, 608, 730, 731, 732, 733, + 734, 735, 736, 729, 1109, 672, 648, 675, 587, 651, + 650, 0, 0, 686, 1025, 687, 688, 488, 489, 490, + 491, 1095, 714, 371, 607, 521, 522, 0, 673, 0, + 0, 0, 0, 0, 0, 0, 0, 678, 679, 676, + 797, 0, 737, 738, 0, 0, 601, 602, 403, 0, + 620, 411, 370, 505, 405, 585, 436, 0, 613, 680, + 614, 525, 526, 741, 746, 742, 743, 745, 766, 495, + 425, 431, 542, 446, 468, 528, 584, 503, 533, 368, + 573, 544, 474, 665, 693, 1118, 1090, 1117, 1119, 1120, + 1116, 1121, 1122, 1102, 979, 0, 1032, 1033, 1114, 1113, + 1115, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 722, 721, 720, 719, 718, 717, 716, 715, + 0, 0, 662, 385, 785, 779, 786, 767, 770, 769, + 744, 986, 341, 642, 466, 520, 402, 709, 710, 0, + 765, 1080, 1043, 1044, 1045, 976, 1046, 1040, 1041, 977, + 1042, 1081, 1030, 1077, 1078, 1005, 1035, 1047, 1076, 1048, + 1079, 1006, 1082, 1123, 1124, 1054, 1038, 302, 1125, 1051, + 1083, 1075, 1074, 1049, 1031, 1084, 1085, 1013, 1008, 1052, + 1053, 1039, 1060, 1061, 1062, 1065, 978, 1066, 1067, 1068, + 1069, 1070, 1064, 1063, 1027, 1028, 1029, 1055, 1056, 1058, + 1059, 1034, 552, 1009, 1010, 1011, 1012, 0, 0, 591, + 592, 593, 616, 0, 594, 575, 641, 412, 342, 556, + 583, 782, 783, 0, 0, 0, 0, 0, 0, 0, + 692, 703, 739, 740, 0, 753, 754, 756, 758, 1071, + 760, 549, 550, 768, 0, 0, 437, 358, 359, 496, + 497, 535, 0, 438, 439, 440, 444, 441, 442, 443, + 1057, 763, 764, 761, 470, 534, 557, 543, 781, 483, + 0, 789, 631, 632, 790, 749, 748, 343, 0, 1036, + 1037, 706, 707, 1023, 0, 1104, 482, 638, 0, 971, + 0, 0, 502, 0, 0, 647, 681, 670, 759, 634, + 0, 0, 0, 0, 0, 0, 974, 0, 0, 0, + 395, 0, 0, 465, 685, 666, 677, 667, 508, 652, + 653, 654, 661, 407, 655, 791, 657, 626, 658, 627, + 659, 660, 1014, 684, 633, 545, 484, 0, 701, 0, + 0, 1096, 1105, 0, 0, 0, 0, 0, 0, 0, + 0, 1092, 0, 0, 0, 0, 0, 965, 0, 0, + 1003, 1073, 1072, 990, 1000, 0, 0, 366, 269, 628, + 755, 630, 629, 991, 0, 992, 996, 999, 995, 993, + 994, 0, 1087, 0, 0, 0, 0, 0, 0, 957, + 969, 0, 975, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 966, 967, + 1921, 0, 0, 0, 1024, 0, 968, 0, 970, 0, + 0, 0, 0, 546, 574, 0, 588, 0, 434, 435, + 1019, 997, 1001, 0, 0, 0, 0, 350, 553, 571, + 367, 540, 586, 372, 548, 564, 362, 501, 536, 0, + 0, 352, 569, 547, 479, 351, 0, 529, 392, 409, + 389, 499, 998, 0, 1022, 1026, 388, 1111, 1020, 579, + 354, 0, 578, 498, 471, 565, 570, 480, 473, 0, + 353, 567, 478, 472, 448, 399, 1112, 449, 450, 451, + 452, 453, 454, 413, 514, 469, 515, 414, 486, 485, + 487, 415, 416, 417, 418, 419, 420, 421, 422, 423, + 424, 0, 0, 0, 0, 0, 610, 611, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 747, 1017, 0, 752, 0, 582, 0, + 0, 1094, 0, 0, 0, 551, 0, 0, 455, 0, + 0, 0, 1021, 0, 532, 504, 1108, 0, 0, 530, + 467, 566, 516, 572, 554, 580, 523, 517, 344, 555, + 391, 481, 363, 365, 780, 393, 396, 400, 401, 492, + 493, 510, 539, 558, 559, 560, 390, 377, 531, 378, + 410, 379, 345, 382, 381, 383, 541, 384, 347, 511, + 563, 0, 406, 527, 476, 348, 475, 512, 562, 561, + 364, 590, 597, 598, 689, 0, 603, 794, 795, 796, + 612, 0, 518, 360, 357, 0, 0, 0, 386, 513, + 373, 375, 376, 374, 507, 509, 617, 618, 619, 621, + 0, 622, 623, 0, 0, 0, 0, 624, 690, 708, + 674, 643, 605, 698, 640, 644, 645, 427, 428, 429, + 430, 711, 0, 0, 0, 596, 456, 457, 0, 398, + 397, 477, 349, 0, 0, 445, 426, 519, 355, 394, + 447, 432, 458, 459, 460, 461, 462, 0, 463, 464, + 404, 339, 340, 788, 1091, 500, 713, 750, 751, 635, + 0, 1107, 1086, 1088, 1089, 1093, 1097, 1098, 1099, 1100, + 1101, 1103, 1106, 1110, 787, 0, 691, 705, 792, 704, + 784, 506, 0, 538, 702, 649, 0, 695, 668, 669, + 0, 696, 664, 700, 356, 433, 524, 581, 0, 637, + 0, 606, 609, 639, 726, 727, 728, 346, 608, 730, + 731, 732, 733, 734, 735, 736, 729, 1109, 672, 648, + 675, 587, 651, 650, 0, 0, 686, 1025, 687, 688, + 488, 489, 490, 491, 1095, 714, 371, 607, 521, 522, + 0, 673, 0, 0, 0, 0, 0, 0, 0, 0, + 678, 679, 676, 797, 0, 737, 738, 0, 0, 601, + 602, 403, 0, 620, 411, 370, 505, 405, 585, 436, + 0, 613, 680, 614, 525, 526, 741, 746, 742, 743, + 745, 766, 495, 425, 431, 542, 446, 468, 528, 584, + 503, 533, 368, 573, 544, 474, 665, 693, 1118, 1090, + 1117, 1119, 1120, 1116, 1121, 1122, 1102, 979, 0, 1032, + 1033, 1114, 1113, 1115, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 722, 721, 720, 719, 718, + 717, 716, 715, 0, 0, 662, 385, 785, 779, 786, + 767, 770, 769, 744, 986, 341, 642, 466, 520, 402, + 709, 710, 0, 765, 1080, 1043, 1044, 1045, 976, 1046, + 1040, 1041, 977, 1042, 1081, 1030, 1077, 1078, 1005, 1035, + 1047, 1076, 1048, 1079, 1006, 1082, 1123, 1124, 1054, 1038, + 302, 1125, 1051, 1083, 1075, 1074, 1049, 1031, 1084, 1085, + 1013, 1008, 1052, 1053, 1039, 1060, 1061, 1062, 1065, 978, + 1066, 1067, 1068, 1069, 1070, 1064, 1063, 1027, 1028, 1029, + 1055, 1056, 1058, 1059, 1034, 552, 1009, 1010, 1011, 1012, + 0, 0, 591, 592, 593, 616, 0, 594, 575, 641, + 412, 342, 556, 583, 782, 783, 0, 0, 0, 0, + 0, 0, 0, 692, 703, 739, 740, 0, 753, 754, + 756, 758, 1071, 760, 549, 550, 768, 0, 0, 437, + 358, 359, 496, 497, 535, 0, 438, 439, 440, 444, + 441, 442, 443, 1057, 763, 764, 761, 470, 534, 557, + 543, 781, 483, 0, 789, 631, 632, 790, 749, 748, + 343, 0, 1036, 1037, 706, 707, 1023, 0, 1104, 482, + 638, 0, 971, 0, 0, 502, 0, 0, 647, 681, + 670, 759, 634, 0, 0, 0, 0, 0, 0, 974, + 0, 0, 0, 395, 2323, 0, 465, 685, 666, 677, + 667, 508, 652, 653, 654, 661, 407, 655, 791, 657, + 626, 658, 627, 659, 660, 1014, 684, 633, 545, 484, + 0, 701, 0, 0, 1096, 1105, 0, 0, 0, 0, + 0, 0, 0, 0, 1092, 0, 0, 0, 0, 0, + 965, 0, 0, 1003, 1073, 1072, 990, 1000, 0, 0, + 366, 269, 628, 755, 630, 629, 991, 0, 992, 996, + 999, 995, 993, 994, 0, 1087, 0, 0, 0, 0, + 0, 0, 957, 969, 0, 975, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 966, 967, 0, 0, 0, 0, 1024, 0, 968, + 0, 970, 0, 0, 0, 0, 546, 574, 0, 588, + 0, 434, 435, 1019, 997, 1001, 0, 0, 0, 0, + 350, 553, 571, 367, 540, 586, 372, 548, 564, 362, + 501, 536, 0, 0, 352, 569, 547, 479, 351, 0, + 529, 392, 409, 389, 499, 998, 0, 1022, 1026, 388, + 1111, 1020, 579, 354, 0, 578, 498, 471, 565, 570, + 480, 473, 0, 353, 567, 478, 472, 448, 399, 1112, + 449, 450, 451, 452, 453, 454, 413, 514, 469, 515, + 414, 486, 485, 487, 415, 416, 417, 418, 419, 420, + 421, 422, 423, 424, 0, 0, 0, 0, 0, 610, + 611, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 747, 1017, 0, 752, + 0, 582, 0, 0, 1094, 0, 0, 0, 551, 0, + 0, 455, 0, 0, 0, 1021, 0, 532, 504, 1108, + 0, 0, 530, 467, 566, 516, 572, 554, 580, 523, + 517, 344, 555, 391, 481, 363, 365, 780, 393, 396, + 400, 401, 492, 493, 510, 539, 558, 559, 560, 390, + 377, 531, 378, 410, 379, 345, 382, 381, 383, 541, + 384, 347, 511, 563, 0, 406, 527, 476, 348, 475, + 512, 562, 561, 364, 590, 597, 598, 689, 0, 603, + 794, 795, 796, 612, 0, 518, 360, 357, 0, 0, + 0, 386, 513, 373, 375, 376, 374, 507, 509, 617, + 618, 619, 621, 0, 622, 623, 0, 0, 0, 0, + 624, 690, 708, 674, 643, 605, 698, 640, 644, 645, + 427, 428, 429, 430, 711, 0, 0, 0, 596, 456, + 457, 0, 398, 397, 477, 349, 0, 0, 445, 426, + 519, 355, 394, 447, 432, 458, 459, 460, 461, 462, + 0, 463, 464, 404, 339, 340, 788, 1091, 500, 713, + 750, 751, 635, 0, 1107, 1086, 1088, 1089, 1093, 1097, + 1098, 1099, 1100, 1101, 1103, 1106, 1110, 787, 0, 691, + 705, 792, 704, 784, 506, 0, 538, 702, 649, 0, + 695, 668, 669, 0, 696, 664, 700, 356, 433, 524, + 581, 0, 637, 0, 606, 609, 639, 726, 727, 728, + 346, 608, 730, 731, 732, 733, 734, 735, 736, 729, + 1109, 672, 648, 675, 587, 651, 650, 0, 0, 686, + 1025, 687, 688, 488, 489, 490, 491, 1095, 714, 371, + 607, 521, 522, 0, 673, 0, 0, 0, 0, 0, + 0, 0, 0, 678, 679, 676, 797, 0, 737, 738, + 0, 0, 601, 602, 403, 0, 620, 411, 370, 505, + 405, 585, 436, 0, 613, 680, 614, 525, 526, 741, + 746, 742, 743, 745, 766, 495, 425, 431, 542, 446, + 468, 528, 584, 503, 533, 368, 573, 544, 474, 665, + 693, 1118, 1090, 1117, 1119, 1120, 1116, 1121, 1122, 1102, + 979, 0, 1032, 1033, 1114, 1113, 1115, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 722, 721, + 720, 719, 718, 717, 716, 715, 0, 0, 662, 385, + 785, 779, 786, 767, 770, 769, 744, 986, 341, 642, + 466, 520, 402, 709, 710, 0, 765, 1080, 1043, 1044, + 1045, 976, 1046, 1040, 1041, 977, 1042, 1081, 1030, 1077, + 1078, 1005, 1035, 1047, 1076, 1048, 1079, 1006, 1082, 1123, + 1124, 1054, 1038, 302, 1125, 1051, 1083, 1075, 1074, 1049, + 1031, 1084, 1085, 1013, 1008, 1052, 1053, 1039, 1060, 1061, + 1062, 1065, 978, 1066, 1067, 1068, 1069, 1070, 1064, 1063, + 1027, 1028, 1029, 1055, 1056, 1058, 1059, 1034, 552, 1009, + 1010, 1011, 1012, 0, 0, 591, 592, 593, 616, 0, + 594, 575, 641, 412, 342, 556, 583, 782, 783, 0, + 0, 0, 0, 0, 0, 0, 692, 703, 739, 740, + 0, 753, 754, 756, 758, 1071, 760, 549, 550, 768, + 0, 0, 437, 358, 359, 496, 497, 535, 0, 438, + 439, 440, 444, 441, 442, 443, 1057, 763, 764, 761, + 470, 534, 557, 543, 781, 483, 0, 789, 631, 632, + 790, 749, 748, 343, 0, 1036, 1037, 706, 707, 0, + 0, 1104, 482, 638, 1023, 971, 0, 2813, 0, 0, + 0, 0, 0, 502, 0, 0, 647, 681, 670, 759, + 634, 0, 0, 0, 0, 0, 0, 974, 0, 0, + 0, 395, 0, 0, 465, 685, 666, 677, 667, 508, + 652, 653, 654, 661, 407, 655, 791, 657, 626, 658, + 627, 659, 660, 1014, 684, 633, 545, 484, 0, 701, + 0, 0, 1096, 1105, 0, 0, 0, 0, 0, 0, + 0, 0, 1092, 0, 0, 0, 0, 0, 965, 0, + 0, 1003, 1073, 1072, 990, 1000, 0, 0, 366, 269, + 628, 755, 630, 629, 991, 0, 992, 996, 999, 995, + 993, 994, 0, 1087, 0, 0, 0, 0, 0, 0, + 957, 969, 0, 975, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 966, + 967, 0, 0, 0, 0, 1024, 0, 968, 0, 970, + 0, 0, 0, 0, 546, 574, 0, 588, 0, 434, + 435, 1019, 997, 1001, 0, 0, 0, 0, 350, 553, + 571, 367, 540, 586, 372, 548, 564, 362, 501, 536, + 0, 0, 352, 569, 547, 479, 351, 0, 529, 392, + 409, 389, 499, 998, 0, 1022, 1026, 388, 1111, 1020, + 579, 354, 0, 578, 498, 471, 565, 570, 480, 473, + 0, 353, 567, 478, 472, 448, 399, 1112, 449, 450, + 451, 452, 453, 454, 413, 514, 469, 515, 414, 486, + 485, 487, 415, 416, 417, 418, 419, 420, 421, 422, + 423, 424, 0, 0, 0, 0, 0, 610, 611, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 747, 1017, 0, 752, 0, 582, + 0, 0, 1094, 0, 0, 0, 551, 0, 0, 455, + 0, 0, 0, 1021, 0, 532, 504, 1108, 0, 0, + 530, 467, 566, 516, 572, 554, 580, 523, 517, 344, + 555, 391, 481, 363, 365, 780, 393, 396, 400, 401, + 492, 493, 510, 539, 558, 559, 560, 390, 377, 531, + 378, 410, 379, 345, 382, 381, 383, 541, 384, 347, + 511, 563, 0, 406, 527, 476, 348, 475, 512, 562, + 561, 364, 590, 597, 598, 689, 0, 603, 794, 795, + 796, 612, 0, 518, 360, 357, 0, 0, 0, 386, + 513, 373, 375, 376, 374, 507, 509, 617, 618, 619, + 621, 0, 622, 623, 0, 0, 0, 0, 624, 690, + 708, 674, 643, 605, 698, 640, 644, 645, 427, 428, + 429, 430, 711, 0, 0, 0, 596, 456, 457, 0, + 398, 397, 477, 349, 0, 0, 445, 426, 519, 355, + 394, 447, 432, 458, 459, 460, 461, 462, 0, 463, + 464, 404, 339, 340, 788, 1091, 500, 713, 750, 751, + 635, 0, 1107, 1086, 1088, 1089, 1093, 1097, 1098, 1099, + 1100, 1101, 1103, 1106, 1110, 787, 0, 691, 705, 792, + 704, 784, 506, 0, 538, 702, 649, 0, 695, 668, + 669, 0, 696, 664, 700, 356, 433, 524, 581, 0, + 637, 0, 606, 609, 639, 726, 727, 728, 346, 608, + 730, 731, 732, 733, 734, 735, 736, 729, 1109, 672, + 648, 675, 587, 651, 650, 0, 0, 686, 1025, 687, + 688, 488, 489, 490, 491, 1095, 714, 371, 607, 521, + 522, 0, 673, 0, 0, 0, 0, 0, 0, 0, + 0, 678, 679, 676, 797, 0, 737, 738, 0, 0, + 601, 602, 403, 0, 620, 411, 370, 505, 405, 585, + 436, 0, 613, 680, 614, 525, 526, 741, 746, 742, + 743, 745, 766, 495, 425, 431, 542, 446, 468, 528, + 584, 503, 533, 368, 573, 544, 474, 665, 693, 1118, + 1090, 1117, 1119, 1120, 1116, 1121, 1122, 1102, 979, 0, + 1032, 1033, 1114, 1113, 1115, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 722, 721, 720, 719, + 718, 717, 716, 715, 0, 0, 662, 385, 785, 779, + 786, 767, 770, 769, 744, 986, 341, 642, 466, 520, + 402, 709, 710, 0, 765, 1080, 1043, 1044, 1045, 976, + 1046, 1040, 1041, 977, 1042, 1081, 1030, 1077, 1078, 1005, + 1035, 1047, 1076, 1048, 1079, 1006, 1082, 1123, 1124, 1054, + 1038, 302, 1125, 1051, 1083, 1075, 1074, 1049, 1031, 1084, + 1085, 1013, 1008, 1052, 1053, 1039, 1060, 1061, 1062, 1065, + 978, 1066, 1067, 1068, 1069, 1070, 1064, 1063, 1027, 1028, + 1029, 1055, 1056, 1058, 1059, 1034, 552, 1009, 1010, 1011, + 1012, 0, 0, 591, 592, 593, 616, 0, 594, 575, + 641, 412, 342, 556, 583, 782, 783, 0, 0, 0, + 0, 0, 0, 0, 692, 703, 739, 740, 0, 753, + 754, 756, 758, 1071, 760, 549, 550, 768, 0, 0, + 437, 358, 359, 496, 497, 535, 0, 438, 439, 440, + 444, 441, 442, 443, 1057, 763, 764, 761, 470, 534, + 557, 543, 781, 483, 0, 789, 631, 632, 790, 749, + 748, 343, 0, 1036, 1037, 706, 707, 1023, 0, 1104, + 482, 638, 0, 971, 0, 0, 502, 0, 0, 647, + 681, 670, 759, 634, 0, 0, 0, 0, 0, 0, + 974, 0, 0, 0, 395, 0, 0, 465, 685, 666, + 677, 667, 508, 652, 653, 654, 661, 407, 655, 791, + 657, 626, 658, 627, 659, 660, 1014, 684, 633, 545, + 484, 0, 701, 0, 0, 1096, 1105, 0, 0, 0, + 0, 0, 0, 0, 0, 1092, 0, 0, 0, 0, + 0, 965, 0, 0, 1003, 1073, 1072, 990, 1000, 0, + 0, 366, 269, 628, 755, 630, 629, 991, 0, 992, + 996, 999, 995, 993, 994, 0, 1087, 0, 0, 0, + 0, 0, 0, 957, 969, 0, 975, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 966, 967, 2314, 0, 0, 0, 1024, 0, + 968, 0, 970, 0, 0, 0, 0, 546, 574, 0, + 588, 0, 434, 435, 1019, 997, 1001, 0, 0, 0, + 0, 350, 553, 571, 367, 540, 586, 372, 548, 564, + 362, 501, 536, 0, 0, 352, 569, 547, 479, 351, + 0, 529, 392, 409, 389, 499, 998, 0, 1022, 1026, + 388, 1111, 1020, 579, 354, 0, 578, 498, 471, 565, + 570, 480, 473, 0, 353, 567, 478, 472, 448, 399, + 1112, 449, 450, 451, 452, 453, 454, 413, 514, 469, + 515, 414, 486, 485, 487, 415, 416, 417, 418, 419, + 420, 421, 422, 423, 424, 0, 0, 0, 0, 0, + 610, 611, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 747, 1017, 0, + 752, 0, 582, 0, 0, 1094, 0, 0, 0, 551, + 0, 0, 455, 0, 0, 0, 1021, 0, 532, 504, + 1108, 0, 0, 530, 467, 566, 516, 572, 554, 580, + 523, 517, 344, 555, 391, 481, 363, 365, 780, 393, + 396, 400, 401, 492, 493, 510, 539, 558, 559, 560, + 390, 377, 531, 378, 410, 379, 345, 382, 381, 383, + 541, 384, 347, 511, 563, 0, 406, 527, 476, 348, + 475, 512, 562, 561, 364, 590, 597, 598, 689, 0, + 603, 794, 795, 796, 612, 0, 518, 360, 357, 0, + 0, 0, 386, 513, 373, 375, 376, 374, 507, 509, + 617, 618, 619, 621, 0, 622, 623, 0, 0, 0, + 0, 624, 690, 708, 674, 643, 605, 698, 640, 644, + 645, 427, 428, 429, 430, 711, 0, 0, 0, 596, + 456, 457, 0, 398, 397, 477, 349, 0, 0, 445, + 426, 519, 355, 394, 447, 432, 458, 459, 460, 461, + 462, 0, 463, 464, 404, 339, 340, 788, 1091, 500, + 713, 750, 751, 635, 0, 1107, 1086, 1088, 1089, 1093, + 1097, 1098, 1099, 1100, 1101, 1103, 1106, 1110, 787, 0, + 691, 705, 792, 704, 784, 506, 0, 538, 702, 649, + 0, 695, 668, 669, 0, 696, 664, 700, 356, 433, + 524, 581, 0, 637, 0, 606, 609, 639, 726, 727, + 728, 346, 608, 730, 731, 732, 733, 734, 735, 736, + 729, 1109, 672, 648, 675, 587, 651, 650, 0, 0, + 686, 1025, 687, 688, 488, 489, 490, 491, 1095, 714, + 371, 607, 521, 522, 0, 673, 0, 0, 0, 0, + 0, 0, 0, 0, 678, 679, 676, 797, 0, 737, + 738, 0, 0, 601, 602, 403, 0, 620, 411, 370, + 505, 405, 585, 436, 0, 613, 680, 614, 525, 526, + 741, 746, 742, 743, 745, 766, 495, 425, 431, 542, + 446, 468, 528, 584, 503, 533, 368, 573, 544, 474, + 665, 693, 1118, 1090, 1117, 1119, 1120, 1116, 1121, 1122, + 1102, 979, 0, 1032, 1033, 1114, 1113, 1115, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 722, + 721, 720, 719, 718, 717, 716, 715, 0, 0, 662, + 385, 785, 779, 786, 767, 770, 769, 744, 986, 341, + 642, 466, 520, 402, 709, 710, 0, 765, 1080, 1043, + 1044, 1045, 976, 1046, 1040, 1041, 977, 1042, 1081, 1030, + 1077, 1078, 1005, 1035, 1047, 1076, 1048, 1079, 1006, 1082, + 1123, 1124, 1054, 1038, 302, 1125, 1051, 1083, 1075, 1074, + 1049, 1031, 1084, 1085, 1013, 1008, 1052, 1053, 1039, 1060, + 1061, 1062, 1065, 978, 1066, 1067, 1068, 1069, 1070, 1064, + 1063, 1027, 1028, 1029, 1055, 1056, 1058, 1059, 1034, 552, + 1009, 1010, 1011, 1012, 0, 0, 591, 592, 593, 616, + 0, 594, 575, 641, 412, 342, 556, 583, 782, 783, + 0, 0, 0, 0, 0, 0, 0, 692, 703, 739, + 740, 0, 753, 754, 756, 758, 1071, 760, 549, 550, + 768, 0, 0, 437, 358, 359, 496, 497, 535, 0, + 438, 439, 440, 444, 441, 442, 443, 1057, 763, 764, + 761, 470, 534, 557, 543, 781, 483, 0, 789, 631, + 632, 790, 749, 748, 343, 0, 1036, 1037, 706, 707, + 1023, 0, 1104, 482, 638, 0, 971, 0, 0, 502, + 0, 0, 647, 681, 670, 759, 634, 0, 0, 0, + 0, 0, 0, 974, 0, 0, 0, 395, 0, 0, + 465, 685, 666, 677, 667, 508, 652, 653, 654, 661, + 407, 655, 791, 657, 626, 658, 627, 659, 660, 1014, + 684, 633, 545, 484, 0, 701, 0, 0, 1096, 1105, + 0, 0, 0, 0, 0, 0, 0, 0, 1092, 0, + 0, 0, 0, 0, 965, 0, 0, 1003, 1073, 1072, + 990, 1000, 0, 0, 366, 269, 628, 755, 630, 629, + 991, 0, 992, 996, 999, 995, 993, 994, 0, 1087, + 0, 0, 0, 0, 0, 0, 957, 969, 0, 975, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 966, 967, 0, 0, 0, + 0, 1024, 0, 968, 0, 970, 0, 0, 0, 0, + 546, 574, 0, 588, 0, 434, 435, 1019, 997, 1001, + 0, 0, 0, 0, 350, 553, 571, 367, 540, 586, + 372, 548, 564, 362, 501, 536, 0, 0, 352, 569, + 547, 479, 351, 0, 529, 392, 409, 389, 499, 998, + 0, 1022, 1026, 388, 1111, 1020, 579, 354, 0, 578, + 498, 471, 565, 570, 480, 473, 0, 353, 567, 478, + 472, 448, 399, 1112, 449, 450, 451, 452, 453, 454, + 413, 514, 469, 515, 414, 486, 485, 487, 415, 416, + 417, 418, 419, 420, 421, 422, 423, 424, 0, 0, + 0, 0, 0, 610, 611, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 747, 1017, 0, 752, 0, 582, 0, 0, 1094, 0, + 0, 0, 551, 0, 0, 455, 0, 0, 0, 1021, + 0, 532, 504, 1108, 0, 0, 530, 467, 566, 516, + 572, 554, 580, 523, 517, 344, 555, 391, 481, 363, + 365, 780, 393, 396, 400, 401, 492, 493, 510, 539, + 558, 559, 560, 390, 377, 531, 378, 410, 379, 345, + 382, 381, 383, 541, 384, 347, 511, 563, 0, 406, + 527, 476, 348, 475, 512, 562, 561, 364, 590, 597, + 598, 689, 0, 603, 794, 795, 796, 612, 0, 518, + 360, 357, 0, 0, 0, 386, 513, 373, 375, 376, + 374, 507, 509, 617, 618, 619, 621, 0, 622, 623, + 0, 0, 0, 0, 624, 690, 708, 674, 643, 605, + 698, 640, 644, 645, 427, 428, 429, 430, 711, 0, + 0, 0, 596, 456, 457, 0, 398, 397, 477, 349, + 0, 0, 445, 426, 519, 355, 394, 447, 432, 458, + 459, 460, 461, 462, 0, 463, 464, 404, 339, 340, + 788, 1091, 500, 713, 750, 751, 635, 0, 1107, 1086, + 1088, 1089, 1093, 1097, 1098, 1099, 1100, 1101, 1103, 1106, + 1110, 787, 0, 691, 705, 792, 704, 784, 506, 0, + 538, 702, 649, 0, 695, 668, 669, 0, 696, 664, + 700, 356, 433, 524, 581, 0, 637, 0, 606, 609, + 639, 726, 727, 728, 346, 608, 730, 731, 732, 733, + 734, 735, 736, 729, 1109, 672, 648, 675, 587, 651, + 650, 0, 0, 686, 1025, 687, 688, 488, 489, 490, + 491, 1095, 714, 371, 607, 521, 522, 0, 673, 0, + 0, 0, 0, 0, 0, 0, 0, 678, 679, 676, + 797, 0, 737, 738, 0, 0, 601, 602, 403, 0, + 620, 411, 370, 505, 405, 585, 436, 0, 613, 680, + 614, 525, 526, 741, 746, 742, 743, 745, 766, 495, + 425, 431, 542, 446, 468, 528, 584, 503, 533, 368, + 573, 544, 474, 665, 693, 1118, 1090, 1117, 1119, 1120, + 1116, 1121, 1122, 1102, 979, 0, 1032, 1033, 1114, 1113, + 1115, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 722, 721, 720, 719, 718, 717, 716, 715, + 0, 0, 662, 385, 785, 779, 786, 767, 770, 769, + 744, 986, 341, 642, 466, 520, 402, 709, 710, 0, + 765, 1080, 1043, 1044, 1045, 976, 1046, 1040, 1041, 977, + 1042, 1081, 1030, 1077, 1078, 1005, 1035, 1047, 1076, 1048, + 1079, 1006, 1082, 1123, 1124, 1054, 1038, 302, 1125, 1051, + 1083, 1075, 1074, 1049, 1031, 1084, 1085, 1013, 1008, 1052, + 1053, 1039, 1060, 1061, 1062, 1065, 978, 1066, 1067, 1068, + 1069, 1070, 1064, 1063, 1027, 1028, 1029, 1055, 1056, 1058, + 1059, 1034, 552, 1009, 1010, 1011, 1012, 0, 0, 591, + 592, 593, 616, 0, 594, 575, 641, 412, 342, 556, + 583, 782, 783, 0, 0, 0, 0, 0, 0, 0, + 692, 703, 739, 740, 0, 753, 754, 756, 758, 1071, + 760, 549, 550, 768, 0, 0, 437, 358, 359, 496, + 497, 535, 0, 438, 439, 440, 444, 441, 442, 443, + 1057, 763, 764, 761, 470, 534, 557, 543, 781, 483, + 0, 789, 631, 632, 790, 749, 748, 343, 0, 1036, + 1037, 706, 707, 1023, 0, 1104, 482, 638, 0, 971, + 0, 0, 502, 0, 0, 647, 681, 670, 759, 634, + 0, 0, 0, 0, 0, 0, 974, 0, 0, 0, + 395, 0, 0, 465, 685, 666, 677, 667, 508, 652, + 653, 654, 661, 407, 655, 791, 657, 626, 658, 627, + 659, 660, 1014, 684, 633, 545, 484, 0, 701, 0, + 0, 1096, 1105, 0, 0, 0, 0, 0, 0, 0, + 0, 1092, 0, 0, 0, 0, 0, 965, 0, 0, + 1003, 1073, 1072, 990, 1000, 0, 0, 366, 269, 628, + 755, 630, 629, 991, 0, 992, 996, 999, 995, 993, + 994, 0, 1087, 0, 0, 0, 0, 0, 0, 957, + 969, 0, 975, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 966, 967, + 0, 0, 0, 0, 1024, 0, 968, 0, 970, 0, + 0, 0, 0, 546, 574, 0, 588, 0, 434, 435, + 1019, 997, 1001, 0, 0, 0, 0, 350, 553, 571, + 367, 540, 586, 372, 548, 564, 362, 501, 536, 0, + 0, 352, 569, 547, 479, 351, 0, 529, 392, 409, + 389, 499, 998, 0, 1022, 1026, 388, 1111, 1020, 579, + 354, 0, 578, 498, 471, 565, 570, 480, 473, 0, + 353, 567, 478, 472, 448, 399, 1112, 449, 450, 451, + 452, 453, 454, 413, 514, 469, 515, 414, 486, 485, + 487, 415, 416, 417, 418, 419, 420, 421, 422, 423, + 424, 0, 0, 0, 0, 0, 610, 611, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 747, 1017, 0, 752, 0, 582, 0, + 0, 1094, 0, 0, 0, 551, 0, 0, 455, 0, + 0, 0, 1021, 0, 532, 504, 1108, 0, 0, 530, + 467, 566, 516, 572, 554, 580, 523, 517, 344, 555, + 391, 481, 363, 365, 780, 393, 396, 400, 401, 492, + 493, 510, 539, 558, 559, 560, 390, 377, 531, 378, + 410, 379, 345, 382, 381, 383, 541, 384, 347, 511, + 563, 0, 406, 527, 476, 348, 475, 512, 562, 561, + 364, 590, 597, 598, 689, 0, 603, 794, 795, 796, + 612, 0, 518, 360, 357, 0, 0, 0, 386, 513, + 373, 375, 376, 374, 507, 509, 617, 618, 619, 621, + 0, 622, 623, 0, 0, 0, 0, 624, 690, 708, + 674, 643, 605, 698, 640, 644, 645, 427, 428, 429, + 430, 711, 0, 0, 0, 596, 456, 457, 0, 398, + 397, 477, 349, 0, 0, 445, 426, 519, 355, 394, + 447, 432, 458, 459, 460, 461, 462, 0, 463, 464, + 404, 339, 340, 788, 1091, 500, 713, 750, 751, 635, + 0, 1107, 1086, 1088, 1089, 1093, 1097, 1098, 1099, 1100, + 1101, 1103, 1106, 1110, 787, 0, 691, 705, 792, 704, + 784, 506, 0, 538, 702, 649, 0, 695, 668, 669, + 0, 696, 664, 700, 356, 433, 524, 581, 0, 637, + 0, 606, 609, 639, 726, 727, 728, 346, 608, 730, + 731, 732, 733, 734, 735, 736, 729, 1109, 672, 648, + 675, 587, 651, 650, 0, 0, 686, 1025, 687, 688, + 488, 489, 490, 491, 1095, 714, 371, 607, 521, 522, + 0, 673, 0, 0, 0, 0, 0, 0, 0, 0, + 678, 679, 676, 797, 0, 737, 738, 0, 0, 601, + 602, 403, 0, 620, 411, 370, 505, 405, 585, 436, + 0, 613, 680, 614, 525, 526, 741, 746, 742, 743, + 745, 766, 495, 425, 431, 542, 446, 468, 528, 584, + 503, 533, 368, 573, 544, 474, 665, 693, 1118, 1090, + 1117, 1119, 1120, 1116, 1121, 1122, 1102, 979, 0, 1032, + 1033, 1114, 1113, 1115, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 722, 721, 720, 719, 718, + 717, 716, 715, 0, 0, 662, 385, 785, 779, 786, + 767, 770, 769, 744, 986, 341, 642, 466, 520, 402, + 709, 710, 0, 765, 1080, 1043, 1044, 1045, 976, 1046, + 1040, 1041, 977, 1042, 1081, 1030, 1077, 1078, 1005, 1035, + 1047, 1076, 1048, 1079, 1006, 1082, 1123, 1124, 1054, 1038, + 302, 1125, 1051, 1083, 1075, 1074, 1049, 1031, 1084, 1085, + 1013, 1008, 1052, 1053, 1039, 1060, 1061, 1062, 1065, 978, + 1066, 1067, 1068, 1069, 1070, 1064, 1063, 1027, 1028, 1029, + 1055, 1056, 1058, 1059, 1034, 552, 1009, 1010, 1011, 1012, + 0, 0, 591, 592, 593, 616, 0, 594, 575, 641, + 412, 342, 556, 583, 782, 783, 0, 0, 0, 0, + 0, 0, 0, 692, 703, 739, 740, 0, 753, 754, + 756, 758, 1071, 760, 549, 550, 768, 0, 0, 437, + 358, 359, 496, 497, 535, 0, 438, 439, 440, 444, + 441, 442, 443, 4757, 763, 4758, 4759, 470, 534, 557, + 543, 781, 483, 0, 789, 631, 632, 790, 749, 748, + 343, 0, 1036, 1037, 706, 707, 1023, 0, 1104, 482, + 638, 0, 971, 0, 0, 502, 0, 0, 647, 681, + 670, 759, 634, 0, 0, 0, 0, 0, 0, 974, + 0, 0, 0, 395, 0, 0, 465, 685, 666, 677, + 667, 508, 652, 653, 654, 661, 407, 655, 791, 657, + 626, 658, 627, 659, 660, 1014, 684, 633, 545, 484, + 0, 701, 0, 0, 1096, 1105, 0, 0, 0, 0, + 0, 0, 0, 0, 1092, 0, 0, 0, 0, 0, + 965, 0, 0, 1003, 1073, 1072, 990, 1000, 0, 0, + 366, 269, 628, 755, 630, 629, 3379, 0, 3380, 996, + 999, 995, 993, 994, 0, 1087, 0, 0, 0, 0, + 0, 0, 957, 969, 0, 975, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 966, 967, 0, 0, 0, 0, 1024, 0, 968, + 0, 970, 0, 0, 0, 0, 546, 574, 0, 588, + 0, 434, 435, 1019, 997, 1001, 0, 0, 0, 0, + 350, 553, 571, 367, 540, 586, 372, 548, 564, 362, + 501, 536, 0, 0, 352, 569, 547, 479, 351, 0, + 529, 392, 409, 389, 499, 998, 0, 1022, 1026, 388, + 1111, 1020, 579, 354, 0, 578, 498, 471, 565, 570, + 480, 473, 0, 353, 567, 478, 472, 448, 399, 1112, + 449, 450, 451, 452, 453, 454, 413, 514, 469, 515, + 414, 486, 485, 487, 415, 416, 417, 418, 419, 420, + 421, 422, 423, 424, 0, 0, 0, 0, 0, 610, + 611, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 747, 1017, 0, 752, + 0, 582, 0, 0, 1094, 0, 0, 0, 551, 0, + 0, 455, 0, 0, 0, 1021, 0, 532, 504, 1108, + 0, 0, 530, 467, 566, 516, 572, 554, 580, 523, + 517, 344, 555, 391, 481, 363, 365, 780, 393, 396, + 400, 401, 492, 493, 510, 539, 558, 559, 560, 390, + 377, 531, 378, 410, 379, 345, 382, 381, 383, 541, + 384, 347, 511, 563, 0, 406, 527, 476, 348, 475, + 512, 562, 561, 364, 590, 597, 598, 689, 0, 603, + 794, 795, 796, 612, 0, 518, 360, 357, 0, 0, + 0, 386, 513, 373, 375, 376, 374, 507, 509, 617, + 618, 619, 621, 0, 622, 623, 0, 0, 0, 0, + 624, 690, 708, 674, 643, 605, 698, 640, 644, 645, + 427, 428, 429, 430, 711, 0, 0, 0, 596, 456, + 457, 0, 398, 397, 477, 349, 0, 0, 445, 426, + 519, 355, 394, 447, 432, 458, 459, 460, 461, 462, + 0, 463, 464, 404, 339, 340, 788, 1091, 500, 713, + 750, 751, 635, 0, 1107, 1086, 1088, 1089, 1093, 1097, + 1098, 1099, 1100, 1101, 1103, 1106, 1110, 787, 0, 691, + 705, 792, 704, 784, 506, 0, 538, 702, 649, 0, + 695, 668, 669, 0, 696, 664, 700, 356, 433, 524, + 581, 0, 637, 0, 606, 609, 639, 726, 727, 728, + 346, 608, 730, 731, 732, 733, 734, 735, 736, 729, + 1109, 672, 648, 675, 587, 651, 650, 0, 0, 686, + 1025, 687, 688, 488, 489, 490, 491, 1095, 714, 371, + 607, 521, 522, 0, 673, 0, 0, 0, 0, 0, + 0, 0, 0, 678, 679, 676, 797, 0, 737, 738, + 0, 0, 601, 602, 403, 0, 620, 411, 370, 505, + 405, 585, 436, 0, 613, 680, 614, 525, 526, 741, + 746, 742, 743, 745, 766, 495, 425, 431, 542, 446, + 468, 528, 584, 503, 533, 368, 573, 544, 474, 665, + 693, 1118, 1090, 1117, 1119, 1120, 1116, 1121, 1122, 1102, + 979, 0, 1032, 1033, 1114, 1113, 1115, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 722, 721, + 720, 719, 718, 717, 716, 715, 0, 0, 662, 385, + 785, 779, 786, 767, 770, 769, 744, 986, 341, 642, + 466, 520, 402, 709, 710, 0, 765, 1080, 1043, 1044, + 1045, 976, 1046, 1040, 1041, 977, 1042, 1081, 1030, 1077, + 1078, 1005, 1035, 1047, 1076, 1048, 1079, 1006, 1082, 1123, + 1124, 1054, 1038, 302, 1125, 1051, 1083, 1075, 1074, 1049, + 1031, 1084, 1085, 1013, 1008, 1052, 1053, 1039, 1060, 1061, + 1062, 1065, 978, 1066, 1067, 1068, 1069, 1070, 1064, 1063, + 1027, 1028, 1029, 1055, 1056, 1058, 1059, 1034, 552, 1009, + 1010, 1011, 1012, 0, 0, 591, 592, 593, 616, 0, + 594, 575, 641, 412, 342, 556, 583, 782, 783, 0, + 0, 0, 0, 0, 0, 0, 692, 703, 739, 740, + 0, 753, 754, 756, 758, 1071, 760, 549, 550, 768, + 0, 0, 437, 358, 359, 496, 497, 535, 0, 438, + 439, 440, 444, 441, 442, 443, 1057, 763, 764, 761, + 470, 534, 557, 543, 781, 483, 0, 789, 631, 632, + 790, 749, 748, 343, 0, 1036, 1037, 706, 707, 1023, + 0, 1104, 482, 638, 0, 971, 0, 0, 502, 0, + 0, 647, 681, 670, 759, 634, 0, 0, 2144, 0, + 0, 0, 974, 0, 0, 0, 395, 0, 0, 465, + 685, 666, 677, 667, 508, 652, 653, 654, 661, 407, + 655, 791, 657, 626, 658, 627, 659, 660, 1014, 684, + 633, 545, 484, 0, 701, 0, 0, 1096, 1105, 0, + 0, 0, 0, 0, 0, 0, 0, 1092, 0, 0, + 0, 0, 0, 965, 0, 0, 1003, 1073, 1072, 990, + 1000, 0, 0, 366, 269, 628, 755, 630, 629, 991, + 0, 992, 996, 999, 995, 993, 994, 0, 1087, 0, + 0, 0, 0, 0, 0, 0, 969, 0, 975, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 966, 967, 0, 0, 0, 0, + 1024, 0, 968, 0, 970, 0, 0, 0, 0, 546, + 574, 0, 588, 0, 434, 435, 1019, 997, 1001, 0, + 0, 0, 0, 350, 553, 571, 367, 540, 586, 372, + 548, 564, 362, 501, 536, 0, 0, 352, 569, 547, + 479, 351, 0, 529, 392, 409, 389, 499, 998, 0, + 1022, 1026, 388, 1111, 1020, 579, 354, 0, 578, 498, + 471, 565, 570, 480, 473, 0, 353, 567, 478, 472, + 448, 399, 1112, 449, 450, 451, 452, 453, 454, 413, + 514, 469, 515, 414, 486, 485, 487, 415, 416, 417, + 418, 419, 420, 421, 422, 423, 424, 0, 0, 0, + 0, 0, 610, 611, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 747, + 1017, 0, 752, 0, 582, 0, 0, 1094, 0, 0, + 0, 551, 0, 0, 455, 0, 0, 0, 1021, 0, + 532, 504, 1108, 0, 0, 530, 467, 566, 516, 572, + 554, 580, 523, 517, 344, 555, 391, 481, 363, 365, + 780, 393, 396, 400, 401, 492, 493, 510, 539, 558, + 559, 560, 390, 377, 531, 378, 410, 379, 345, 382, + 381, 383, 541, 384, 347, 511, 563, 0, 406, 527, + 476, 348, 475, 512, 562, 561, 364, 590, 2145, 2146, + 689, 0, 603, 794, 795, 796, 612, 0, 518, 360, + 357, 0, 0, 0, 386, 513, 373, 375, 376, 374, + 507, 509, 617, 618, 619, 621, 0, 622, 623, 0, + 0, 0, 0, 624, 690, 708, 674, 643, 605, 698, + 640, 644, 645, 427, 428, 429, 430, 711, 0, 0, + 0, 596, 456, 457, 0, 398, 397, 477, 349, 0, + 0, 445, 426, 519, 355, 394, 447, 432, 458, 459, + 460, 461, 462, 0, 463, 464, 404, 339, 340, 788, + 1091, 500, 713, 750, 751, 635, 0, 1107, 1086, 1088, + 1089, 1093, 1097, 1098, 1099, 1100, 1101, 1103, 1106, 1110, + 787, 0, 691, 705, 792, 704, 784, 506, 0, 538, + 702, 649, 0, 695, 668, 669, 0, 696, 664, 700, + 356, 433, 524, 581, 0, 637, 0, 606, 609, 639, + 726, 727, 728, 346, 608, 730, 731, 732, 733, 734, + 735, 736, 729, 1109, 672, 648, 675, 587, 651, 650, + 0, 0, 686, 1025, 687, 688, 488, 489, 490, 491, + 1095, 714, 371, 607, 521, 522, 0, 673, 0, 0, + 0, 0, 0, 0, 0, 0, 678, 679, 676, 797, + 0, 737, 738, 0, 0, 601, 602, 403, 0, 620, + 411, 370, 505, 405, 585, 436, 0, 613, 680, 614, + 525, 526, 741, 746, 742, 743, 745, 766, 495, 425, + 431, 542, 446, 468, 528, 584, 503, 533, 368, 573, + 544, 474, 665, 693, 1118, 1090, 1117, 1119, 1120, 1116, + 1121, 1122, 1102, 979, 0, 1032, 1033, 1114, 1113, 1115, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 722, 721, 720, 719, 718, 717, 716, 715, 0, + 0, 662, 385, 785, 779, 786, 767, 770, 769, 744, + 986, 341, 642, 466, 520, 402, 709, 710, 0, 765, + 1080, 1043, 1044, 1045, 976, 1046, 1040, 1041, 977, 1042, + 1081, 1030, 1077, 1078, 1005, 1035, 1047, 1076, 1048, 1079, + 1006, 1082, 1123, 1124, 1054, 1038, 302, 1125, 1051, 1083, + 1075, 1074, 1049, 1031, 1084, 1085, 1013, 1008, 1052, 1053, + 1039, 1060, 1061, 1062, 1065, 978, 1066, 1067, 1068, 1069, + 1070, 1064, 1063, 1027, 1028, 1029, 1055, 1056, 1058, 1059, + 1034, 552, 1009, 1010, 1011, 1012, 0, 0, 591, 592, + 593, 616, 0, 594, 575, 641, 412, 342, 556, 583, + 782, 783, 0, 0, 0, 0, 0, 0, 0, 692, + 703, 739, 740, 0, 753, 754, 756, 758, 1071, 760, + 549, 550, 768, 0, 0, 437, 358, 359, 496, 497, + 535, 0, 438, 439, 440, 444, 441, 442, 443, 1057, + 763, 764, 761, 470, 534, 557, 543, 781, 483, 0, + 789, 631, 632, 790, 749, 748, 343, 0, 1036, 1037, + 706, 707, 1023, 0, 1104, 482, 638, 0, 971, 0, + 0, 502, 0, 0, 647, 681, 670, 759, 634, 0, + 0, 0, 0, 0, 0, 974, 0, 0, 0, 395, + 0, 0, 465, 685, 666, 677, 667, 508, 652, 653, + 654, 661, 407, 655, 791, 657, 626, 658, 627, 659, + 660, 1014, 684, 633, 545, 484, 0, 701, 0, 0, + 1096, 1105, 0, 0, 0, 0, 0, 0, 0, 0, + 1092, 0, 0, 0, 0, 0, 1627, 0, 0, 1003, + 1073, 1072, 990, 1000, 0, 0, 366, 269, 628, 755, + 630, 629, 991, 0, 992, 996, 999, 995, 993, 994, + 0, 1087, 0, 0, 0, 0, 0, 0, 957, 969, + 0, 975, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 966, 967, 0, + 0, 0, 0, 1024, 0, 968, 0, 970, 0, 0, + 0, 0, 546, 574, 0, 588, 0, 434, 435, 1019, + 997, 1001, 0, 0, 0, 0, 350, 553, 571, 367, + 540, 586, 372, 548, 564, 362, 501, 536, 0, 0, + 352, 569, 547, 479, 351, 0, 529, 392, 409, 389, + 499, 998, 0, 1022, 1026, 388, 1111, 1020, 579, 354, + 0, 578, 498, 471, 565, 570, 480, 473, 0, 353, + 567, 478, 472, 448, 399, 1112, 449, 450, 451, 452, + 453, 454, 413, 514, 469, 515, 414, 486, 485, 487, + 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, + 0, 0, 0, 0, 0, 610, 611, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 747, 1017, 0, 752, 0, 582, 0, 0, + 1094, 0, 0, 0, 551, 0, 0, 455, 0, 0, + 0, 1021, 0, 532, 504, 1108, 0, 0, 530, 467, + 566, 516, 572, 554, 580, 523, 517, 344, 555, 391, + 481, 363, 365, 780, 393, 396, 400, 401, 492, 493, + 510, 539, 558, 559, 560, 390, 377, 531, 378, 410, + 379, 345, 382, 381, 383, 541, 384, 347, 511, 563, + 0, 406, 527, 476, 348, 475, 512, 562, 561, 364, + 590, 597, 598, 689, 0, 603, 794, 795, 796, 612, + 0, 518, 360, 357, 0, 0, 0, 386, 513, 373, + 375, 376, 374, 507, 509, 617, 618, 619, 621, 0, + 622, 623, 0, 0, 0, 0, 624, 690, 708, 674, + 643, 605, 698, 640, 644, 645, 427, 428, 429, 430, + 711, 0, 0, 0, 596, 456, 457, 0, 398, 397, + 477, 349, 0, 0, 445, 426, 519, 355, 394, 447, + 432, 458, 459, 460, 461, 462, 0, 463, 464, 404, + 339, 340, 788, 1091, 500, 713, 750, 751, 635, 0, + 1107, 1086, 1088, 1089, 1093, 1097, 1098, 1099, 1100, 1101, + 1103, 1106, 1110, 787, 0, 691, 705, 792, 704, 784, + 506, 0, 538, 702, 649, 0, 695, 668, 669, 0, + 696, 664, 700, 356, 433, 524, 581, 0, 637, 0, + 606, 609, 639, 726, 727, 728, 346, 608, 730, 731, + 732, 733, 734, 735, 736, 729, 1109, 672, 648, 675, + 587, 651, 650, 0, 0, 686, 1025, 687, 688, 488, + 489, 490, 491, 1095, 714, 371, 607, 521, 522, 0, + 673, 0, 0, 0, 0, 0, 0, 0, 0, 678, + 679, 676, 797, 0, 737, 738, 0, 0, 601, 602, + 403, 0, 620, 411, 370, 505, 405, 585, 436, 0, + 613, 680, 614, 525, 526, 741, 746, 742, 743, 745, + 766, 495, 425, 431, 542, 446, 468, 528, 584, 503, + 533, 368, 573, 544, 474, 665, 693, 1118, 1090, 1117, + 1119, 1120, 1116, 1121, 1122, 1102, 979, 0, 1032, 1033, + 1114, 1113, 1115, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 722, 721, 720, 719, 718, 717, + 716, 715, 0, 0, 662, 385, 785, 779, 786, 767, + 770, 769, 744, 986, 341, 642, 466, 520, 402, 709, + 710, 0, 765, 1080, 1043, 1044, 1045, 976, 1046, 1040, + 1041, 977, 1042, 1081, 1030, 1077, 1078, 1005, 1035, 1047, + 1076, 1048, 1079, 1006, 1082, 1123, 1124, 1054, 1038, 302, + 1125, 1051, 1083, 1075, 1074, 1049, 1031, 1084, 1085, 1013, + 1008, 1052, 1053, 1039, 1060, 1061, 1062, 1065, 978, 1066, + 1067, 1068, 1069, 1070, 1064, 1063, 1027, 1028, 1029, 1055, + 1056, 1058, 1059, 1034, 552, 1009, 1010, 1011, 1012, 0, + 0, 591, 592, 593, 616, 0, 594, 575, 641, 412, + 342, 556, 583, 782, 783, 0, 0, 0, 0, 0, + 0, 0, 692, 703, 739, 740, 0, 753, 754, 756, + 758, 1071, 760, 549, 550, 768, 0, 0, 437, 358, + 359, 496, 497, 535, 0, 438, 439, 440, 444, 441, + 442, 443, 1057, 763, 764, 761, 470, 534, 557, 543, + 781, 483, 0, 789, 631, 632, 790, 749, 748, 343, + 0, 1036, 1037, 706, 707, 1023, 0, 1104, 482, 638, + 0, 971, 0, 0, 502, 0, 0, 647, 681, 670, + 759, 634, 0, 0, 0, 0, 0, 0, 974, 0, + 0, 0, 395, 0, 0, 465, 685, 666, 677, 667, + 508, 652, 653, 654, 661, 407, 655, 791, 657, 626, + 658, 627, 659, 660, 1014, 684, 633, 545, 484, 0, + 701, 0, 0, 1096, 1105, 0, 0, 0, 0, 0, + 0, 0, 0, 1092, 0, 0, 0, 0, 0, 965, + 0, 0, 1003, 1073, 1072, 990, 1000, 0, 0, 366, + 269, 628, 755, 630, 629, 991, 0, 992, 996, 999, + 995, 993, 994, 0, 1087, 0, 0, 0, 0, 0, + 0, 0, 969, 0, 975, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 966, 967, 0, 0, 0, 0, 1024, 0, 968, 0, + 970, 0, 0, 0, 0, 546, 574, 0, 588, 0, + 434, 435, 1019, 997, 1001, 0, 0, 0, 0, 350, + 553, 571, 367, 540, 586, 372, 548, 564, 362, 501, + 536, 0, 0, 352, 569, 547, 479, 351, 0, 529, + 392, 409, 389, 499, 998, 0, 1022, 1026, 388, 1111, + 1020, 579, 354, 0, 578, 498, 471, 565, 570, 480, + 473, 0, 353, 567, 478, 472, 448, 399, 1112, 449, + 450, 451, 452, 453, 454, 413, 514, 469, 515, 414, + 486, 485, 487, 415, 416, 417, 418, 419, 420, 421, + 422, 423, 424, 0, 0, 0, 0, 0, 610, 611, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 747, 1017, 0, 752, 0, + 582, 0, 0, 1094, 0, 0, 0, 551, 0, 0, + 455, 0, 0, 0, 1021, 0, 532, 504, 1108, 0, + 0, 530, 467, 566, 516, 572, 554, 580, 523, 517, + 344, 555, 391, 481, 363, 365, 780, 393, 396, 400, + 401, 492, 493, 510, 539, 558, 559, 560, 390, 377, + 531, 378, 410, 379, 345, 382, 381, 383, 541, 384, + 347, 511, 563, 0, 406, 527, 476, 348, 475, 512, + 562, 561, 364, 590, 597, 598, 689, 0, 603, 794, + 795, 796, 612, 0, 518, 360, 357, 0, 0, 0, + 386, 513, 373, 375, 376, 374, 507, 509, 617, 618, + 619, 621, 0, 622, 623, 0, 0, 0, 0, 624, + 690, 708, 674, 643, 605, 698, 640, 644, 645, 427, + 428, 429, 430, 711, 0, 0, 0, 596, 456, 457, + 0, 398, 397, 477, 349, 0, 0, 445, 426, 519, + 355, 394, 447, 432, 458, 459, 460, 461, 462, 0, + 463, 464, 404, 339, 340, 788, 1091, 500, 713, 750, + 751, 635, 0, 1107, 1086, 1088, 1089, 1093, 1097, 1098, + 1099, 1100, 1101, 1103, 1106, 1110, 787, 0, 691, 705, + 792, 704, 784, 506, 0, 538, 702, 649, 0, 695, + 668, 669, 0, 696, 664, 700, 356, 433, 524, 581, + 0, 637, 0, 606, 609, 639, 726, 727, 728, 346, + 608, 730, 731, 732, 733, 734, 735, 736, 729, 1109, + 672, 648, 675, 587, 651, 650, 0, 0, 686, 1025, + 687, 688, 488, 489, 490, 491, 1095, 714, 371, 607, + 521, 522, 0, 673, 0, 0, 0, 0, 0, 0, + 0, 0, 678, 679, 676, 797, 0, 737, 738, 0, + 0, 601, 602, 403, 0, 620, 411, 370, 505, 405, + 585, 436, 0, 613, 680, 614, 525, 526, 741, 746, + 742, 743, 745, 766, 495, 425, 431, 542, 446, 468, + 528, 584, 503, 533, 368, 573, 544, 474, 665, 693, + 1118, 1090, 1117, 1119, 1120, 1116, 1121, 1122, 1102, 979, + 0, 1032, 1033, 1114, 1113, 1115, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 722, 721, 720, + 719, 718, 717, 716, 715, 0, 0, 662, 385, 785, + 779, 786, 767, 770, 769, 744, 986, 341, 642, 466, + 520, 402, 709, 710, 0, 765, 1080, 1043, 1044, 1045, + 976, 1046, 1040, 1041, 977, 1042, 1081, 1030, 1077, 1078, + 1005, 1035, 1047, 1076, 1048, 1079, 1006, 1082, 1123, 1124, + 1054, 1038, 302, 1125, 1051, 1083, 1075, 1074, 1049, 1031, + 1084, 1085, 1013, 1008, 1052, 1053, 1039, 1060, 1061, 1062, + 1065, 978, 1066, 1067, 1068, 1069, 1070, 1064, 1063, 1027, + 1028, 1029, 1055, 1056, 1058, 1059, 1034, 552, 1009, 1010, + 1011, 1012, 0, 0, 591, 592, 593, 616, 0, 594, + 575, 641, 412, 342, 556, 583, 782, 783, 0, 0, + 0, 0, 0, 0, 0, 692, 703, 739, 740, 0, + 753, 754, 756, 758, 1071, 760, 549, 550, 768, 0, + 0, 437, 358, 359, 496, 497, 535, 0, 438, 439, + 440, 444, 441, 442, 443, 1057, 763, 764, 761, 470, + 534, 557, 543, 781, 483, 0, 789, 631, 632, 790, + 749, 748, 343, 0, 1036, 1037, 706, 707, 0, 0, + 1104, 482, 638, 0, 971, 200, 245, 199, 232, 201, + 0, 0, 0, 0, 0, 0, 502, 0, 0, 647, + 681, 670, 759, 634, 0, 233, 0, 0, 0, 0, + 0, 0, 225, 0, 395, 0, 234, 465, 685, 666, + 677, 667, 508, 652, 653, 654, 661, 407, 655, 656, + 657, 626, 658, 627, 659, 660, 169, 684, 633, 545, + 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, + 0, 154, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 268, 0, 0, 0, 0, 0, + 0, 366, 269, 628, 755, 630, 629, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 369, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 260, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 546, 574, 0, + 588, 0, 434, 435, 0, 0, 0, 0, 0, 0, + 0, 350, 553, 571, 367, 540, 586, 372, 548, 564, + 362, 501, 536, 0, 0, 352, 569, 547, 479, 351, + 0, 529, 392, 409, 389, 499, 0, 0, 568, 599, + 388, 589, 0, 579, 354, 0, 578, 498, 471, 565, + 570, 480, 473, 0, 353, 567, 478, 472, 448, 399, + 615, 449, 450, 451, 452, 453, 454, 413, 514, 469, + 515, 414, 486, 485, 487, 415, 416, 417, 418, 419, + 420, 421, 422, 423, 424, 0, 0, 0, 0, 0, + 610, 611, 0, 0, 0, 0, 0, 0, 0, 198, + 230, 242, 231, 84, 150, 0, 0, 747, 0, 246, + 752, 0, 582, 0, 0, 261, 0, 0, 0, 551, + 0, 0, 455, 152, 224, 223, 600, 0, 532, 504, + 274, 0, 0, 530, 467, 566, 516, 572, 554, 580, + 523, 517, 344, 555, 391, 481, 363, 365, 283, 393, + 396, 400, 401, 492, 493, 510, 539, 558, 559, 560, + 390, 377, 531, 378, 410, 379, 345, 382, 381, 383, + 541, 384, 347, 511, 563, 151, 406, 527, 476, 348, + 475, 512, 562, 561, 364, 590, 597, 598, 689, 0, + 603, 723, 724, 725, 612, 0, 518, 360, 357, 0, + 0, 0, 386, 513, 373, 375, 376, 374, 507, 509, + 617, 618, 619, 621, 0, 622, 623, 0, 0, 0, + 0, 624, 690, 708, 674, 643, 605, 698, 640, 644, + 645, 427, 428, 429, 430, 711, 0, 0, 0, 596, + 456, 457, 0, 398, 397, 477, 349, 0, 0, 445, + 426, 519, 355, 394, 447, 432, 458, 459, 460, 461, + 462, 0, 463, 464, 404, 339, 340, 576, 387, 500, + 713, 750, 751, 635, 0, 699, 636, 646, 380, 671, + 683, 682, 494, 595, 264, 694, 697, 625, 275, 0, + 691, 705, 663, 704, 276, 506, 0, 538, 702, 649, + 0, 695, 668, 669, 0, 696, 664, 700, 356, 433, + 524, 581, 0, 637, 0, 606, 609, 639, 726, 727, + 728, 346, 608, 730, 731, 732, 733, 734, 735, 736, + 729, 577, 672, 648, 675, 587, 651, 650, 0, 0, + 686, 604, 687, 688, 488, 489, 490, 491, 408, 714, + 371, 607, 521, 522, 166, 673, 0, 0, 0, 0, + 0, 0, 0, 0, 678, 679, 676, 273, 0, 737, + 738, 0, 0, 601, 602, 403, 0, 620, 411, 370, + 505, 405, 585, 436, 0, 613, 680, 614, 525, 526, + 741, 746, 742, 743, 745, 766, 495, 425, 431, 542, + 446, 468, 528, 584, 503, 533, 368, 573, 544, 474, + 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, + 79, 0, 0, 325, 326, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 722, + 721, 720, 719, 718, 717, 716, 715, 0, 0, 662, + 385, 281, 361, 282, 767, 770, 769, 744, 0, 341, + 642, 466, 520, 402, 709, 710, 72, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, 308, - 309, 310, 708, 301, 302, 311, 312, 313, 314, 315, + 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, - 0, 0, 0, 333, 767, 768, 769, 770, 771, 0, - 0, 334, 335, 336, 0, 0, 299, 300, 327, 549, - 328, 329, 330, 331, 0, 0, 587, 588, 589, 612, - 0, 590, 572, 637, 411, 342, 553, 579, 778, 779, - 0, 0, 0, 0, 0, 0, 0, 688, 699, 735, - 736, 0, 749, 750, 752, 754, 753, 756, 546, 547, - 764, 0, 0, 435, 357, 358, 494, 495, 532, 0, - 436, 437, 438, 442, 439, 440, 441, 758, 759, 760, - 757, 468, 531, 554, 540, 777, 481, 0, 785, 627, - 628, 786, 745, 744, 343, 0, 337, 338, 702, 703, - 0, 0, 534, 480, 634, 200, 245, 199, 232, 201, - 0, 0, 0, 0, 0, 0, 500, 815, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 0, 680, 629, 542, - 482, 0, 697, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 822, 0, 0, 0, 0, 0, 0, 0, - 0, 821, 0, 0, 268, 0, 0, 0, 0, 0, - 0, 365, 269, 624, 751, 626, 625, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 0, 0, 0, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 0, 0, 565, 595, - 387, 585, 0, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 611, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 819, 820, 0, 743, 0, 246, - 748, 0, 578, 0, 0, 0, 0, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 596, 0, 529, 502, - 789, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 386, 498, - 709, 746, 747, 631, 0, 695, 632, 642, 379, 667, - 679, 678, 492, 591, 0, 690, 693, 621, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 574, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 600, 683, 684, - 486, 487, 488, 489, 816, 818, 370, 603, 519, 520, - 831, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 0, 0, - 0, 0, 0, 0, 0, 0, 79, 0, 0, 325, - 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 0, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 284, 285, 286, 287, 288, 289, - 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, - 303, 304, 305, 306, 307, 308, 309, 310, 708, 301, - 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, - 767, 768, 769, 770, 771, 0, 0, 334, 335, 336, - 0, 0, 299, 300, 327, 549, 328, 329, 330, 331, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 753, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 758, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 744, - 343, 0, 337, 338, 702, 703, 0, 0, 534, 480, - 634, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 394, - 0, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 0, 680, 629, 542, 482, 0, 697, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1644, 0, 0, 268, - 0, 0, 986, 996, 0, 0, 365, 269, 624, 751, - 626, 625, 987, 0, 988, 992, 995, 991, 989, 990, - 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 0, - 993, 0, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 994, 0, 565, 595, 387, 585, 0, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 611, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 0, 0, 748, 0, 578, 0, 0, - 0, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 596, 0, 529, 502, 789, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 386, 498, 709, 746, 747, 631, 0, - 695, 632, 642, 379, 667, 679, 678, 492, 591, 0, - 690, 693, 621, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 574, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 600, 683, 684, 486, 487, 488, 489, 407, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, + 0, 0, 0, 333, 771, 772, 773, 774, 775, 0, + 0, 334, 335, 336, 0, 0, 299, 300, 327, 552, + 328, 329, 330, 331, 0, 0, 591, 592, 593, 616, + 0, 594, 575, 641, 412, 342, 556, 583, 277, 278, + 55, 262, 265, 267, 266, 0, 73, 692, 703, 739, + 740, 9, 753, 754, 756, 758, 757, 760, 549, 550, + 768, 0, 0, 437, 358, 359, 496, 497, 535, 0, + 438, 439, 440, 444, 441, 442, 443, 762, 763, 764, + 761, 470, 534, 557, 543, 272, 483, 173, 279, 631, + 632, 280, 749, 748, 343, 0, 337, 338, 706, 707, + 200, 245, 537, 482, 638, 0, 0, 0, 0, 0, + 0, 502, 0, 0, 647, 681, 670, 759, 634, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 395, + 0, 0, 465, 685, 666, 677, 667, 508, 652, 653, + 654, 661, 407, 655, 791, 657, 626, 658, 627, 659, + 660, 1270, 684, 633, 545, 484, 0, 701, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 238, 0, 0, 268, + 0, 0, 0, 0, 0, 0, 366, 269, 628, 755, + 630, 629, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 369, 3052, 3055, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 546, 574, 0, 588, 0, 434, 435, 0, + 0, 0, 0, 0, 0, 0, 350, 553, 571, 367, + 540, 586, 372, 548, 564, 362, 501, 536, 0, 0, + 352, 569, 547, 479, 351, 0, 529, 392, 409, 389, + 499, 0, 0, 568, 599, 388, 589, 0, 579, 354, + 0, 578, 498, 471, 565, 570, 480, 473, 0, 353, + 567, 478, 472, 448, 399, 615, 449, 450, 451, 452, + 453, 454, 413, 514, 469, 515, 414, 486, 485, 487, + 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, + 0, 0, 0, 0, 0, 610, 611, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 747, 0, 246, 752, 3056, 582, 0, 0, + 0, 3051, 0, 3050, 551, 3047, 3053, 455, 0, 0, + 0, 600, 0, 532, 504, 793, 0, 0, 530, 467, + 566, 516, 572, 554, 580, 523, 517, 344, 555, 391, + 481, 363, 365, 780, 393, 396, 400, 401, 492, 493, + 510, 539, 558, 559, 560, 390, 377, 531, 378, 410, + 379, 345, 382, 381, 383, 541, 384, 347, 511, 563, + 3054, 406, 527, 476, 348, 475, 512, 562, 561, 364, + 590, 597, 598, 689, 0, 603, 794, 795, 796, 612, + 0, 518, 360, 357, 0, 0, 0, 386, 513, 373, + 375, 376, 374, 507, 509, 617, 618, 619, 621, 0, + 622, 623, 0, 0, 0, 0, 624, 690, 708, 674, + 643, 605, 698, 640, 644, 645, 427, 428, 429, 430, + 711, 0, 0, 0, 596, 456, 457, 0, 398, 397, + 477, 349, 0, 0, 445, 426, 519, 355, 394, 447, + 432, 458, 459, 460, 461, 462, 3048, 463, 464, 404, + 339, 340, 788, 387, 500, 713, 750, 751, 635, 0, + 699, 636, 646, 380, 671, 683, 682, 494, 595, 0, + 694, 697, 625, 787, 0, 691, 705, 792, 704, 784, + 506, 0, 538, 702, 649, 0, 695, 668, 669, 0, + 696, 664, 700, 356, 433, 524, 581, 0, 637, 0, + 606, 609, 639, 726, 727, 728, 346, 608, 730, 731, + 732, 733, 734, 735, 736, 729, 577, 672, 648, 675, + 587, 651, 650, 0, 0, 686, 604, 687, 688, 488, + 489, 490, 491, 408, 714, 371, 607, 521, 522, 0, + 673, 0, 0, 0, 0, 0, 0, 0, 0, 678, + 679, 676, 797, 0, 737, 738, 0, 0, 601, 602, + 403, 0, 620, 411, 370, 505, 405, 585, 436, 0, + 613, 680, 614, 525, 526, 741, 746, 742, 743, 745, + 766, 495, 425, 431, 542, 446, 468, 528, 584, 503, + 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 0, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 284, - 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, - 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, - 308, 309, 310, 708, 301, 302, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 0, 0, 0, 0, 333, 767, 768, 769, 770, 771, - 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, - 549, 328, 329, 330, 331, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 753, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 758, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 337, 338, 702, - 703, 0, 0, 534, 480, 634, 500, 0, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 0, 680, 629, 542, - 482, 0, 697, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 722, 721, 720, 719, 718, 717, + 716, 715, 0, 0, 662, 385, 785, 779, 786, 767, + 770, 769, 744, 0, 341, 642, 466, 520, 402, 709, + 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, + 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, + 304, 305, 306, 307, 308, 309, 310, 712, 301, 302, + 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 0, 0, 0, 0, 333, 771, + 772, 773, 774, 775, 0, 0, 334, 335, 336, 0, + 0, 299, 300, 327, 552, 328, 329, 330, 331, 0, + 0, 591, 592, 593, 616, 0, 594, 575, 641, 412, + 342, 556, 583, 782, 783, 0, 0, 0, 0, 0, + 0, 0, 692, 703, 739, 740, 0, 753, 754, 756, + 758, 757, 760, 549, 550, 768, 0, 0, 437, 358, + 359, 496, 497, 535, 0, 438, 439, 440, 444, 441, + 442, 443, 762, 763, 764, 761, 470, 534, 557, 543, + 781, 483, 0, 789, 631, 632, 790, 749, 748, 343, + 0, 337, 338, 706, 707, 0, 0, 537, 482, 638, + 200, 245, 199, 232, 201, 0, 0, 0, 0, 0, + 0, 502, 819, 0, 647, 681, 670, 759, 634, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 395, + 0, 0, 465, 685, 666, 677, 667, 508, 652, 653, + 654, 661, 407, 655, 791, 657, 626, 658, 627, 659, + 660, 0, 684, 633, 545, 484, 0, 701, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 826, 0, 0, + 0, 0, 0, 0, 0, 0, 825, 0, 0, 268, + 0, 0, 0, 0, 0, 0, 366, 269, 628, 755, + 630, 629, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 369, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 546, 574, 0, 588, 0, 434, 435, 0, + 0, 0, 0, 0, 0, 0, 350, 553, 571, 367, + 540, 586, 372, 548, 564, 362, 501, 536, 0, 0, + 352, 569, 547, 479, 351, 0, 529, 392, 409, 389, + 499, 0, 0, 568, 599, 388, 589, 0, 579, 354, + 0, 578, 498, 471, 565, 570, 480, 473, 0, 353, + 567, 478, 472, 448, 399, 615, 449, 450, 451, 452, + 453, 454, 413, 514, 469, 515, 414, 486, 485, 487, + 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, + 0, 0, 0, 0, 0, 610, 611, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 823, + 824, 0, 747, 0, 246, 752, 0, 582, 0, 0, + 0, 0, 0, 0, 551, 0, 0, 455, 0, 0, + 0, 600, 0, 532, 504, 793, 0, 0, 530, 467, + 566, 516, 572, 554, 580, 523, 517, 344, 555, 391, + 481, 363, 365, 780, 393, 396, 400, 401, 492, 493, + 510, 539, 558, 559, 560, 390, 377, 531, 378, 410, + 379, 345, 382, 381, 383, 541, 384, 347, 511, 563, + 0, 406, 527, 476, 348, 475, 512, 562, 561, 364, + 590, 597, 598, 689, 0, 603, 794, 795, 796, 612, + 0, 518, 360, 357, 0, 0, 0, 386, 513, 373, + 375, 376, 374, 507, 509, 617, 618, 619, 621, 0, + 622, 623, 0, 0, 0, 0, 624, 690, 708, 674, + 643, 605, 698, 640, 644, 645, 427, 428, 429, 430, + 711, 0, 0, 0, 596, 456, 457, 0, 398, 397, + 477, 349, 0, 0, 445, 426, 519, 355, 394, 447, + 432, 458, 459, 460, 461, 462, 0, 463, 464, 404, + 339, 340, 788, 387, 500, 713, 750, 751, 635, 0, + 699, 636, 646, 380, 671, 683, 682, 494, 595, 0, + 694, 697, 625, 787, 0, 691, 705, 792, 704, 784, + 506, 0, 538, 702, 649, 0, 695, 668, 669, 0, + 696, 664, 700, 356, 433, 524, 581, 0, 637, 0, + 606, 609, 639, 726, 727, 728, 346, 608, 730, 731, + 732, 733, 734, 735, 736, 729, 577, 672, 648, 675, + 587, 651, 650, 0, 0, 686, 604, 687, 688, 488, + 489, 490, 491, 820, 822, 371, 607, 521, 522, 835, + 673, 0, 0, 0, 0, 0, 0, 0, 0, 678, + 679, 676, 797, 0, 737, 738, 0, 0, 601, 602, + 403, 0, 620, 411, 370, 505, 405, 585, 436, 0, + 613, 680, 614, 525, 526, 741, 746, 742, 743, 745, + 766, 495, 425, 431, 542, 446, 468, 528, 584, 503, + 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, + 0, 0, 0, 0, 0, 79, 0, 0, 325, 326, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 722, 721, 720, 719, 718, 717, + 716, 715, 0, 0, 662, 385, 785, 779, 786, 767, + 770, 769, 744, 0, 341, 642, 466, 520, 402, 709, + 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, + 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, + 304, 305, 306, 307, 308, 309, 310, 712, 301, 302, + 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 0, 0, 0, 0, 333, 771, + 772, 773, 774, 775, 0, 0, 334, 335, 336, 0, + 0, 299, 300, 327, 552, 328, 329, 330, 331, 0, + 0, 591, 592, 593, 616, 0, 594, 575, 641, 412, + 342, 556, 583, 782, 783, 0, 0, 0, 0, 0, + 0, 0, 692, 703, 739, 740, 0, 753, 754, 756, + 758, 757, 760, 549, 550, 768, 0, 0, 437, 358, + 359, 496, 497, 535, 0, 438, 439, 440, 444, 441, + 442, 443, 762, 763, 764, 761, 470, 534, 557, 543, + 781, 483, 0, 789, 631, 632, 790, 749, 748, 343, + 0, 337, 338, 706, 707, 0, 0, 537, 482, 638, + 502, 0, 0, 647, 681, 670, 759, 634, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 395, 0, + 0, 465, 685, 666, 677, 667, 508, 652, 653, 654, + 661, 407, 655, 791, 657, 626, 658, 627, 659, 660, + 0, 684, 633, 545, 484, 0, 701, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1648, 0, 0, 268, 0, + 0, 990, 1000, 0, 0, 366, 269, 628, 755, 630, + 629, 991, 0, 992, 996, 999, 995, 993, 994, 0, + 369, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 546, 574, 0, 588, 0, 434, 435, 0, 997, + 0, 0, 0, 0, 0, 350, 553, 571, 367, 540, + 586, 372, 548, 564, 362, 501, 536, 0, 0, 352, + 569, 547, 479, 351, 0, 529, 392, 409, 389, 499, + 998, 0, 568, 599, 388, 589, 0, 579, 354, 0, + 578, 498, 471, 565, 570, 480, 473, 0, 353, 567, + 478, 472, 448, 399, 615, 449, 450, 451, 452, 453, + 454, 413, 514, 469, 515, 414, 486, 485, 487, 415, + 416, 417, 418, 419, 420, 421, 422, 423, 424, 0, + 0, 0, 0, 0, 610, 611, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 747, 0, 0, 752, 0, 582, 0, 0, 0, + 0, 0, 0, 551, 0, 0, 455, 0, 0, 0, + 600, 0, 532, 504, 793, 0, 0, 530, 467, 566, + 516, 572, 554, 580, 523, 517, 344, 555, 391, 481, + 363, 365, 780, 393, 396, 400, 401, 492, 493, 510, + 539, 558, 559, 560, 390, 377, 531, 378, 410, 379, + 345, 382, 381, 383, 541, 384, 347, 511, 563, 0, + 406, 527, 476, 348, 475, 512, 562, 561, 364, 590, + 597, 598, 689, 0, 603, 794, 795, 796, 612, 0, + 518, 360, 357, 0, 0, 0, 386, 513, 373, 375, + 376, 374, 507, 509, 617, 618, 619, 621, 0, 622, + 623, 0, 0, 0, 0, 624, 690, 708, 674, 643, + 605, 698, 640, 644, 645, 427, 428, 429, 430, 711, + 0, 0, 0, 596, 456, 457, 0, 398, 397, 477, + 349, 0, 0, 445, 426, 519, 355, 394, 447, 432, + 458, 459, 460, 461, 462, 0, 463, 464, 404, 339, + 340, 788, 387, 500, 713, 750, 751, 635, 0, 699, + 636, 646, 380, 671, 683, 682, 494, 595, 0, 694, + 697, 625, 787, 0, 691, 705, 792, 704, 784, 506, + 0, 538, 702, 649, 0, 695, 668, 669, 0, 696, + 664, 700, 356, 433, 524, 581, 0, 637, 0, 606, + 609, 639, 726, 727, 728, 346, 608, 730, 731, 732, + 733, 734, 735, 736, 729, 577, 672, 648, 675, 587, + 651, 650, 0, 0, 686, 604, 687, 688, 488, 489, + 490, 491, 408, 714, 371, 607, 521, 522, 0, 673, + 0, 0, 0, 0, 0, 0, 0, 0, 678, 679, + 676, 797, 0, 737, 738, 0, 0, 601, 602, 403, + 0, 620, 411, 370, 505, 405, 585, 436, 0, 613, + 680, 614, 525, 526, 741, 746, 742, 743, 745, 766, + 495, 425, 431, 542, 446, 468, 528, 584, 503, 533, + 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 268, 0, 0, 0, 0, 0, - 0, 365, 269, 624, 751, 626, 625, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 3048, 3051, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 0, 0, 0, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 0, 0, 565, 595, - 387, 585, 0, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 611, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 0, 0, - 748, 3052, 578, 0, 0, 0, 3047, 0, 3046, 548, - 3043, 3049, 453, 0, 0, 0, 596, 0, 529, 502, - 789, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 3050, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 3044, 461, 462, 403, 339, 340, 784, 386, 498, - 709, 746, 747, 631, 0, 695, 632, 642, 379, 667, - 679, 678, 492, 591, 0, 690, 693, 621, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 574, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 600, 683, 684, - 486, 487, 488, 489, 407, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, - 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 0, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 284, 285, 286, 287, 288, 289, - 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, - 303, 304, 305, 306, 307, 308, 309, 310, 708, 301, - 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, - 767, 768, 769, 770, 771, 0, 0, 334, 335, 336, - 0, 0, 299, 300, 327, 549, 328, 329, 330, 331, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 753, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 758, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 744, - 343, 0, 337, 338, 702, 703, 0, 0, 534, 480, - 634, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 1345, 0, 0, 0, 0, 0, 0, 0, 0, 394, - 0, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 0, 680, 629, 542, 482, 0, 697, 0, 0, + 0, 0, 0, 722, 721, 720, 719, 718, 717, 716, + 715, 0, 0, 662, 385, 785, 779, 786, 767, 770, + 769, 744, 0, 341, 642, 466, 520, 402, 709, 710, + 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, + 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, + 305, 306, 307, 308, 309, 310, 712, 301, 302, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 0, 0, 0, 0, 333, 771, 772, + 773, 774, 775, 0, 0, 334, 335, 336, 0, 0, + 299, 300, 327, 552, 328, 329, 330, 331, 0, 0, + 591, 592, 593, 616, 0, 594, 575, 641, 412, 342, + 556, 583, 782, 783, 0, 0, 0, 0, 0, 0, + 0, 692, 703, 739, 740, 0, 753, 754, 756, 758, + 757, 760, 549, 550, 768, 0, 0, 437, 358, 359, + 496, 497, 535, 0, 438, 439, 440, 444, 441, 442, + 443, 762, 763, 764, 761, 470, 534, 557, 543, 781, + 483, 0, 789, 631, 632, 790, 749, 748, 343, 0, + 337, 338, 706, 707, 0, 0, 537, 482, 638, 502, + 0, 0, 647, 681, 670, 759, 634, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 395, 0, 0, + 465, 685, 666, 677, 667, 508, 652, 653, 654, 661, + 407, 655, 791, 657, 626, 658, 627, 659, 660, 0, + 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 268, 0, 0, + 0, 0, 0, 0, 366, 269, 628, 755, 630, 629, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 369, + 3052, 3055, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 546, 574, 0, 588, 0, 434, 435, 0, 0, 0, + 0, 0, 0, 0, 350, 553, 571, 367, 540, 586, + 372, 548, 564, 362, 501, 536, 0, 0, 352, 569, + 547, 479, 351, 0, 529, 392, 409, 389, 499, 0, + 0, 568, 599, 388, 589, 0, 579, 354, 0, 578, + 498, 471, 565, 570, 480, 473, 0, 353, 567, 478, + 472, 448, 399, 615, 449, 450, 451, 452, 453, 454, + 413, 514, 469, 515, 414, 486, 485, 487, 415, 416, + 417, 418, 419, 420, 421, 422, 423, 424, 0, 0, + 0, 0, 0, 610, 611, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 747, 0, 0, 752, 3056, 582, 0, 0, 0, 3051, + 0, 3050, 551, 3047, 3053, 455, 0, 0, 0, 600, + 0, 532, 504, 793, 0, 0, 530, 467, 566, 516, + 572, 554, 580, 523, 517, 344, 555, 391, 481, 363, + 365, 780, 393, 396, 400, 401, 492, 493, 510, 539, + 558, 559, 560, 390, 377, 531, 378, 410, 379, 345, + 382, 381, 383, 541, 384, 347, 511, 563, 3054, 406, + 527, 476, 348, 475, 512, 562, 561, 364, 590, 597, + 598, 689, 0, 603, 794, 795, 796, 612, 0, 518, + 360, 357, 0, 0, 0, 386, 513, 373, 375, 376, + 374, 507, 509, 617, 618, 619, 621, 0, 622, 623, + 0, 0, 0, 0, 624, 690, 708, 674, 643, 605, + 698, 640, 644, 645, 427, 428, 429, 430, 711, 0, + 0, 0, 596, 456, 457, 0, 398, 397, 477, 349, + 0, 0, 445, 426, 519, 355, 394, 447, 432, 458, + 459, 460, 461, 462, 3048, 463, 464, 404, 339, 340, + 788, 387, 500, 713, 750, 751, 635, 0, 699, 636, + 646, 380, 671, 683, 682, 494, 595, 0, 694, 697, + 625, 787, 0, 691, 705, 792, 704, 784, 506, 0, + 538, 702, 649, 0, 695, 668, 669, 0, 696, 664, + 700, 356, 433, 524, 581, 0, 637, 0, 606, 609, + 639, 726, 727, 728, 346, 608, 730, 731, 732, 733, + 734, 735, 736, 729, 577, 672, 648, 675, 587, 651, + 650, 0, 0, 686, 604, 687, 688, 488, 489, 490, + 491, 408, 714, 371, 607, 521, 522, 0, 673, 0, + 0, 0, 0, 0, 0, 0, 0, 678, 679, 676, + 797, 0, 737, 738, 0, 0, 601, 602, 403, 0, + 620, 411, 370, 505, 405, 585, 436, 0, 613, 680, + 614, 525, 526, 741, 746, 742, 743, 745, 766, 495, + 425, 431, 542, 446, 468, 528, 584, 503, 533, 368, + 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, - 0, 0, 0, 0, 0, 0, 365, 269, 624, 751, - 626, 625, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 3473, 3474, 1325, - 0, 0, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 3467, 3470, 3471, 3472, 3475, 0, 3480, 3476, 3477, 3478, - 3479, 0, 0, 3463, 3464, 3465, 3466, 1323, 3442, 3468, - 0, 3443, 496, 3444, 3445, 3446, 3447, 3448, 1328, 3449, - 3450, 3451, 3452, 3453, 3460, 3461, 3454, 3455, 3456, 3457, - 3458, 3459, 3481, 3482, 3483, 3484, 3485, 3486, 3487, 3488, - 3490, 3489, 3491, 3492, 3493, 3494, 3495, 3496, 3497, 3498, - 1356, 1358, 1360, 1362, 1365, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 0, 0, 748, 0, 578, 0, 0, - 0, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 3462, 0, 529, 502, 789, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 386, 498, 709, 746, 747, 631, 0, - 695, 632, 642, 379, 667, 679, 678, 492, 591, 0, - 690, 693, 621, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 574, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 600, 683, 684, 486, 487, 488, 489, 407, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, + 0, 0, 722, 721, 720, 719, 718, 717, 716, 715, + 0, 0, 662, 385, 785, 779, 786, 767, 770, 769, + 744, 0, 341, 642, 466, 520, 402, 709, 710, 0, + 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, + 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, + 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 0, 0, 0, 0, 333, 771, 772, 773, + 774, 775, 0, 0, 334, 335, 336, 0, 0, 299, + 300, 327, 552, 328, 329, 330, 331, 0, 0, 591, + 592, 593, 616, 0, 594, 575, 641, 412, 342, 556, + 583, 782, 783, 0, 0, 0, 0, 0, 0, 0, + 692, 703, 739, 740, 0, 753, 754, 756, 758, 757, + 760, 549, 550, 768, 0, 0, 437, 358, 359, 496, + 497, 535, 0, 438, 439, 440, 444, 441, 442, 443, + 762, 763, 764, 761, 470, 534, 557, 543, 781, 483, + 0, 789, 631, 632, 790, 749, 748, 343, 0, 337, + 338, 706, 707, 0, 0, 537, 482, 638, 502, 0, + 0, 647, 681, 670, 759, 634, 0, 1349, 0, 0, + 0, 0, 0, 0, 0, 0, 395, 0, 0, 465, + 685, 666, 677, 667, 508, 652, 653, 654, 661, 407, + 655, 791, 657, 626, 658, 627, 659, 660, 0, 684, + 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 0, - 341, 3469, 464, 518, 401, 705, 706, 0, 761, 284, - 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, - 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, - 308, 309, 310, 708, 301, 302, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 0, 0, 0, 0, 333, 767, 768, 769, 770, 771, - 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, - 549, 328, 329, 330, 331, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 753, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 758, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 3441, 0, 337, 338, 702, - 703, 200, 245, 534, 480, 634, 0, 0, 0, 0, - 0, 0, 500, 0, 0, 643, 677, 666, 755, 630, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 394, 0, 0, 463, 681, 662, 673, 663, 506, 648, - 649, 650, 657, 406, 651, 787, 653, 622, 654, 623, - 655, 656, 1266, 680, 629, 542, 482, 0, 697, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1812, 0, 0, - 268, 0, 0, 0, 0, 0, 0, 365, 269, 624, - 751, 626, 625, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 368, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 543, 571, 0, 584, 0, 432, 433, - 0, 0, 0, 0, 0, 0, 0, 350, 550, 568, - 366, 537, 582, 371, 545, 561, 361, 499, 533, 0, - 0, 352, 566, 544, 477, 351, 0, 526, 391, 408, - 388, 497, 0, 0, 565, 595, 387, 585, 0, 576, - 354, 0, 575, 496, 469, 562, 567, 478, 471, 0, - 353, 564, 476, 470, 446, 398, 611, 447, 448, 449, - 450, 451, 452, 412, 512, 467, 513, 413, 484, 483, - 485, 414, 415, 416, 417, 418, 419, 420, 421, 422, - 423, 0, 0, 0, 0, 0, 606, 607, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 743, 0, 246, 748, 0, 578, 0, - 0, 0, 0, 0, 0, 548, 0, 0, 453, 0, - 0, 0, 596, 0, 529, 502, 789, 0, 0, 527, - 465, 563, 514, 569, 551, 577, 521, 515, 344, 552, - 390, 479, 362, 364, 776, 392, 395, 399, 400, 490, - 491, 508, 536, 555, 556, 557, 389, 376, 528, 377, - 409, 378, 345, 381, 380, 382, 538, 383, 347, 509, - 560, 0, 405, 524, 474, 348, 473, 510, 559, 558, - 363, 586, 593, 594, 685, 0, 599, 790, 791, 792, - 608, 0, 516, 359, 356, 0, 0, 0, 385, 511, - 372, 374, 375, 373, 505, 507, 613, 614, 615, 617, - 0, 618, 619, 0, 0, 0, 0, 620, 686, 704, - 670, 639, 601, 694, 636, 640, 641, 426, 427, 428, - 429, 707, 0, 0, 0, 592, 454, 455, 0, 397, - 396, 475, 349, 0, 0, 443, 425, 517, 355, 393, - 445, 431, 456, 457, 458, 459, 460, 0, 461, 462, - 403, 339, 340, 784, 386, 498, 709, 746, 747, 631, - 0, 695, 632, 642, 379, 667, 679, 678, 492, 591, - 0, 690, 693, 621, 783, 0, 687, 701, 788, 700, - 780, 504, 0, 535, 698, 645, 0, 691, 664, 665, - 0, 692, 660, 696, 0, 633, 0, 602, 605, 635, - 722, 723, 724, 346, 604, 726, 727, 728, 729, 730, - 731, 732, 725, 574, 668, 644, 671, 583, 647, 646, - 0, 0, 682, 600, 683, 684, 486, 487, 488, 489, - 407, 710, 370, 603, 519, 520, 0, 669, 0, 0, - 0, 0, 0, 0, 0, 0, 674, 675, 672, 793, - 0, 733, 734, 0, 0, 597, 598, 402, 0, 616, - 410, 369, 503, 404, 581, 434, 0, 609, 676, 610, - 522, 523, 737, 742, 738, 739, 741, 762, 493, 424, - 430, 539, 444, 466, 525, 580, 501, 530, 367, 570, - 541, 472, 661, 689, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 268, 0, 0, 0, + 0, 0, 0, 366, 269, 628, 755, 630, 629, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 369, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 546, + 574, 0, 588, 0, 3477, 3478, 1329, 0, 0, 0, + 0, 0, 0, 350, 553, 571, 367, 540, 586, 372, + 548, 564, 362, 501, 536, 0, 0, 3471, 3474, 3475, + 3476, 3479, 0, 3484, 3480, 3481, 3482, 3483, 0, 0, + 3467, 3468, 3469, 3470, 1327, 3446, 3472, 0, 3447, 498, + 3448, 3449, 3450, 3451, 3452, 1332, 3453, 3454, 3455, 3456, + 3457, 3464, 3465, 3458, 3459, 3460, 3461, 3462, 3463, 3485, + 3486, 3487, 3488, 3489, 3490, 3491, 3492, 3494, 3493, 3495, + 3496, 3497, 3498, 3499, 3500, 3501, 3502, 1360, 1362, 1364, + 1366, 1369, 610, 611, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 747, + 0, 0, 752, 0, 582, 0, 0, 0, 0, 0, + 0, 551, 0, 0, 455, 0, 0, 0, 3466, 0, + 532, 504, 793, 0, 0, 530, 467, 566, 516, 572, + 554, 580, 523, 517, 344, 555, 391, 481, 363, 365, + 780, 393, 396, 400, 401, 492, 493, 510, 539, 558, + 559, 560, 390, 377, 531, 378, 410, 379, 345, 382, + 381, 383, 541, 384, 347, 511, 563, 0, 406, 527, + 476, 348, 475, 512, 562, 561, 364, 590, 597, 598, + 689, 0, 603, 794, 795, 796, 612, 0, 518, 360, + 357, 0, 0, 0, 386, 513, 373, 375, 376, 374, + 507, 509, 617, 618, 619, 621, 0, 622, 623, 0, + 0, 0, 0, 624, 690, 708, 674, 643, 605, 698, + 640, 644, 645, 427, 428, 429, 430, 711, 0, 0, + 0, 596, 456, 457, 0, 398, 397, 477, 349, 0, + 0, 445, 426, 519, 355, 394, 447, 432, 458, 459, + 460, 461, 462, 0, 463, 464, 404, 339, 340, 788, + 387, 500, 713, 750, 751, 635, 0, 699, 636, 646, + 380, 671, 683, 682, 494, 595, 0, 694, 697, 625, + 787, 0, 691, 705, 792, 704, 784, 506, 0, 538, + 702, 649, 0, 695, 668, 669, 0, 696, 664, 700, + 356, 433, 524, 581, 0, 637, 0, 606, 609, 639, + 726, 727, 728, 346, 608, 730, 731, 732, 733, 734, + 735, 736, 729, 577, 672, 648, 675, 587, 651, 650, + 0, 0, 686, 604, 687, 688, 488, 489, 490, 491, + 408, 714, 371, 607, 521, 522, 0, 673, 0, 0, + 0, 0, 0, 0, 0, 0, 678, 679, 676, 797, + 0, 737, 738, 0, 0, 601, 602, 403, 0, 620, + 411, 370, 505, 405, 585, 436, 0, 613, 680, 614, + 525, 526, 741, 746, 742, 743, 745, 766, 495, 425, + 431, 542, 446, 468, 528, 584, 503, 533, 368, 573, + 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 718, 717, 716, 715, 714, 713, 712, 711, 0, - 0, 658, 384, 781, 775, 782, 763, 766, 765, 740, - 0, 341, 638, 464, 518, 401, 705, 706, 0, 761, + 0, 722, 721, 720, 719, 718, 717, 716, 715, 0, + 0, 662, 385, 785, 779, 786, 767, 770, 769, 744, + 0, 341, 3473, 466, 520, 402, 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, - 307, 308, 309, 310, 708, 301, 302, 311, 312, 313, + 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 324, 0, 0, 0, 0, 333, 767, 768, 769, 770, - 771, 0, 0, 334, 335, 336, 0, 0, 299, 300, - 327, 549, 328, 329, 330, 331, 0, 0, 587, 588, - 589, 612, 0, 590, 572, 637, 411, 342, 553, 579, - 778, 779, 0, 0, 0, 0, 0, 0, 0, 688, - 699, 735, 736, 0, 749, 750, 752, 754, 753, 756, - 546, 547, 764, 0, 0, 435, 357, 358, 494, 495, - 532, 0, 436, 437, 438, 442, 439, 440, 441, 758, - 759, 760, 757, 468, 531, 554, 540, 777, 481, 0, - 785, 627, 628, 786, 745, 744, 343, 0, 337, 338, - 702, 703, 0, 0, 534, 480, 634, 500, 2455, 0, - 643, 677, 666, 755, 630, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 394, 0, 0, 463, 681, - 662, 673, 663, 506, 648, 649, 650, 657, 406, 651, - 787, 653, 622, 654, 623, 655, 656, 0, 680, 629, - 542, 482, 0, 697, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 268, 0, 0, 0, 0, - 0, 0, 365, 269, 624, 751, 626, 625, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 368, 0, 3063, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 543, 571, - 0, 584, 0, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 350, 550, 568, 366, 537, 582, 371, 545, - 561, 361, 499, 533, 0, 0, 352, 566, 544, 477, - 351, 0, 526, 391, 408, 388, 497, 0, 0, 565, - 595, 387, 585, 0, 576, 354, 0, 575, 496, 469, - 562, 567, 478, 471, 0, 353, 564, 476, 470, 446, - 398, 611, 447, 448, 449, 450, 451, 452, 412, 512, - 467, 513, 413, 484, 483, 485, 414, 415, 416, 417, - 418, 419, 420, 421, 422, 423, 0, 0, 0, 0, - 0, 606, 607, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 743, 0, - 0, 748, 3062, 578, 0, 0, 0, 3068, 3065, 3067, - 548, 0, 3066, 453, 0, 0, 0, 596, 0, 529, - 502, 789, 0, 3060, 527, 465, 563, 514, 569, 551, - 577, 521, 515, 344, 552, 390, 479, 362, 364, 776, - 392, 395, 399, 400, 490, 491, 508, 536, 555, 556, - 557, 389, 376, 528, 377, 409, 378, 345, 381, 380, - 382, 538, 383, 347, 509, 560, 0, 405, 524, 474, - 348, 473, 510, 559, 558, 363, 586, 593, 594, 685, - 0, 599, 790, 791, 792, 608, 0, 516, 359, 356, - 0, 0, 0, 385, 511, 372, 374, 375, 373, 505, - 507, 613, 614, 615, 617, 0, 618, 619, 0, 0, - 0, 0, 620, 686, 704, 670, 639, 601, 694, 636, - 640, 641, 426, 427, 428, 429, 707, 0, 0, 0, - 592, 454, 455, 0, 397, 396, 475, 349, 0, 0, - 443, 425, 517, 355, 393, 445, 431, 456, 457, 458, - 459, 460, 0, 461, 462, 403, 339, 340, 784, 386, - 498, 709, 746, 747, 631, 0, 695, 632, 642, 379, - 667, 679, 678, 492, 591, 0, 690, 693, 621, 783, - 0, 687, 701, 788, 700, 780, 504, 0, 535, 698, - 645, 0, 691, 664, 665, 0, 692, 660, 696, 0, - 633, 0, 602, 605, 635, 722, 723, 724, 346, 604, - 726, 727, 728, 729, 730, 731, 732, 725, 574, 668, - 644, 671, 583, 647, 646, 0, 0, 682, 600, 683, - 684, 486, 487, 488, 489, 407, 710, 370, 603, 519, - 520, 0, 669, 0, 0, 0, 0, 0, 0, 0, - 0, 674, 675, 672, 793, 0, 733, 734, 0, 0, - 597, 598, 402, 0, 616, 410, 369, 503, 404, 581, - 434, 0, 609, 676, 610, 522, 523, 737, 742, 738, - 739, 741, 762, 493, 424, 430, 539, 444, 466, 525, - 580, 501, 530, 367, 570, 541, 472, 661, 689, 0, + 324, 0, 0, 0, 0, 333, 771, 772, 773, 774, + 775, 0, 0, 334, 335, 336, 0, 0, 299, 300, + 327, 552, 328, 329, 330, 331, 0, 0, 591, 592, + 593, 616, 0, 594, 575, 641, 412, 342, 556, 583, + 782, 783, 0, 0, 0, 0, 0, 0, 0, 692, + 703, 739, 740, 0, 753, 754, 756, 758, 757, 760, + 549, 550, 768, 0, 0, 437, 358, 359, 496, 497, + 535, 0, 438, 439, 440, 444, 441, 442, 443, 762, + 763, 764, 761, 470, 534, 557, 543, 781, 483, 0, + 789, 631, 632, 790, 749, 748, 3445, 0, 337, 338, + 706, 707, 200, 245, 537, 482, 638, 0, 0, 0, + 0, 0, 0, 502, 0, 0, 647, 681, 670, 759, + 634, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 395, 0, 0, 465, 685, 666, 677, 667, 508, + 652, 653, 654, 661, 407, 655, 791, 657, 626, 658, + 627, 659, 660, 1270, 684, 633, 545, 484, 0, 701, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1816, 0, + 0, 268, 0, 0, 0, 0, 0, 0, 366, 269, + 628, 755, 630, 629, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 369, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 546, 574, 0, 588, 0, 434, + 435, 0, 0, 0, 0, 0, 0, 0, 350, 553, + 571, 367, 540, 586, 372, 548, 564, 362, 501, 536, + 0, 0, 352, 569, 547, 479, 351, 0, 529, 392, + 409, 389, 499, 0, 0, 568, 599, 388, 589, 0, + 579, 354, 0, 578, 498, 471, 565, 570, 480, 473, + 0, 353, 567, 478, 472, 448, 399, 615, 449, 450, + 451, 452, 453, 454, 413, 514, 469, 515, 414, 486, + 485, 487, 415, 416, 417, 418, 419, 420, 421, 422, + 423, 424, 0, 0, 0, 0, 0, 610, 611, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 747, 0, 246, 752, 0, 582, + 0, 0, 0, 0, 0, 0, 551, 0, 0, 455, + 0, 0, 0, 600, 0, 532, 504, 793, 0, 0, + 530, 467, 566, 516, 572, 554, 580, 523, 517, 344, + 555, 391, 481, 363, 365, 780, 393, 396, 400, 401, + 492, 493, 510, 539, 558, 559, 560, 390, 377, 531, + 378, 410, 379, 345, 382, 381, 383, 541, 384, 347, + 511, 563, 0, 406, 527, 476, 348, 475, 512, 562, + 561, 364, 590, 597, 598, 689, 0, 603, 794, 795, + 796, 612, 0, 518, 360, 357, 0, 0, 0, 386, + 513, 373, 375, 376, 374, 507, 509, 617, 618, 619, + 621, 0, 622, 623, 0, 0, 0, 0, 624, 690, + 708, 674, 643, 605, 698, 640, 644, 645, 427, 428, + 429, 430, 711, 0, 0, 0, 596, 456, 457, 0, + 398, 397, 477, 349, 0, 0, 445, 426, 519, 355, + 394, 447, 432, 458, 459, 460, 461, 462, 0, 463, + 464, 404, 339, 340, 788, 387, 500, 713, 750, 751, + 635, 0, 699, 636, 646, 380, 671, 683, 682, 494, + 595, 0, 694, 697, 625, 787, 0, 691, 705, 792, + 704, 784, 506, 0, 538, 702, 649, 0, 695, 668, + 669, 0, 696, 664, 700, 356, 433, 524, 581, 0, + 637, 0, 606, 609, 639, 726, 727, 728, 346, 608, + 730, 731, 732, 733, 734, 735, 736, 729, 577, 672, + 648, 675, 587, 651, 650, 0, 0, 686, 604, 687, + 688, 488, 489, 490, 491, 408, 714, 371, 607, 521, + 522, 0, 673, 0, 0, 0, 0, 0, 0, 0, + 0, 678, 679, 676, 797, 0, 737, 738, 0, 0, + 601, 602, 403, 0, 620, 411, 370, 505, 405, 585, + 436, 0, 613, 680, 614, 525, 526, 741, 746, 742, + 743, 745, 766, 495, 425, 431, 542, 446, 468, 528, + 584, 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 718, 717, 716, 715, - 714, 713, 712, 711, 0, 0, 658, 384, 781, 775, - 782, 763, 766, 765, 740, 0, 341, 638, 464, 518, - 401, 705, 706, 0, 761, 284, 285, 286, 287, 288, + 0, 0, 0, 0, 0, 0, 722, 721, 720, 719, + 718, 717, 716, 715, 0, 0, 662, 385, 785, 779, + 786, 767, 770, 769, 744, 0, 341, 642, 466, 520, + 402, 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, - 298, 303, 304, 305, 306, 307, 308, 309, 310, 708, + 298, 303, 304, 305, 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, - 333, 767, 768, 769, 770, 771, 0, 0, 334, 335, - 336, 0, 0, 299, 300, 327, 549, 328, 329, 330, - 331, 0, 0, 587, 588, 589, 612, 0, 590, 572, - 637, 411, 342, 553, 579, 778, 779, 0, 0, 0, - 0, 0, 0, 0, 688, 699, 735, 736, 0, 749, - 750, 752, 754, 753, 756, 546, 547, 764, 0, 0, - 435, 357, 358, 494, 495, 532, 0, 436, 437, 438, - 442, 439, 440, 441, 758, 759, 760, 757, 468, 531, - 554, 540, 777, 481, 0, 785, 627, 628, 786, 745, - 744, 343, 0, 337, 338, 702, 703, 0, 0, 534, - 480, 634, 500, 0, 0, 643, 677, 666, 755, 630, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 394, 0, 0, 463, 681, 662, 673, 663, 506, 648, - 649, 650, 657, 406, 651, 787, 653, 622, 654, 623, - 655, 656, 0, 680, 629, 542, 482, 0, 697, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 268, 0, 0, 0, 0, 0, 0, 365, 269, 624, - 751, 626, 625, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 368, 0, 3063, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 543, 571, 0, 584, 0, 432, 433, - 0, 0, 0, 0, 0, 0, 0, 350, 550, 568, - 366, 537, 582, 371, 545, 561, 361, 499, 533, 0, - 0, 352, 566, 544, 477, 351, 0, 526, 391, 408, - 388, 497, 0, 0, 565, 595, 387, 585, 0, 576, - 354, 0, 575, 496, 469, 562, 567, 478, 471, 0, - 353, 564, 476, 470, 446, 398, 611, 447, 448, 449, - 450, 451, 452, 412, 512, 467, 513, 413, 484, 483, - 485, 414, 415, 416, 417, 418, 419, 420, 421, 422, - 423, 0, 0, 0, 0, 0, 606, 607, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 743, 0, 0, 748, 3062, 578, 0, - 0, 0, 3068, 3065, 3067, 548, 0, 3066, 453, 0, - 0, 0, 596, 0, 529, 502, 789, 0, 0, 527, - 465, 563, 514, 569, 551, 577, 521, 515, 344, 552, - 390, 479, 362, 364, 776, 392, 395, 399, 400, 490, - 491, 508, 536, 555, 556, 557, 389, 376, 528, 377, - 409, 378, 345, 381, 380, 382, 538, 383, 347, 509, - 560, 0, 405, 524, 474, 348, 473, 510, 559, 558, - 363, 586, 593, 594, 685, 0, 599, 790, 791, 792, - 608, 0, 516, 359, 356, 0, 0, 0, 385, 511, - 372, 374, 375, 373, 505, 507, 613, 614, 615, 617, - 0, 618, 619, 0, 0, 0, 0, 620, 686, 704, - 670, 639, 601, 694, 636, 640, 641, 426, 427, 428, - 429, 707, 0, 0, 0, 592, 454, 455, 0, 397, - 396, 475, 349, 0, 0, 443, 425, 517, 355, 393, - 445, 431, 456, 457, 458, 459, 460, 0, 461, 462, - 403, 339, 340, 784, 386, 498, 709, 746, 747, 631, - 0, 695, 632, 642, 379, 667, 679, 678, 492, 591, - 0, 690, 693, 621, 783, 0, 687, 701, 788, 700, - 780, 504, 0, 535, 698, 645, 0, 691, 664, 665, - 0, 692, 660, 696, 0, 633, 0, 602, 605, 635, - 722, 723, 724, 346, 604, 726, 727, 728, 729, 730, - 731, 732, 725, 574, 668, 644, 671, 583, 647, 646, - 0, 0, 682, 600, 683, 684, 486, 487, 488, 489, - 407, 710, 370, 603, 519, 520, 0, 669, 0, 0, - 0, 0, 0, 0, 0, 0, 674, 675, 672, 793, - 0, 733, 734, 0, 0, 597, 598, 402, 0, 616, - 410, 369, 503, 404, 581, 434, 0, 609, 676, 610, - 522, 523, 737, 742, 738, 739, 741, 762, 493, 424, - 430, 539, 444, 466, 525, 580, 501, 530, 367, 570, - 541, 472, 661, 689, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, + 333, 771, 772, 773, 774, 775, 0, 0, 334, 335, + 336, 0, 0, 299, 300, 327, 552, 328, 329, 330, + 331, 0, 0, 591, 592, 593, 616, 0, 594, 575, + 641, 412, 342, 556, 583, 782, 783, 0, 0, 0, + 0, 0, 0, 0, 692, 703, 739, 740, 0, 753, + 754, 756, 758, 757, 760, 549, 550, 768, 0, 0, + 437, 358, 359, 496, 497, 535, 0, 438, 439, 440, + 444, 441, 442, 443, 762, 763, 764, 761, 470, 534, + 557, 543, 781, 483, 0, 789, 631, 632, 790, 749, + 748, 343, 0, 337, 338, 706, 707, 0, 0, 537, + 482, 638, 502, 2459, 0, 647, 681, 670, 759, 634, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 395, 0, 0, 465, 685, 666, 677, 667, 508, 652, + 653, 654, 661, 407, 655, 791, 657, 626, 658, 627, + 659, 660, 0, 684, 633, 545, 484, 0, 701, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 268, 0, 0, 0, 0, 0, 0, 366, 269, 628, + 755, 630, 629, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 369, 0, 3067, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 546, 574, 0, 588, 0, 434, 435, + 0, 0, 0, 0, 0, 0, 0, 350, 553, 571, + 367, 540, 586, 372, 548, 564, 362, 501, 536, 0, + 0, 352, 569, 547, 479, 351, 0, 529, 392, 409, + 389, 499, 0, 0, 568, 599, 388, 589, 0, 579, + 354, 0, 578, 498, 471, 565, 570, 480, 473, 0, + 353, 567, 478, 472, 448, 399, 615, 449, 450, 451, + 452, 453, 454, 413, 514, 469, 515, 414, 486, 485, + 487, 415, 416, 417, 418, 419, 420, 421, 422, 423, + 424, 0, 0, 0, 0, 0, 610, 611, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 747, 0, 0, 752, 3066, 582, 0, + 0, 0, 3072, 3069, 3071, 551, 0, 3070, 455, 0, + 0, 0, 600, 0, 532, 504, 793, 0, 3064, 530, + 467, 566, 516, 572, 554, 580, 523, 517, 344, 555, + 391, 481, 363, 365, 780, 393, 396, 400, 401, 492, + 493, 510, 539, 558, 559, 560, 390, 377, 531, 378, + 410, 379, 345, 382, 381, 383, 541, 384, 347, 511, + 563, 0, 406, 527, 476, 348, 475, 512, 562, 561, + 364, 590, 597, 598, 689, 0, 603, 794, 795, 796, + 612, 0, 518, 360, 357, 0, 0, 0, 386, 513, + 373, 375, 376, 374, 507, 509, 617, 618, 619, 621, + 0, 622, 623, 0, 0, 0, 0, 624, 690, 708, + 674, 643, 605, 698, 640, 644, 645, 427, 428, 429, + 430, 711, 0, 0, 0, 596, 456, 457, 0, 398, + 397, 477, 349, 0, 0, 445, 426, 519, 355, 394, + 447, 432, 458, 459, 460, 461, 462, 0, 463, 464, + 404, 339, 340, 788, 387, 500, 713, 750, 751, 635, + 0, 699, 636, 646, 380, 671, 683, 682, 494, 595, + 0, 694, 697, 625, 787, 0, 691, 705, 792, 704, + 784, 506, 0, 538, 702, 649, 0, 695, 668, 669, + 0, 696, 664, 700, 356, 433, 524, 581, 0, 637, + 0, 606, 609, 639, 726, 727, 728, 346, 608, 730, + 731, 732, 733, 734, 735, 736, 729, 577, 672, 648, + 675, 587, 651, 650, 0, 0, 686, 604, 687, 688, + 488, 489, 490, 491, 408, 714, 371, 607, 521, 522, + 0, 673, 0, 0, 0, 0, 0, 0, 0, 0, + 678, 679, 676, 797, 0, 737, 738, 0, 0, 601, + 602, 403, 0, 620, 411, 370, 505, 405, 585, 436, + 0, 613, 680, 614, 525, 526, 741, 746, 742, 743, + 745, 766, 495, 425, 431, 542, 446, 468, 528, 584, + 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, + 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 722, 721, 720, 719, 718, + 717, 716, 715, 0, 0, 662, 385, 785, 779, 786, + 767, 770, 769, 744, 0, 341, 642, 466, 520, 402, + 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, + 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, + 303, 304, 305, 306, 307, 308, 309, 310, 712, 301, + 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, + 771, 772, 773, 774, 775, 0, 0, 334, 335, 336, + 0, 0, 299, 300, 327, 552, 328, 329, 330, 331, + 0, 0, 591, 592, 593, 616, 0, 594, 575, 641, + 412, 342, 556, 583, 782, 783, 0, 0, 0, 0, + 0, 0, 0, 692, 703, 739, 740, 0, 753, 754, + 756, 758, 757, 760, 549, 550, 768, 0, 0, 437, + 358, 359, 496, 497, 535, 0, 438, 439, 440, 444, + 441, 442, 443, 762, 763, 764, 761, 470, 534, 557, + 543, 781, 483, 0, 789, 631, 632, 790, 749, 748, + 343, 0, 337, 338, 706, 707, 0, 0, 537, 482, + 638, 502, 0, 0, 647, 681, 670, 759, 634, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 395, + 0, 0, 465, 685, 666, 677, 667, 508, 652, 653, + 654, 661, 407, 655, 791, 657, 626, 658, 627, 659, + 660, 0, 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 718, 717, 716, 715, 714, 713, 712, 711, 0, - 0, 658, 384, 781, 775, 782, 763, 766, 765, 740, - 0, 341, 638, 464, 518, 401, 705, 706, 0, 761, - 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, - 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, - 307, 308, 309, 310, 708, 301, 302, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 324, 0, 0, 0, 0, 333, 767, 768, 769, 770, - 771, 0, 0, 334, 335, 336, 0, 0, 299, 300, - 327, 549, 328, 329, 330, 331, 0, 0, 587, 588, - 589, 612, 0, 590, 572, 637, 411, 342, 553, 579, - 778, 779, 0, 0, 0, 0, 0, 0, 0, 688, - 699, 735, 736, 0, 749, 750, 752, 754, 753, 756, - 546, 547, 764, 0, 0, 435, 357, 358, 494, 495, - 532, 0, 436, 437, 438, 442, 439, 440, 441, 758, - 759, 760, 757, 468, 531, 554, 540, 777, 481, 0, - 785, 627, 628, 786, 745, 744, 343, 0, 337, 338, - 702, 703, 200, 245, 534, 480, 634, 0, 0, 0, - 0, 0, 0, 500, 0, 0, 643, 677, 666, 755, - 630, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 394, 0, 0, 463, 681, 662, 673, 663, 506, - 648, 649, 650, 657, 406, 651, 787, 653, 622, 654, - 623, 655, 656, 1266, 680, 629, 542, 482, 0, 697, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 238, 3220, - 0, 268, 0, 0, 0, 0, 0, 0, 365, 269, - 624, 751, 626, 625, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 368, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 543, 571, 0, 584, 0, 432, - 433, 0, 0, 0, 0, 0, 0, 0, 350, 550, - 568, 366, 537, 582, 371, 545, 561, 361, 499, 533, - 0, 0, 352, 566, 544, 477, 351, 0, 526, 391, - 408, 388, 497, 0, 0, 565, 595, 387, 585, 0, - 576, 354, 0, 575, 496, 469, 562, 567, 478, 471, - 0, 353, 564, 476, 470, 446, 398, 611, 447, 448, - 449, 450, 451, 452, 412, 512, 467, 513, 413, 484, - 483, 485, 414, 415, 416, 417, 418, 419, 420, 421, - 422, 423, 0, 0, 0, 0, 0, 606, 607, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 743, 0, 246, 748, 0, 578, - 0, 0, 0, 0, 0, 0, 548, 0, 0, 453, - 0, 0, 0, 596, 0, 529, 502, 789, 0, 0, - 527, 465, 563, 514, 569, 551, 577, 521, 515, 344, - 552, 390, 479, 362, 364, 776, 392, 395, 399, 400, - 490, 491, 508, 536, 555, 556, 557, 389, 376, 528, - 377, 409, 378, 345, 381, 380, 382, 538, 383, 347, - 509, 560, 0, 405, 524, 474, 348, 473, 510, 559, - 558, 363, 586, 593, 594, 685, 0, 599, 790, 791, - 792, 608, 0, 516, 359, 356, 0, 0, 0, 385, - 511, 372, 374, 375, 373, 505, 507, 613, 614, 615, - 617, 0, 618, 619, 0, 0, 0, 0, 620, 686, - 704, 670, 639, 601, 694, 636, 640, 641, 426, 427, - 428, 429, 707, 0, 0, 0, 592, 454, 455, 0, - 397, 396, 475, 349, 0, 0, 443, 425, 517, 355, - 393, 445, 431, 456, 457, 458, 459, 460, 0, 461, - 462, 403, 339, 340, 784, 386, 498, 709, 746, 747, - 631, 0, 695, 632, 642, 379, 667, 679, 678, 492, - 591, 0, 690, 693, 621, 783, 0, 687, 701, 788, - 700, 780, 504, 0, 535, 698, 645, 0, 691, 664, - 665, 0, 692, 660, 696, 0, 633, 0, 602, 605, - 635, 722, 723, 724, 346, 604, 726, 727, 728, 729, - 730, 731, 732, 725, 574, 668, 644, 671, 583, 647, - 646, 0, 0, 682, 600, 683, 684, 486, 487, 488, - 489, 407, 710, 370, 603, 519, 520, 0, 669, 0, - 0, 0, 0, 0, 0, 0, 0, 674, 675, 672, - 793, 0, 733, 734, 0, 0, 597, 598, 402, 0, - 616, 410, 369, 503, 404, 581, 434, 0, 609, 676, - 610, 522, 523, 737, 742, 738, 739, 741, 762, 493, - 424, 430, 539, 444, 466, 525, 580, 501, 530, 367, - 570, 541, 472, 661, 689, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, + 0, 0, 0, 0, 0, 0, 366, 269, 628, 755, + 630, 629, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 369, 0, 3067, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 546, 574, 0, 588, 0, 434, 435, 0, + 0, 0, 0, 0, 0, 0, 350, 553, 571, 367, + 540, 586, 372, 548, 564, 362, 501, 536, 0, 0, + 352, 569, 547, 479, 351, 0, 529, 392, 409, 389, + 499, 0, 0, 568, 599, 388, 589, 0, 579, 354, + 0, 578, 498, 471, 565, 570, 480, 473, 0, 353, + 567, 478, 472, 448, 399, 615, 449, 450, 451, 452, + 453, 454, 413, 514, 469, 515, 414, 486, 485, 487, + 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, + 0, 0, 0, 0, 0, 610, 611, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 747, 0, 0, 752, 3066, 582, 0, 0, + 0, 3072, 3069, 3071, 551, 0, 3070, 455, 0, 0, + 0, 600, 0, 532, 504, 793, 0, 0, 530, 467, + 566, 516, 572, 554, 580, 523, 517, 344, 555, 391, + 481, 363, 365, 780, 393, 396, 400, 401, 492, 493, + 510, 539, 558, 559, 560, 390, 377, 531, 378, 410, + 379, 345, 382, 381, 383, 541, 384, 347, 511, 563, + 0, 406, 527, 476, 348, 475, 512, 562, 561, 364, + 590, 597, 598, 689, 0, 603, 794, 795, 796, 612, + 0, 518, 360, 357, 0, 0, 0, 386, 513, 373, + 375, 376, 374, 507, 509, 617, 618, 619, 621, 0, + 622, 623, 0, 0, 0, 0, 624, 690, 708, 674, + 643, 605, 698, 640, 644, 645, 427, 428, 429, 430, + 711, 0, 0, 0, 596, 456, 457, 0, 398, 397, + 477, 349, 0, 0, 445, 426, 519, 355, 394, 447, + 432, 458, 459, 460, 461, 462, 0, 463, 464, 404, + 339, 340, 788, 387, 500, 713, 750, 751, 635, 0, + 699, 636, 646, 380, 671, 683, 682, 494, 595, 0, + 694, 697, 625, 787, 0, 691, 705, 792, 704, 784, + 506, 0, 538, 702, 649, 0, 695, 668, 669, 0, + 696, 664, 700, 356, 433, 524, 581, 0, 637, 0, + 606, 609, 639, 726, 727, 728, 346, 608, 730, 731, + 732, 733, 734, 735, 736, 729, 577, 672, 648, 675, + 587, 651, 650, 0, 0, 686, 604, 687, 688, 488, + 489, 490, 491, 408, 714, 371, 607, 521, 522, 0, + 673, 0, 0, 0, 0, 0, 0, 0, 0, 678, + 679, 676, 797, 0, 737, 738, 0, 0, 601, 602, + 403, 0, 620, 411, 370, 505, 405, 585, 436, 0, + 613, 680, 614, 525, 526, 741, 746, 742, 743, 745, + 766, 495, 425, 431, 542, 446, 468, 528, 584, 503, + 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 718, 717, 716, 715, 714, 713, 712, 711, - 0, 0, 658, 384, 781, 775, 782, 763, 766, 765, - 740, 0, 341, 638, 464, 518, 401, 705, 706, 0, - 761, 284, 285, 286, 287, 288, 289, 290, 291, 332, - 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, - 306, 307, 308, 309, 310, 708, 301, 302, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 324, 0, 0, 0, 0, 333, 767, 768, 769, - 770, 771, 0, 0, 334, 335, 336, 0, 0, 299, - 300, 327, 549, 328, 329, 330, 331, 0, 0, 587, - 588, 589, 612, 0, 590, 572, 637, 411, 342, 553, - 579, 778, 779, 0, 0, 0, 0, 0, 0, 0, - 688, 699, 735, 736, 0, 749, 750, 752, 754, 753, - 756, 546, 547, 764, 0, 0, 435, 357, 358, 494, - 495, 532, 0, 436, 437, 438, 442, 439, 440, 441, - 758, 759, 760, 757, 468, 531, 554, 540, 777, 481, - 0, 785, 627, 628, 786, 745, 744, 343, 0, 337, - 338, 702, 703, 200, 245, 534, 480, 634, 0, 0, - 0, 0, 0, 0, 500, 0, 0, 643, 677, 666, - 755, 630, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 394, 0, 0, 463, 681, 662, 673, 663, - 506, 648, 649, 650, 657, 406, 651, 787, 653, 622, - 654, 623, 655, 656, 1266, 680, 629, 542, 482, 0, - 697, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, - 2964, 0, 268, 0, 0, 0, 0, 0, 0, 365, - 269, 624, 751, 626, 625, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 368, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 543, 571, 0, 584, 0, - 432, 433, 0, 0, 0, 0, 0, 0, 0, 350, - 550, 568, 366, 537, 582, 371, 545, 561, 361, 499, - 533, 0, 0, 352, 566, 544, 477, 351, 0, 526, - 391, 408, 388, 497, 0, 0, 565, 595, 387, 585, - 0, 576, 354, 0, 575, 496, 469, 562, 567, 478, - 471, 0, 353, 564, 476, 470, 446, 398, 611, 447, - 448, 449, 450, 451, 452, 412, 512, 467, 513, 413, - 484, 483, 485, 414, 415, 416, 417, 418, 419, 420, - 421, 422, 423, 0, 0, 0, 0, 0, 606, 607, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 743, 0, 246, 748, 0, - 578, 0, 0, 0, 0, 0, 0, 548, 0, 0, - 453, 0, 0, 0, 596, 0, 529, 502, 789, 0, - 0, 527, 465, 563, 514, 569, 551, 577, 521, 515, - 344, 552, 390, 479, 362, 364, 776, 392, 395, 399, - 400, 490, 491, 508, 536, 555, 556, 557, 389, 376, - 528, 377, 409, 378, 345, 381, 380, 382, 538, 383, - 347, 509, 560, 0, 405, 524, 474, 348, 473, 510, - 559, 558, 363, 586, 593, 594, 685, 0, 599, 790, - 791, 792, 608, 0, 516, 359, 356, 0, 0, 0, - 385, 511, 372, 374, 375, 373, 505, 507, 613, 614, - 615, 617, 0, 618, 619, 0, 0, 0, 0, 620, - 686, 704, 670, 639, 601, 694, 636, 640, 641, 426, - 427, 428, 429, 707, 0, 0, 0, 592, 454, 455, - 0, 397, 396, 475, 349, 0, 0, 443, 425, 517, - 355, 393, 445, 431, 456, 457, 458, 459, 460, 0, - 461, 462, 403, 339, 340, 784, 386, 498, 709, 746, - 747, 631, 0, 695, 632, 642, 379, 667, 679, 678, - 492, 591, 0, 690, 693, 621, 783, 0, 687, 701, - 788, 700, 780, 504, 0, 535, 698, 645, 0, 691, - 664, 665, 0, 692, 660, 696, 0, 633, 0, 602, - 605, 635, 722, 723, 724, 346, 604, 726, 727, 728, - 729, 730, 731, 732, 725, 574, 668, 644, 671, 583, - 647, 646, 0, 0, 682, 600, 683, 684, 486, 487, - 488, 489, 407, 710, 370, 603, 519, 520, 0, 669, - 0, 0, 0, 0, 0, 0, 0, 0, 674, 675, - 672, 793, 0, 733, 734, 0, 0, 597, 598, 402, - 0, 616, 410, 369, 503, 404, 581, 434, 0, 609, - 676, 610, 522, 523, 737, 742, 738, 739, 741, 762, - 493, 424, 430, 539, 444, 466, 525, 580, 501, 530, - 367, 570, 541, 472, 661, 689, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, + 0, 0, 0, 0, 722, 721, 720, 719, 718, 717, + 716, 715, 0, 0, 662, 385, 785, 779, 786, 767, + 770, 769, 744, 0, 341, 642, 466, 520, 402, 709, + 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, + 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, + 304, 305, 306, 307, 308, 309, 310, 712, 301, 302, + 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 0, 0, 0, 0, 333, 771, + 772, 773, 774, 775, 0, 0, 334, 335, 336, 0, + 0, 299, 300, 327, 552, 328, 329, 330, 331, 0, + 0, 591, 592, 593, 616, 0, 594, 575, 641, 412, + 342, 556, 583, 782, 783, 0, 0, 0, 0, 0, + 0, 0, 692, 703, 739, 740, 0, 753, 754, 756, + 758, 757, 760, 549, 550, 768, 0, 0, 437, 358, + 359, 496, 497, 535, 0, 438, 439, 440, 444, 441, + 442, 443, 762, 763, 764, 761, 470, 534, 557, 543, + 781, 483, 0, 789, 631, 632, 790, 749, 748, 343, + 0, 337, 338, 706, 707, 200, 245, 537, 482, 638, + 0, 0, 0, 0, 0, 0, 502, 0, 0, 647, + 681, 670, 759, 634, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 395, 0, 0, 465, 685, 666, + 677, 667, 508, 652, 653, 654, 661, 407, 655, 791, + 657, 626, 658, 627, 659, 660, 1270, 684, 633, 545, + 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 238, 3224, 0, 268, 0, 0, 0, 0, 0, + 0, 366, 269, 628, 755, 630, 629, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 369, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 546, 574, 0, + 588, 0, 434, 435, 0, 0, 0, 0, 0, 0, + 0, 350, 553, 571, 367, 540, 586, 372, 548, 564, + 362, 501, 536, 0, 0, 352, 569, 547, 479, 351, + 0, 529, 392, 409, 389, 499, 0, 0, 568, 599, + 388, 589, 0, 579, 354, 0, 578, 498, 471, 565, + 570, 480, 473, 0, 353, 567, 478, 472, 448, 399, + 615, 449, 450, 451, 452, 453, 454, 413, 514, 469, + 515, 414, 486, 485, 487, 415, 416, 417, 418, 419, + 420, 421, 422, 423, 424, 0, 0, 0, 0, 0, + 610, 611, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 747, 0, 246, + 752, 0, 582, 0, 0, 0, 0, 0, 0, 551, + 0, 0, 455, 0, 0, 0, 600, 0, 532, 504, + 793, 0, 0, 530, 467, 566, 516, 572, 554, 580, + 523, 517, 344, 555, 391, 481, 363, 365, 780, 393, + 396, 400, 401, 492, 493, 510, 539, 558, 559, 560, + 390, 377, 531, 378, 410, 379, 345, 382, 381, 383, + 541, 384, 347, 511, 563, 0, 406, 527, 476, 348, + 475, 512, 562, 561, 364, 590, 597, 598, 689, 0, + 603, 794, 795, 796, 612, 0, 518, 360, 357, 0, + 0, 0, 386, 513, 373, 375, 376, 374, 507, 509, + 617, 618, 619, 621, 0, 622, 623, 0, 0, 0, + 0, 624, 690, 708, 674, 643, 605, 698, 640, 644, + 645, 427, 428, 429, 430, 711, 0, 0, 0, 596, + 456, 457, 0, 398, 397, 477, 349, 0, 0, 445, + 426, 519, 355, 394, 447, 432, 458, 459, 460, 461, + 462, 0, 463, 464, 404, 339, 340, 788, 387, 500, + 713, 750, 751, 635, 0, 699, 636, 646, 380, 671, + 683, 682, 494, 595, 0, 694, 697, 625, 787, 0, + 691, 705, 792, 704, 784, 506, 0, 538, 702, 649, + 0, 695, 668, 669, 0, 696, 664, 700, 356, 433, + 524, 581, 0, 637, 0, 606, 609, 639, 726, 727, + 728, 346, 608, 730, 731, 732, 733, 734, 735, 736, + 729, 577, 672, 648, 675, 587, 651, 650, 0, 0, + 686, 604, 687, 688, 488, 489, 490, 491, 408, 714, + 371, 607, 521, 522, 0, 673, 0, 0, 0, 0, + 0, 0, 0, 0, 678, 679, 676, 797, 0, 737, + 738, 0, 0, 601, 602, 403, 0, 620, 411, 370, + 505, 405, 585, 436, 0, 613, 680, 614, 525, 526, + 741, 746, 742, 743, 745, 766, 495, 425, 431, 542, + 446, 468, 528, 584, 503, 533, 368, 573, 544, 474, + 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 722, + 721, 720, 719, 718, 717, 716, 715, 0, 0, 662, + 385, 785, 779, 786, 767, 770, 769, 744, 0, 341, + 642, 466, 520, 402, 709, 710, 0, 765, 284, 285, + 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, + 295, 296, 297, 298, 303, 304, 305, 306, 307, 308, + 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, + 0, 0, 0, 333, 771, 772, 773, 774, 775, 0, + 0, 334, 335, 336, 0, 0, 299, 300, 327, 552, + 328, 329, 330, 331, 0, 0, 591, 592, 593, 616, + 0, 594, 575, 641, 412, 342, 556, 583, 782, 783, + 0, 0, 0, 0, 0, 0, 0, 692, 703, 739, + 740, 0, 753, 754, 756, 758, 757, 760, 549, 550, + 768, 0, 0, 437, 358, 359, 496, 497, 535, 0, + 438, 439, 440, 444, 441, 442, 443, 762, 763, 764, + 761, 470, 534, 557, 543, 781, 483, 0, 789, 631, + 632, 790, 749, 748, 343, 0, 337, 338, 706, 707, + 200, 245, 537, 482, 638, 0, 0, 0, 0, 0, + 0, 502, 0, 0, 647, 681, 670, 759, 634, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 395, + 0, 0, 465, 685, 666, 677, 667, 508, 652, 653, + 654, 661, 407, 655, 791, 657, 626, 658, 627, 659, + 660, 1270, 684, 633, 545, 484, 0, 701, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 238, 2968, 0, 268, + 0, 0, 0, 0, 0, 0, 366, 269, 628, 755, + 630, 629, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 369, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 546, 574, 0, 588, 0, 434, 435, 0, + 0, 0, 0, 0, 0, 0, 350, 553, 571, 367, + 540, 586, 372, 548, 564, 362, 501, 536, 0, 0, + 352, 569, 547, 479, 351, 0, 529, 392, 409, 389, + 499, 0, 0, 568, 599, 388, 589, 0, 579, 354, + 0, 578, 498, 471, 565, 570, 480, 473, 0, 353, + 567, 478, 472, 448, 399, 615, 449, 450, 451, 452, + 453, 454, 413, 514, 469, 515, 414, 486, 485, 487, + 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, + 0, 0, 0, 0, 0, 610, 611, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 747, 0, 246, 752, 0, 582, 0, 0, + 0, 0, 0, 0, 551, 0, 0, 455, 0, 0, + 0, 600, 0, 532, 504, 793, 0, 0, 530, 467, + 566, 516, 572, 554, 580, 523, 517, 344, 555, 391, + 481, 363, 365, 780, 393, 396, 400, 401, 492, 493, + 510, 539, 558, 559, 560, 390, 377, 531, 378, 410, + 379, 345, 382, 381, 383, 541, 384, 347, 511, 563, + 0, 406, 527, 476, 348, 475, 512, 562, 561, 364, + 590, 597, 598, 689, 0, 603, 794, 795, 796, 612, + 0, 518, 360, 357, 0, 0, 0, 386, 513, 373, + 375, 376, 374, 507, 509, 617, 618, 619, 621, 0, + 622, 623, 0, 0, 0, 0, 624, 690, 708, 674, + 643, 605, 698, 640, 644, 645, 427, 428, 429, 430, + 711, 0, 0, 0, 596, 456, 457, 0, 398, 397, + 477, 349, 0, 0, 445, 426, 519, 355, 394, 447, + 432, 458, 459, 460, 461, 462, 0, 463, 464, 404, + 339, 340, 788, 387, 500, 713, 750, 751, 635, 0, + 699, 636, 646, 380, 671, 683, 682, 494, 595, 0, + 694, 697, 625, 787, 0, 691, 705, 792, 704, 784, + 506, 0, 538, 702, 649, 0, 695, 668, 669, 0, + 696, 664, 700, 356, 433, 524, 581, 0, 637, 0, + 606, 609, 639, 726, 727, 728, 346, 608, 730, 731, + 732, 733, 734, 735, 736, 729, 577, 672, 648, 675, + 587, 651, 650, 0, 0, 686, 604, 687, 688, 488, + 489, 490, 491, 408, 714, 371, 607, 521, 522, 0, + 673, 0, 0, 0, 0, 0, 0, 0, 0, 678, + 679, 676, 797, 0, 737, 738, 0, 0, 601, 602, + 403, 0, 620, 411, 370, 505, 405, 585, 436, 0, + 613, 680, 614, 525, 526, 741, 746, 742, 743, 745, + 766, 495, 425, 431, 542, 446, 468, 528, 584, 503, + 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 718, 717, 716, 715, 714, 713, 712, - 711, 0, 0, 658, 384, 781, 775, 782, 763, 766, - 765, 740, 0, 341, 638, 464, 518, 401, 705, 706, - 0, 761, 284, 285, 286, 287, 288, 289, 290, 291, - 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, - 305, 306, 307, 308, 309, 310, 708, 301, 302, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 324, 0, 0, 0, 0, 333, 767, 768, - 769, 770, 771, 0, 0, 334, 335, 336, 0, 0, - 299, 300, 327, 549, 328, 329, 330, 331, 0, 0, - 587, 588, 589, 612, 0, 590, 572, 637, 411, 342, - 553, 579, 778, 779, 0, 0, 0, 0, 0, 0, - 0, 688, 699, 735, 736, 0, 749, 750, 752, 754, - 753, 756, 546, 547, 764, 0, 0, 435, 357, 358, - 494, 495, 532, 0, 436, 437, 438, 442, 439, 440, - 441, 758, 759, 760, 757, 468, 531, 554, 540, 777, - 481, 0, 785, 627, 628, 786, 745, 744, 343, 0, - 337, 338, 702, 703, 0, 0, 534, 480, 634, 500, - 0, 0, 643, 677, 666, 755, 630, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 394, 1239, 0, - 463, 681, 662, 673, 663, 506, 648, 649, 650, 657, - 406, 651, 787, 653, 622, 654, 623, 655, 656, 0, - 680, 629, 542, 482, 0, 697, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 268, 1246, 1247, - 0, 0, 0, 0, 365, 269, 624, 751, 626, 625, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1250, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 543, 571, 0, 584, 0, 432, 433, 0, 0, 0, - 0, 0, 0, 0, 350, 550, 1233, 366, 537, 582, - 371, 545, 561, 361, 499, 533, 0, 0, 352, 566, - 544, 477, 351, 0, 526, 391, 408, 388, 497, 0, - 0, 565, 595, 387, 585, 897, 576, 354, 896, 575, - 496, 469, 562, 567, 478, 471, 0, 353, 564, 476, - 470, 446, 398, 611, 447, 448, 449, 450, 451, 452, - 412, 512, 467, 513, 413, 484, 483, 485, 414, 415, - 416, 417, 418, 419, 420, 421, 422, 423, 0, 0, - 0, 0, 0, 606, 607, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 743, 0, 0, 748, 0, 578, 0, 0, 0, 0, - 0, 0, 548, 0, 0, 453, 0, 0, 0, 596, - 0, 529, 502, 789, 0, 0, 527, 465, 563, 514, - 569, 551, 577, 1237, 515, 344, 552, 390, 479, 362, - 364, 776, 392, 395, 399, 400, 490, 491, 508, 536, - 555, 556, 557, 389, 376, 528, 377, 409, 378, 345, - 381, 380, 382, 538, 383, 347, 509, 560, 0, 405, - 524, 474, 348, 473, 510, 559, 558, 363, 586, 593, - 594, 685, 0, 599, 790, 791, 792, 608, 0, 516, - 359, 356, 0, 0, 0, 385, 511, 372, 374, 375, - 373, 505, 507, 613, 614, 615, 617, 0, 618, 619, - 0, 0, 0, 0, 620, 686, 704, 670, 639, 601, - 694, 636, 640, 641, 426, 427, 428, 429, 707, 0, - 0, 0, 592, 454, 455, 0, 397, 396, 475, 349, - 0, 0, 443, 425, 517, 355, 393, 445, 431, 456, - 457, 458, 459, 460, 0, 461, 462, 403, 339, 340, - 784, 386, 498, 709, 746, 747, 631, 0, 695, 632, - 642, 379, 667, 679, 678, 492, 591, 0, 690, 693, - 621, 783, 0, 687, 701, 788, 700, 780, 504, 0, - 535, 698, 645, 0, 691, 664, 665, 0, 692, 660, - 696, 0, 633, 0, 602, 605, 635, 722, 723, 724, - 346, 604, 726, 727, 728, 729, 730, 731, 1238, 725, - 574, 668, 644, 671, 583, 647, 646, 0, 0, 682, - 1241, 683, 684, 486, 487, 488, 489, 407, 710, 1236, - 603, 519, 520, 0, 669, 0, 0, 0, 0, 0, - 0, 0, 0, 674, 675, 672, 793, 0, 733, 734, - 0, 0, 597, 598, 402, 0, 616, 410, 369, 503, - 404, 581, 434, 0, 609, 676, 610, 522, 523, 737, - 742, 738, 739, 741, 762, 1248, 1234, 1244, 1235, 444, - 466, 525, 580, 501, 530, 367, 570, 541, 1245, 661, - 689, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 718, 717, - 716, 715, 714, 713, 712, 711, 0, 0, 658, 384, - 781, 775, 782, 763, 766, 765, 740, 0, 341, 638, - 464, 518, 401, 705, 706, 0, 761, 284, 285, 286, - 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, - 296, 297, 298, 303, 304, 305, 306, 307, 308, 309, - 310, 708, 301, 302, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 324, 0, 0, - 0, 0, 333, 767, 768, 769, 770, 771, 0, 0, - 334, 335, 336, 0, 0, 299, 300, 327, 549, 328, - 329, 330, 331, 0, 0, 587, 588, 589, 612, 0, - 590, 572, 637, 411, 342, 553, 579, 778, 779, 0, - 0, 0, 0, 0, 0, 0, 688, 699, 735, 736, - 0, 749, 750, 752, 754, 753, 756, 546, 547, 764, - 0, 0, 435, 357, 358, 494, 495, 532, 0, 436, - 437, 438, 442, 439, 440, 441, 758, 759, 760, 757, - 1232, 531, 554, 540, 777, 481, 0, 785, 627, 628, - 786, 745, 744, 343, 0, 337, 338, 702, 703, 0, - 0, 534, 480, 634, 500, 0, 0, 643, 677, 666, - 755, 630, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 394, 0, 0, 463, 681, 662, 673, 663, - 506, 648, 649, 650, 657, 406, 651, 787, 653, 622, - 654, 623, 655, 656, 0, 680, 629, 542, 482, 0, - 697, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1812, - 0, 0, 268, 0, 0, 0, 0, 0, 0, 365, - 269, 624, 751, 626, 625, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 368, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 543, 571, 0, 584, 0, - 432, 433, 0, 0, 0, 0, 0, 0, 0, 350, - 550, 568, 366, 537, 582, 371, 545, 561, 361, 499, - 533, 0, 0, 352, 566, 544, 477, 351, 0, 526, - 391, 408, 388, 497, 0, 0, 565, 595, 387, 585, - 0, 576, 354, 0, 575, 496, 469, 562, 567, 478, - 471, 0, 353, 564, 476, 470, 446, 398, 611, 447, - 448, 449, 450, 451, 452, 412, 512, 467, 513, 413, - 484, 483, 485, 414, 415, 416, 417, 418, 419, 420, - 421, 422, 423, 0, 0, 0, 0, 0, 606, 607, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 743, 0, 0, 748, 0, - 578, 0, 0, 0, 0, 0, 0, 548, 0, 0, - 453, 0, 0, 0, 596, 0, 529, 502, 789, 0, - 0, 527, 465, 563, 514, 569, 551, 577, 521, 515, - 344, 552, 390, 479, 362, 364, 776, 392, 395, 399, - 400, 490, 491, 508, 536, 555, 556, 557, 389, 376, - 528, 377, 409, 378, 345, 381, 380, 382, 538, 383, - 347, 509, 560, 0, 405, 524, 474, 348, 473, 510, - 559, 558, 363, 586, 593, 594, 685, 0, 599, 790, - 791, 792, 608, 0, 516, 359, 356, 0, 0, 0, - 385, 511, 372, 374, 375, 373, 505, 507, 613, 614, - 615, 617, 0, 618, 619, 0, 0, 0, 0, 620, - 686, 704, 670, 639, 601, 694, 636, 640, 641, 426, - 427, 428, 429, 707, 0, 0, 0, 592, 454, 455, - 0, 397, 396, 475, 349, 0, 0, 443, 425, 517, - 355, 393, 445, 431, 456, 457, 458, 459, 460, 0, - 461, 462, 403, 339, 340, 784, 386, 498, 709, 746, - 747, 631, 0, 695, 632, 642, 379, 667, 679, 678, - 492, 591, 0, 690, 693, 621, 783, 0, 687, 701, - 788, 700, 780, 504, 0, 535, 698, 645, 0, 691, - 664, 665, 0, 692, 660, 696, 0, 633, 0, 602, - 605, 635, 722, 723, 724, 346, 604, 726, 727, 728, - 729, 730, 731, 732, 725, 574, 668, 644, 671, 583, - 647, 646, 0, 0, 682, 600, 683, 684, 486, 487, - 488, 489, 407, 710, 370, 603, 519, 520, 0, 669, - 0, 0, 0, 0, 0, 0, 0, 0, 674, 675, - 672, 793, 0, 733, 734, 0, 0, 597, 598, 402, - 0, 616, 410, 369, 503, 404, 581, 434, 0, 609, - 676, 610, 522, 523, 737, 742, 738, 739, 741, 762, - 493, 424, 430, 539, 444, 466, 525, 580, 501, 530, - 367, 570, 541, 472, 661, 689, 0, 0, 0, 0, + 0, 0, 0, 0, 722, 721, 720, 719, 718, 717, + 716, 715, 0, 0, 662, 385, 785, 779, 786, 767, + 770, 769, 744, 0, 341, 642, 466, 520, 402, 709, + 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, + 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, + 304, 305, 306, 307, 308, 309, 310, 712, 301, 302, + 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 0, 0, 0, 0, 333, 771, + 772, 773, 774, 775, 0, 0, 334, 335, 336, 0, + 0, 299, 300, 327, 552, 328, 329, 330, 331, 0, + 0, 591, 592, 593, 616, 0, 594, 575, 641, 412, + 342, 556, 583, 782, 783, 0, 0, 0, 0, 0, + 0, 0, 692, 703, 739, 740, 0, 753, 754, 756, + 758, 757, 760, 549, 550, 768, 0, 0, 437, 358, + 359, 496, 497, 535, 0, 438, 439, 440, 444, 441, + 442, 443, 762, 763, 764, 761, 470, 534, 557, 543, + 781, 483, 0, 789, 631, 632, 790, 749, 748, 343, + 0, 337, 338, 706, 707, 0, 0, 537, 482, 638, + 502, 0, 0, 647, 681, 670, 759, 634, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 395, 1243, + 0, 465, 685, 666, 677, 667, 508, 652, 653, 654, + 661, 407, 655, 791, 657, 626, 658, 627, 659, 660, + 0, 684, 633, 545, 484, 0, 701, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 268, 1250, + 1251, 0, 0, 0, 0, 366, 269, 628, 755, 630, + 629, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1254, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 546, 574, 0, 588, 0, 434, 435, 0, 0, + 0, 0, 0, 0, 0, 350, 553, 1237, 367, 540, + 586, 372, 548, 564, 362, 501, 536, 0, 0, 352, + 569, 547, 479, 351, 0, 529, 392, 409, 389, 499, + 0, 0, 568, 599, 388, 589, 901, 579, 354, 900, + 578, 498, 471, 565, 570, 480, 473, 0, 353, 567, + 478, 472, 448, 399, 615, 449, 450, 451, 452, 453, + 454, 413, 514, 469, 515, 414, 486, 485, 487, 415, + 416, 417, 418, 419, 420, 421, 422, 423, 424, 0, + 0, 0, 0, 0, 610, 611, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 747, 0, 0, 752, 0, 582, 0, 0, 0, + 0, 0, 0, 551, 0, 0, 455, 0, 0, 0, + 600, 0, 532, 504, 793, 0, 0, 530, 467, 566, + 516, 572, 554, 580, 1241, 517, 344, 555, 391, 481, + 363, 365, 780, 393, 396, 400, 401, 492, 493, 510, + 539, 558, 559, 560, 390, 377, 531, 378, 410, 379, + 345, 382, 381, 383, 541, 384, 347, 511, 563, 0, + 406, 527, 476, 348, 475, 512, 562, 561, 364, 590, + 597, 598, 689, 0, 603, 794, 795, 796, 612, 0, + 518, 360, 357, 0, 0, 0, 386, 513, 373, 375, + 376, 374, 507, 509, 617, 618, 619, 621, 0, 622, + 623, 0, 0, 0, 0, 624, 690, 708, 674, 643, + 605, 698, 640, 644, 645, 427, 428, 429, 430, 711, + 0, 0, 0, 596, 456, 457, 0, 398, 397, 477, + 349, 0, 0, 445, 426, 519, 355, 394, 447, 432, + 458, 459, 460, 461, 462, 0, 463, 464, 404, 339, + 340, 788, 387, 500, 713, 750, 751, 635, 0, 699, + 636, 646, 380, 671, 683, 682, 494, 595, 0, 694, + 697, 625, 787, 0, 691, 705, 792, 704, 784, 506, + 0, 538, 702, 649, 0, 695, 668, 669, 0, 696, + 664, 700, 356, 433, 524, 581, 0, 637, 0, 606, + 609, 639, 726, 727, 728, 346, 608, 730, 731, 732, + 733, 734, 735, 1242, 729, 577, 672, 648, 675, 587, + 651, 650, 0, 0, 686, 1245, 687, 688, 488, 489, + 490, 491, 408, 714, 1240, 607, 521, 522, 0, 673, + 0, 0, 0, 0, 0, 0, 0, 0, 678, 679, + 676, 797, 0, 737, 738, 0, 0, 601, 602, 403, + 0, 620, 411, 370, 505, 405, 585, 436, 0, 613, + 680, 614, 525, 526, 741, 746, 742, 743, 745, 766, + 1252, 1238, 1248, 1239, 446, 468, 528, 584, 503, 533, + 368, 573, 544, 1249, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 718, 717, 716, 715, 714, 713, 712, - 711, 0, 0, 658, 384, 781, 775, 782, 763, 766, - 765, 740, 0, 341, 638, 464, 518, 401, 705, 706, - 0, 761, 284, 285, 286, 287, 288, 289, 290, 291, + 0, 0, 0, 722, 721, 720, 719, 718, 717, 716, + 715, 0, 0, 662, 385, 785, 779, 786, 767, 770, + 769, 744, 0, 341, 642, 466, 520, 402, 709, 710, + 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, - 305, 306, 307, 308, 309, 310, 708, 301, 302, 311, + 305, 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 324, 0, 0, 0, 0, 333, 767, 768, - 769, 770, 771, 0, 0, 334, 335, 336, 0, 0, - 299, 300, 327, 549, 328, 329, 330, 331, 0, 0, - 587, 588, 589, 612, 0, 590, 572, 637, 411, 342, - 553, 579, 778, 779, 0, 0, 0, 0, 0, 0, - 0, 688, 699, 735, 736, 0, 749, 750, 752, 754, - 753, 756, 546, 547, 764, 0, 0, 435, 357, 358, - 494, 495, 532, 0, 436, 437, 438, 442, 439, 440, - 441, 758, 759, 760, 757, 468, 531, 554, 540, 777, - 481, 0, 785, 627, 628, 786, 745, 744, 343, 0, - 337, 338, 702, 703, 0, 0, 534, 480, 634, 500, - 2455, 0, 643, 677, 666, 755, 630, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 394, 0, 0, - 463, 681, 662, 673, 663, 506, 648, 649, 650, 657, - 406, 651, 787, 653, 622, 654, 623, 655, 656, 0, - 680, 629, 542, 482, 0, 697, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 268, 1246, 1247, - 0, 0, 0, 0, 365, 269, 624, 751, 626, 625, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1250, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 543, 571, 0, 584, 0, 432, 433, 0, 0, 0, - 0, 0, 0, 0, 350, 550, 568, 366, 537, 582, - 371, 545, 561, 361, 499, 533, 0, 0, 352, 566, - 544, 477, 351, 0, 526, 391, 408, 388, 497, 0, - 0, 565, 595, 387, 585, 897, 576, 354, 896, 575, - 496, 469, 562, 567, 478, 471, 0, 353, 564, 476, - 470, 446, 398, 611, 447, 448, 449, 450, 451, 452, - 412, 512, 467, 513, 413, 484, 483, 485, 414, 415, - 416, 417, 418, 419, 420, 421, 422, 423, 0, 0, - 0, 0, 0, 606, 607, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 743, 0, 0, 748, 0, 578, 0, 0, 0, 0, - 0, 0, 548, 0, 0, 453, 0, 0, 0, 596, - 0, 529, 502, 789, 0, 0, 527, 465, 563, 514, - 569, 551, 577, 521, 515, 344, 552, 390, 479, 362, - 364, 776, 392, 395, 399, 400, 490, 491, 508, 536, - 555, 556, 557, 389, 376, 528, 377, 409, 378, 345, - 381, 380, 382, 538, 383, 347, 509, 560, 0, 405, - 524, 474, 348, 473, 510, 559, 558, 363, 586, 593, - 594, 685, 0, 599, 790, 791, 792, 608, 0, 516, - 359, 356, 0, 0, 0, 385, 511, 372, 374, 375, - 373, 505, 507, 613, 614, 615, 617, 0, 618, 619, - 0, 0, 0, 0, 620, 686, 704, 670, 639, 601, - 694, 636, 640, 641, 426, 427, 428, 429, 707, 0, - 0, 0, 592, 454, 455, 0, 397, 396, 475, 349, - 0, 0, 443, 425, 517, 355, 393, 445, 431, 456, - 457, 458, 459, 460, 0, 461, 462, 403, 339, 340, - 784, 386, 498, 709, 746, 747, 631, 0, 695, 632, - 642, 379, 667, 679, 678, 492, 591, 0, 690, 693, - 621, 783, 0, 687, 701, 788, 700, 780, 504, 0, - 535, 698, 645, 0, 691, 664, 665, 0, 692, 660, - 696, 0, 633, 0, 602, 605, 635, 722, 723, 724, - 346, 604, 726, 727, 728, 729, 730, 731, 732, 725, - 574, 668, 644, 671, 583, 647, 646, 0, 0, 682, - 600, 683, 684, 486, 487, 488, 489, 407, 710, 370, - 603, 519, 520, 0, 669, 0, 0, 0, 0, 0, - 0, 0, 0, 674, 675, 672, 793, 0, 733, 734, - 0, 0, 597, 598, 402, 0, 616, 410, 369, 503, - 404, 581, 434, 0, 609, 676, 610, 522, 523, 737, - 742, 738, 739, 741, 762, 1248, 2561, 1244, 2562, 444, - 466, 525, 580, 501, 530, 367, 570, 541, 1245, 661, - 689, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 718, 717, - 716, 715, 714, 713, 712, 711, 0, 0, 658, 384, - 781, 775, 782, 763, 766, 765, 740, 0, 341, 638, - 464, 518, 401, 705, 706, 0, 761, 284, 285, 286, - 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, - 296, 297, 298, 303, 304, 305, 306, 307, 308, 309, - 310, 708, 301, 302, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 324, 0, 0, - 0, 0, 333, 767, 768, 769, 770, 771, 0, 0, - 334, 335, 336, 0, 0, 299, 300, 327, 549, 328, - 329, 330, 331, 0, 0, 587, 588, 589, 612, 0, - 590, 572, 637, 411, 342, 553, 579, 778, 779, 0, - 0, 0, 0, 0, 0, 0, 688, 699, 735, 736, - 0, 749, 750, 752, 754, 753, 756, 546, 547, 764, - 0, 0, 435, 357, 358, 494, 495, 532, 0, 436, - 437, 438, 442, 439, 440, 441, 758, 759, 760, 757, - 468, 531, 554, 540, 777, 481, 0, 785, 627, 628, - 786, 745, 744, 343, 0, 337, 338, 702, 703, 0, - 0, 534, 480, 634, 500, 0, 0, 643, 677, 666, - 755, 630, 0, 0, 3757, 0, 0, 0, 0, 0, - 0, 0, 394, 0, 0, 463, 681, 662, 673, 663, - 506, 648, 649, 650, 657, 406, 651, 787, 653, 622, - 654, 623, 655, 656, 0, 680, 629, 542, 482, 0, - 697, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 268, 0, 0, 0, 0, 0, 0, 365, - 269, 624, 751, 626, 625, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 368, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 543, 571, 0, 584, 0, - 432, 433, 0, 0, 0, 0, 0, 0, 0, 350, - 550, 568, 366, 537, 582, 371, 545, 561, 361, 499, - 533, 0, 0, 352, 566, 544, 477, 351, 0, 526, - 391, 408, 388, 497, 0, 0, 565, 595, 387, 585, - 0, 576, 354, 0, 575, 496, 469, 562, 567, 478, - 471, 0, 353, 564, 476, 470, 446, 398, 611, 447, - 448, 449, 450, 451, 452, 412, 512, 467, 513, 413, - 484, 483, 485, 414, 415, 416, 417, 418, 419, 420, - 421, 422, 423, 0, 0, 0, 0, 0, 606, 607, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3760, - 0, 0, 0, 0, 3759, 743, 0, 0, 748, 0, - 578, 0, 0, 0, 0, 0, 0, 548, 0, 0, - 453, 0, 0, 0, 596, 0, 529, 502, 789, 0, - 0, 527, 465, 563, 514, 569, 551, 577, 521, 515, - 344, 552, 390, 479, 362, 364, 776, 392, 395, 399, - 400, 490, 491, 508, 536, 555, 556, 557, 389, 376, - 528, 377, 409, 378, 345, 381, 380, 382, 538, 383, - 347, 509, 560, 0, 405, 524, 474, 348, 473, 510, - 559, 558, 363, 586, 593, 594, 685, 0, 599, 790, - 791, 792, 608, 0, 516, 359, 356, 0, 0, 0, - 385, 511, 372, 374, 375, 373, 505, 507, 613, 614, - 615, 617, 0, 618, 619, 0, 0, 0, 0, 620, - 686, 704, 670, 639, 601, 694, 636, 640, 641, 426, - 427, 428, 429, 707, 0, 0, 0, 592, 454, 455, - 0, 397, 396, 475, 349, 0, 0, 443, 425, 517, - 355, 393, 445, 431, 456, 457, 458, 459, 460, 0, - 461, 462, 403, 339, 340, 784, 386, 498, 709, 746, - 747, 631, 0, 695, 632, 642, 379, 667, 679, 678, - 492, 591, 0, 690, 693, 621, 783, 0, 687, 701, - 788, 700, 780, 504, 0, 535, 698, 645, 0, 691, - 664, 665, 0, 692, 660, 696, 0, 633, 0, 602, - 605, 635, 722, 723, 724, 346, 604, 726, 727, 728, - 729, 730, 731, 732, 725, 574, 668, 644, 671, 583, - 647, 646, 0, 0, 682, 600, 683, 684, 486, 487, - 488, 489, 407, 710, 370, 603, 519, 520, 0, 669, - 0, 0, 0, 0, 0, 0, 0, 0, 674, 675, - 672, 793, 0, 733, 734, 0, 0, 597, 598, 402, - 0, 616, 410, 369, 503, 404, 581, 434, 0, 609, - 676, 610, 522, 523, 737, 742, 738, 739, 741, 762, - 493, 424, 430, 539, 444, 466, 525, 580, 501, 530, - 367, 570, 541, 472, 661, 689, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, + 322, 323, 324, 0, 0, 0, 0, 333, 771, 772, + 773, 774, 775, 0, 0, 334, 335, 336, 0, 0, + 299, 300, 327, 552, 328, 329, 330, 331, 0, 0, + 591, 592, 593, 616, 0, 594, 575, 641, 412, 342, + 556, 583, 782, 783, 0, 0, 0, 0, 0, 0, + 0, 692, 703, 739, 740, 0, 753, 754, 756, 758, + 757, 760, 549, 550, 768, 0, 0, 437, 358, 359, + 496, 497, 535, 0, 438, 439, 440, 444, 441, 442, + 443, 762, 763, 764, 761, 1236, 534, 557, 543, 781, + 483, 0, 789, 631, 632, 790, 749, 748, 343, 0, + 337, 338, 706, 707, 0, 0, 537, 482, 638, 502, + 0, 0, 647, 681, 670, 759, 634, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 395, 0, 0, + 465, 685, 666, 677, 667, 508, 652, 653, 654, 661, + 407, 655, 791, 657, 626, 658, 627, 659, 660, 0, + 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1816, 0, 0, 268, 0, 0, + 0, 0, 0, 0, 366, 269, 628, 755, 630, 629, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 369, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 546, 574, 0, 588, 0, 434, 435, 0, 0, 0, + 0, 0, 0, 0, 350, 553, 571, 367, 540, 586, + 372, 548, 564, 362, 501, 536, 0, 0, 352, 569, + 547, 479, 351, 0, 529, 392, 409, 389, 499, 0, + 0, 568, 599, 388, 589, 0, 579, 354, 0, 578, + 498, 471, 565, 570, 480, 473, 0, 353, 567, 478, + 472, 448, 399, 615, 449, 450, 451, 452, 453, 454, + 413, 514, 469, 515, 414, 486, 485, 487, 415, 416, + 417, 418, 419, 420, 421, 422, 423, 424, 0, 0, + 0, 0, 0, 610, 611, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 747, 0, 0, 752, 0, 582, 0, 0, 0, 0, + 0, 0, 551, 0, 0, 455, 0, 0, 0, 600, + 0, 532, 504, 793, 0, 0, 530, 467, 566, 516, + 572, 554, 580, 523, 517, 344, 555, 391, 481, 363, + 365, 780, 393, 396, 400, 401, 492, 493, 510, 539, + 558, 559, 560, 390, 377, 531, 378, 410, 379, 345, + 382, 381, 383, 541, 384, 347, 511, 563, 0, 406, + 527, 476, 348, 475, 512, 562, 561, 364, 590, 597, + 598, 689, 0, 603, 794, 795, 796, 612, 0, 518, + 360, 357, 0, 0, 0, 386, 513, 373, 375, 376, + 374, 507, 509, 617, 618, 619, 621, 0, 622, 623, + 0, 0, 0, 0, 624, 690, 708, 674, 643, 605, + 698, 640, 644, 645, 427, 428, 429, 430, 711, 0, + 0, 0, 596, 456, 457, 0, 398, 397, 477, 349, + 0, 0, 445, 426, 519, 355, 394, 447, 432, 458, + 459, 460, 461, 462, 0, 463, 464, 404, 339, 340, + 788, 387, 500, 713, 750, 751, 635, 0, 699, 636, + 646, 380, 671, 683, 682, 494, 595, 0, 694, 697, + 625, 787, 0, 691, 705, 792, 704, 784, 506, 0, + 538, 702, 649, 0, 695, 668, 669, 0, 696, 664, + 700, 356, 433, 524, 581, 0, 637, 0, 606, 609, + 639, 726, 727, 728, 346, 608, 730, 731, 732, 733, + 734, 735, 736, 729, 577, 672, 648, 675, 587, 651, + 650, 0, 0, 686, 604, 687, 688, 488, 489, 490, + 491, 408, 714, 371, 607, 521, 522, 0, 673, 0, + 0, 0, 0, 0, 0, 0, 0, 678, 679, 676, + 797, 0, 737, 738, 0, 0, 601, 602, 403, 0, + 620, 411, 370, 505, 405, 585, 436, 0, 613, 680, + 614, 525, 526, 741, 746, 742, 743, 745, 766, 495, + 425, 431, 542, 446, 468, 528, 584, 503, 533, 368, + 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 718, 717, 716, 715, 714, 713, 712, - 711, 0, 0, 658, 384, 781, 775, 782, 763, 766, - 765, 740, 0, 341, 638, 464, 518, 401, 705, 706, - 0, 761, 284, 285, 286, 287, 288, 289, 290, 291, - 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, - 305, 306, 307, 308, 309, 310, 708, 301, 302, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 324, 0, 0, 0, 0, 333, 767, 768, - 769, 770, 771, 0, 0, 334, 335, 336, 0, 0, - 299, 300, 327, 549, 328, 329, 330, 331, 0, 0, - 587, 588, 589, 612, 0, 590, 572, 637, 411, 342, - 553, 579, 778, 779, 0, 0, 0, 0, 0, 0, - 0, 688, 699, 735, 736, 0, 749, 750, 752, 754, - 753, 756, 546, 547, 764, 0, 0, 435, 357, 358, - 494, 495, 532, 0, 436, 437, 438, 442, 439, 440, - 441, 758, 759, 760, 757, 468, 531, 554, 540, 777, - 481, 0, 785, 627, 628, 786, 745, 744, 343, 0, - 337, 338, 702, 703, 0, 0, 534, 480, 634, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 2621, - 0, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 0, 680, 629, 542, - 482, 0, 697, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 268, 0, 0, 2622, 0, 0, - 0, 365, 269, 624, 751, 626, 625, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 0, 0, 1565, - 0, 1566, 1564, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 0, 0, 0, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 0, 0, 565, 595, - 387, 585, 0, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 611, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 0, 0, - 748, 0, 578, 0, 0, 0, 0, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 596, 0, 529, 502, - 789, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 386, 498, - 709, 746, 747, 631, 0, 695, 632, 642, 379, 667, - 679, 678, 492, 591, 0, 690, 693, 621, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 574, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 600, 683, 684, - 486, 487, 488, 489, 407, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, - 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 0, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 284, 285, 286, 287, 288, 289, - 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, - 303, 304, 305, 306, 307, 308, 309, 310, 708, 301, - 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, - 767, 768, 769, 770, 771, 0, 0, 334, 335, 336, - 0, 0, 299, 300, 327, 549, 328, 329, 330, 331, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 753, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 758, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 0, - 343, 0, 337, 338, 702, 703, 0, 0, 534, 480, - 634, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 394, - 1868, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 0, 680, 629, 542, 482, 0, 697, 0, 0, + 0, 0, 722, 721, 720, 719, 718, 717, 716, 715, + 0, 0, 662, 385, 785, 779, 786, 767, 770, 769, + 744, 0, 341, 642, 466, 520, 402, 709, 710, 0, + 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, + 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, + 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 0, 0, 0, 0, 333, 771, 772, 773, + 774, 775, 0, 0, 334, 335, 336, 0, 0, 299, + 300, 327, 552, 328, 329, 330, 331, 0, 0, 591, + 592, 593, 616, 0, 594, 575, 641, 412, 342, 556, + 583, 782, 783, 0, 0, 0, 0, 0, 0, 0, + 692, 703, 739, 740, 0, 753, 754, 756, 758, 757, + 760, 549, 550, 768, 0, 0, 437, 358, 359, 496, + 497, 535, 0, 438, 439, 440, 444, 441, 442, 443, + 762, 763, 764, 761, 470, 534, 557, 543, 781, 483, + 0, 789, 631, 632, 790, 749, 748, 343, 0, 337, + 338, 706, 707, 0, 0, 537, 482, 638, 502, 2459, + 0, 647, 681, 670, 759, 634, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 395, 0, 0, 465, + 685, 666, 677, 667, 508, 652, 653, 654, 661, 407, + 655, 791, 657, 626, 658, 627, 659, 660, 0, 684, + 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 268, 1250, 1251, 0, + 0, 0, 0, 366, 269, 628, 755, 630, 629, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1254, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 546, + 574, 0, 588, 0, 434, 435, 0, 0, 0, 0, + 0, 0, 0, 350, 553, 571, 367, 540, 586, 372, + 548, 564, 362, 501, 536, 0, 0, 352, 569, 547, + 479, 351, 0, 529, 392, 409, 389, 499, 0, 0, + 568, 599, 388, 589, 901, 579, 354, 900, 578, 498, + 471, 565, 570, 480, 473, 0, 353, 567, 478, 472, + 448, 399, 615, 449, 450, 451, 452, 453, 454, 413, + 514, 469, 515, 414, 486, 485, 487, 415, 416, 417, + 418, 419, 420, 421, 422, 423, 424, 0, 0, 0, + 0, 0, 610, 611, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 747, + 0, 0, 752, 0, 582, 0, 0, 0, 0, 0, + 0, 551, 0, 0, 455, 0, 0, 0, 600, 0, + 532, 504, 793, 0, 0, 530, 467, 566, 516, 572, + 554, 580, 523, 517, 344, 555, 391, 481, 363, 365, + 780, 393, 396, 400, 401, 492, 493, 510, 539, 558, + 559, 560, 390, 377, 531, 378, 410, 379, 345, 382, + 381, 383, 541, 384, 347, 511, 563, 0, 406, 527, + 476, 348, 475, 512, 562, 561, 364, 590, 597, 598, + 689, 0, 603, 794, 795, 796, 612, 0, 518, 360, + 357, 0, 0, 0, 386, 513, 373, 375, 376, 374, + 507, 509, 617, 618, 619, 621, 0, 622, 623, 0, + 0, 0, 0, 624, 690, 708, 674, 643, 605, 698, + 640, 644, 645, 427, 428, 429, 430, 711, 0, 0, + 0, 596, 456, 457, 0, 398, 397, 477, 349, 0, + 0, 445, 426, 519, 355, 394, 447, 432, 458, 459, + 460, 461, 462, 0, 463, 464, 404, 339, 340, 788, + 387, 500, 713, 750, 751, 635, 0, 699, 636, 646, + 380, 671, 683, 682, 494, 595, 0, 694, 697, 625, + 787, 0, 691, 705, 792, 704, 784, 506, 0, 538, + 702, 649, 0, 695, 668, 669, 0, 696, 664, 700, + 356, 433, 524, 581, 0, 637, 0, 606, 609, 639, + 726, 727, 728, 346, 608, 730, 731, 732, 733, 734, + 735, 736, 729, 577, 672, 648, 675, 587, 651, 650, + 0, 0, 686, 604, 687, 688, 488, 489, 490, 491, + 408, 714, 371, 607, 521, 522, 0, 673, 0, 0, + 0, 0, 0, 0, 0, 0, 678, 679, 676, 797, + 0, 737, 738, 0, 0, 601, 602, 403, 0, 620, + 411, 370, 505, 405, 585, 436, 0, 613, 680, 614, + 525, 526, 741, 746, 742, 743, 745, 766, 1252, 2565, + 1248, 2566, 446, 468, 528, 584, 503, 533, 368, 573, + 544, 1249, 665, 693, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, - 0, 0, 1866, 0, 0, 0, 365, 269, 624, 751, - 626, 625, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 1864, - 0, 0, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 0, 0, 565, 595, 387, 585, 0, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 611, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 0, 0, 748, 0, 578, 0, 0, - 0, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 596, 0, 529, 502, 789, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 386, 498, 709, 746, 747, 631, 0, - 695, 632, 642, 379, 667, 679, 678, 492, 591, 0, - 690, 693, 621, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 574, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 600, 683, 684, 486, 487, 488, 489, 407, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 0, 0, 0, 0, 0, 0, 0, + 0, 722, 721, 720, 719, 718, 717, 716, 715, 0, + 0, 662, 385, 785, 779, 786, 767, 770, 769, 744, + 0, 341, 642, 466, 520, 402, 709, 710, 0, 765, + 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, + 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, + 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, + 324, 0, 0, 0, 0, 333, 771, 772, 773, 774, + 775, 0, 0, 334, 335, 336, 0, 0, 299, 300, + 327, 552, 328, 329, 330, 331, 0, 0, 591, 592, + 593, 616, 0, 594, 575, 641, 412, 342, 556, 583, + 782, 783, 0, 0, 0, 0, 0, 0, 0, 692, + 703, 739, 740, 0, 753, 754, 756, 758, 757, 760, + 549, 550, 768, 0, 0, 437, 358, 359, 496, 497, + 535, 0, 438, 439, 440, 444, 441, 442, 443, 762, + 763, 764, 761, 470, 534, 557, 543, 781, 483, 0, + 789, 631, 632, 790, 749, 748, 343, 0, 337, 338, + 706, 707, 0, 0, 537, 482, 638, 502, 0, 0, + 647, 681, 670, 759, 634, 0, 0, 3761, 0, 0, + 0, 0, 0, 0, 0, 395, 0, 0, 465, 685, + 666, 677, 667, 508, 652, 653, 654, 661, 407, 655, + 791, 657, 626, 658, 627, 659, 660, 0, 684, 633, + 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 268, 0, 0, 0, 0, + 0, 0, 366, 269, 628, 755, 630, 629, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 369, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 546, 574, + 0, 588, 0, 434, 435, 0, 0, 0, 0, 0, + 0, 0, 350, 553, 571, 367, 540, 586, 372, 548, + 564, 362, 501, 536, 0, 0, 352, 569, 547, 479, + 351, 0, 529, 392, 409, 389, 499, 0, 0, 568, + 599, 388, 589, 0, 579, 354, 0, 578, 498, 471, + 565, 570, 480, 473, 0, 353, 567, 478, 472, 448, + 399, 615, 449, 450, 451, 452, 453, 454, 413, 514, + 469, 515, 414, 486, 485, 487, 415, 416, 417, 418, + 419, 420, 421, 422, 423, 424, 0, 0, 0, 0, + 0, 610, 611, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3764, 0, 0, 0, 0, 3763, 747, 0, + 0, 752, 0, 582, 0, 0, 0, 0, 0, 0, + 551, 0, 0, 455, 0, 0, 0, 600, 0, 532, + 504, 793, 0, 0, 530, 467, 566, 516, 572, 554, + 580, 523, 517, 344, 555, 391, 481, 363, 365, 780, + 393, 396, 400, 401, 492, 493, 510, 539, 558, 559, + 560, 390, 377, 531, 378, 410, 379, 345, 382, 381, + 383, 541, 384, 347, 511, 563, 0, 406, 527, 476, + 348, 475, 512, 562, 561, 364, 590, 597, 598, 689, + 0, 603, 794, 795, 796, 612, 0, 518, 360, 357, + 0, 0, 0, 386, 513, 373, 375, 376, 374, 507, + 509, 617, 618, 619, 621, 0, 622, 623, 0, 0, + 0, 0, 624, 690, 708, 674, 643, 605, 698, 640, + 644, 645, 427, 428, 429, 430, 711, 0, 0, 0, + 596, 456, 457, 0, 398, 397, 477, 349, 0, 0, + 445, 426, 519, 355, 394, 447, 432, 458, 459, 460, + 461, 462, 0, 463, 464, 404, 339, 340, 788, 387, + 500, 713, 750, 751, 635, 0, 699, 636, 646, 380, + 671, 683, 682, 494, 595, 0, 694, 697, 625, 787, + 0, 691, 705, 792, 704, 784, 506, 0, 538, 702, + 649, 0, 695, 668, 669, 0, 696, 664, 700, 356, + 433, 524, 581, 0, 637, 0, 606, 609, 639, 726, + 727, 728, 346, 608, 730, 731, 732, 733, 734, 735, + 736, 729, 577, 672, 648, 675, 587, 651, 650, 0, + 0, 686, 604, 687, 688, 488, 489, 490, 491, 408, + 714, 371, 607, 521, 522, 0, 673, 0, 0, 0, + 0, 0, 0, 0, 0, 678, 679, 676, 797, 0, + 737, 738, 0, 0, 601, 602, 403, 0, 620, 411, + 370, 505, 405, 585, 436, 0, 613, 680, 614, 525, + 526, 741, 746, 742, 743, 745, 766, 495, 425, 431, + 542, 446, 468, 528, 584, 503, 533, 368, 573, 544, + 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 0, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 284, + 722, 721, 720, 719, 718, 717, 716, 715, 0, 0, + 662, 385, 785, 779, 786, 767, 770, 769, 744, 0, + 341, 642, 466, 520, 402, 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, - 308, 309, 310, 708, 301, 302, 311, 312, 313, 314, + 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 0, 0, 0, 0, 333, 767, 768, 769, 770, 771, + 0, 0, 0, 0, 333, 771, 772, 773, 774, 775, 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, - 549, 328, 329, 330, 331, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 753, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 758, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 337, 338, 702, - 703, 0, 0, 534, 480, 634, 500, 0, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 394, 1862, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 0, 680, 629, 542, - 482, 0, 697, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 268, 0, 0, 1866, 0, 0, - 0, 365, 269, 624, 751, 626, 625, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 1864, 0, 0, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 0, 0, 565, 595, - 387, 585, 0, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 611, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 0, 0, - 748, 0, 578, 0, 0, 0, 0, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 596, 0, 529, 502, - 789, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 386, 498, - 709, 746, 747, 631, 0, 695, 632, 642, 379, 667, - 679, 678, 492, 591, 0, 690, 693, 621, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 574, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 600, 683, 684, - 486, 487, 488, 489, 407, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 0, 0, + 552, 328, 329, 330, 331, 0, 0, 591, 592, 593, + 616, 0, 594, 575, 641, 412, 342, 556, 583, 782, + 783, 0, 0, 0, 0, 0, 0, 0, 692, 703, + 739, 740, 0, 753, 754, 756, 758, 757, 760, 549, + 550, 768, 0, 0, 437, 358, 359, 496, 497, 535, + 0, 438, 439, 440, 444, 441, 442, 443, 762, 763, + 764, 761, 470, 534, 557, 543, 781, 483, 0, 789, + 631, 632, 790, 749, 748, 343, 0, 337, 338, 706, + 707, 0, 0, 537, 482, 638, 647, 681, 670, 759, + 634, 0, 0, 0, 0, 0, 2625, 0, 0, 0, + 0, 395, 0, 0, 465, 685, 666, 677, 667, 508, + 652, 653, 654, 661, 407, 655, 791, 657, 626, 658, + 627, 659, 660, 0, 684, 633, 545, 484, 0, 701, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 268, 0, 0, 2626, 0, 0, 0, 366, 269, + 628, 755, 630, 629, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 369, 0, 0, 1569, 0, 1570, 1568, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 546, 574, 0, 588, 0, 434, + 435, 0, 0, 0, 0, 0, 0, 0, 350, 553, + 571, 367, 540, 586, 372, 548, 564, 362, 501, 536, + 0, 0, 352, 569, 547, 479, 351, 0, 529, 392, + 409, 389, 499, 0, 0, 568, 599, 388, 589, 0, + 579, 354, 0, 578, 498, 471, 565, 570, 480, 473, + 0, 353, 567, 478, 472, 448, 399, 615, 449, 450, + 451, 452, 453, 454, 413, 514, 469, 515, 414, 486, + 485, 487, 415, 416, 417, 418, 419, 420, 421, 422, + 423, 424, 0, 0, 0, 0, 0, 610, 611, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 747, 0, 0, 752, 0, 582, + 0, 0, 0, 0, 0, 0, 551, 0, 0, 455, + 0, 0, 0, 600, 0, 532, 504, 793, 0, 0, + 530, 467, 566, 516, 572, 554, 580, 523, 517, 344, + 555, 391, 481, 363, 365, 780, 393, 396, 400, 401, + 492, 493, 510, 539, 558, 559, 560, 390, 377, 531, + 378, 410, 379, 345, 382, 381, 383, 541, 384, 347, + 511, 563, 0, 406, 527, 476, 348, 475, 512, 562, + 561, 364, 590, 597, 598, 689, 0, 603, 794, 795, + 796, 612, 0, 518, 360, 357, 0, 0, 0, 386, + 513, 373, 375, 376, 374, 507, 509, 617, 618, 619, + 621, 0, 622, 623, 0, 0, 0, 0, 624, 690, + 708, 674, 643, 605, 698, 640, 644, 645, 427, 428, + 429, 430, 711, 0, 0, 0, 596, 456, 457, 0, + 398, 397, 477, 349, 0, 0, 445, 426, 519, 355, + 394, 447, 432, 458, 459, 460, 461, 462, 0, 463, + 464, 404, 339, 340, 788, 387, 500, 713, 750, 751, + 635, 0, 699, 636, 646, 380, 671, 683, 682, 494, + 595, 0, 694, 697, 625, 787, 0, 691, 705, 792, + 704, 784, 506, 0, 538, 702, 649, 0, 695, 668, + 669, 0, 696, 664, 700, 356, 433, 524, 581, 0, + 637, 0, 606, 609, 639, 726, 727, 728, 346, 608, + 730, 731, 732, 733, 734, 735, 736, 729, 577, 672, + 648, 675, 587, 651, 650, 0, 0, 686, 604, 687, + 688, 488, 489, 490, 491, 408, 714, 371, 607, 521, + 522, 0, 673, 0, 0, 0, 0, 0, 0, 0, + 0, 678, 679, 676, 797, 0, 737, 738, 0, 0, + 601, 602, 403, 0, 620, 411, 370, 505, 405, 585, + 436, 0, 613, 680, 614, 525, 526, 741, 746, 742, + 743, 745, 766, 495, 425, 431, 542, 446, 468, 528, + 584, 503, 533, 368, 573, 544, 474, 665, 693, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 722, 721, 720, 719, + 718, 717, 716, 715, 0, 0, 662, 385, 785, 779, + 786, 767, 770, 769, 744, 0, 341, 642, 466, 520, + 402, 709, 710, 0, 765, 284, 285, 286, 287, 288, + 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, + 298, 303, 304, 305, 306, 307, 308, 309, 310, 712, + 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, + 333, 771, 772, 773, 774, 775, 0, 0, 334, 335, + 336, 0, 0, 299, 300, 327, 552, 328, 329, 330, + 331, 0, 0, 591, 592, 593, 616, 0, 594, 575, + 641, 412, 342, 556, 583, 782, 783, 0, 0, 0, + 0, 0, 0, 0, 692, 703, 739, 740, 0, 753, + 754, 756, 758, 757, 760, 549, 550, 768, 0, 0, + 437, 358, 359, 496, 497, 535, 0, 438, 439, 440, + 444, 441, 442, 443, 762, 763, 764, 761, 470, 534, + 557, 543, 781, 483, 0, 789, 631, 632, 790, 749, + 0, 343, 0, 337, 338, 706, 707, 0, 0, 537, + 482, 638, 502, 0, 0, 647, 681, 670, 759, 634, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 395, 1872, 0, 465, 685, 666, 677, 667, 508, 652, + 653, 654, 661, 407, 655, 791, 657, 626, 658, 627, + 659, 660, 0, 684, 633, 545, 484, 0, 701, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 268, 0, 0, 1870, 0, 0, 0, 366, 269, 628, + 755, 630, 629, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 369, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 546, 574, 0, 588, 0, 434, 435, + 1868, 0, 0, 0, 0, 0, 0, 350, 553, 571, + 367, 540, 586, 372, 548, 564, 362, 501, 536, 0, + 0, 352, 569, 547, 479, 351, 0, 529, 392, 409, + 389, 499, 0, 0, 568, 599, 388, 589, 0, 579, + 354, 0, 578, 498, 471, 565, 570, 480, 473, 0, + 353, 567, 478, 472, 448, 399, 615, 449, 450, 451, + 452, 453, 454, 413, 514, 469, 515, 414, 486, 485, + 487, 415, 416, 417, 418, 419, 420, 421, 422, 423, + 424, 0, 0, 0, 0, 0, 610, 611, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 747, 0, 0, 752, 0, 582, 0, + 0, 0, 0, 0, 0, 551, 0, 0, 455, 0, + 0, 0, 600, 0, 532, 504, 793, 0, 0, 530, + 467, 566, 516, 572, 554, 580, 523, 517, 344, 555, + 391, 481, 363, 365, 780, 393, 396, 400, 401, 492, + 493, 510, 539, 558, 559, 560, 390, 377, 531, 378, + 410, 379, 345, 382, 381, 383, 541, 384, 347, 511, + 563, 0, 406, 527, 476, 348, 475, 512, 562, 561, + 364, 590, 597, 598, 689, 0, 603, 794, 795, 796, + 612, 0, 518, 360, 357, 0, 0, 0, 386, 513, + 373, 375, 376, 374, 507, 509, 617, 618, 619, 621, + 0, 622, 623, 0, 0, 0, 0, 624, 690, 708, + 674, 643, 605, 698, 640, 644, 645, 427, 428, 429, + 430, 711, 0, 0, 0, 596, 456, 457, 0, 398, + 397, 477, 349, 0, 0, 445, 426, 519, 355, 394, + 447, 432, 458, 459, 460, 461, 462, 0, 463, 464, + 404, 339, 340, 788, 387, 500, 713, 750, 751, 635, + 0, 699, 636, 646, 380, 671, 683, 682, 494, 595, + 0, 694, 697, 625, 787, 0, 691, 705, 792, 704, + 784, 506, 0, 538, 702, 649, 0, 695, 668, 669, + 0, 696, 664, 700, 356, 433, 524, 581, 0, 637, + 0, 606, 609, 639, 726, 727, 728, 346, 608, 730, + 731, 732, 733, 734, 735, 736, 729, 577, 672, 648, + 675, 587, 651, 650, 0, 0, 686, 604, 687, 688, + 488, 489, 490, 491, 408, 714, 371, 607, 521, 522, + 0, 673, 0, 0, 0, 0, 0, 0, 0, 0, + 678, 679, 676, 797, 0, 737, 738, 0, 0, 601, + 602, 403, 0, 620, 411, 370, 505, 405, 585, 436, + 0, 613, 680, 614, 525, 526, 741, 746, 742, 743, + 745, 766, 495, 425, 431, 542, 446, 468, 528, 584, + 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 0, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 284, 285, 286, 287, 288, 289, + 0, 0, 0, 0, 0, 722, 721, 720, 719, 718, + 717, 716, 715, 0, 0, 662, 385, 785, 779, 786, + 767, 770, 769, 744, 0, 341, 642, 466, 520, 402, + 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, - 303, 304, 305, 306, 307, 308, 309, 310, 708, 301, + 303, 304, 305, 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, - 767, 768, 769, 770, 771, 0, 0, 334, 335, 336, - 0, 0, 299, 300, 327, 549, 328, 329, 330, 331, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 753, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 758, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 744, - 343, 0, 337, 338, 702, 703, 0, 0, 534, 480, - 634, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 1200, 0, 0, 0, 0, 0, 0, 1205, 394, - 0, 0, 463, 681, 1201, 673, 663, 1203, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 0, 680, 629, 542, 482, 0, 697, 0, 0, + 771, 772, 773, 774, 775, 0, 0, 334, 335, 336, + 0, 0, 299, 300, 327, 552, 328, 329, 330, 331, + 0, 0, 591, 592, 593, 616, 0, 594, 575, 641, + 412, 342, 556, 583, 782, 783, 0, 0, 0, 0, + 0, 0, 0, 692, 703, 739, 740, 0, 753, 754, + 756, 758, 757, 760, 549, 550, 768, 0, 0, 437, + 358, 359, 496, 497, 535, 0, 438, 439, 440, 444, + 441, 442, 443, 762, 763, 764, 761, 470, 534, 557, + 543, 781, 483, 0, 789, 631, 632, 790, 749, 748, + 343, 0, 337, 338, 706, 707, 0, 0, 537, 482, + 638, 502, 0, 0, 647, 681, 670, 759, 634, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 395, + 1866, 0, 465, 685, 666, 677, 667, 508, 652, 653, + 654, 661, 407, 655, 791, 657, 626, 658, 627, 659, + 660, 0, 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, - 0, 0, 0, 0, 0, 0, 365, 269, 624, 751, - 626, 625, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 0, - 0, 0, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 0, 0, 565, 595, 387, 585, 0, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 611, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 0, 0, 748, 0, 578, 0, 1204, - 0, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 596, 0, 529, 502, 789, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 386, 498, 709, 746, 747, 631, 0, - 695, 632, 642, 379, 667, 679, 678, 492, 591, 0, - 690, 693, 621, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 574, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 600, 683, 684, 486, 487, 488, 489, 407, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, + 0, 0, 1870, 0, 0, 0, 366, 269, 628, 755, + 630, 629, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 369, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 546, 574, 0, 588, 0, 434, 435, 1868, + 0, 0, 0, 0, 0, 0, 350, 553, 571, 367, + 540, 586, 372, 548, 564, 362, 501, 536, 0, 0, + 352, 569, 547, 479, 351, 0, 529, 392, 409, 389, + 499, 0, 0, 568, 599, 388, 589, 0, 579, 354, + 0, 578, 498, 471, 565, 570, 480, 473, 0, 353, + 567, 478, 472, 448, 399, 615, 449, 450, 451, 452, + 453, 454, 413, 514, 469, 515, 414, 486, 485, 487, + 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, + 0, 0, 0, 0, 0, 610, 611, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 747, 0, 0, 752, 0, 582, 0, 0, + 0, 0, 0, 0, 551, 0, 0, 455, 0, 0, + 0, 600, 0, 532, 504, 793, 0, 0, 530, 467, + 566, 516, 572, 554, 580, 523, 517, 344, 555, 391, + 481, 363, 365, 780, 393, 396, 400, 401, 492, 493, + 510, 539, 558, 559, 560, 390, 377, 531, 378, 410, + 379, 345, 382, 381, 383, 541, 384, 347, 511, 563, + 0, 406, 527, 476, 348, 475, 512, 562, 561, 364, + 590, 597, 598, 689, 0, 603, 794, 795, 796, 612, + 0, 518, 360, 357, 0, 0, 0, 386, 513, 373, + 375, 376, 374, 507, 509, 617, 618, 619, 621, 0, + 622, 623, 0, 0, 0, 0, 624, 690, 708, 674, + 643, 605, 698, 640, 644, 645, 427, 428, 429, 430, + 711, 0, 0, 0, 596, 456, 457, 0, 398, 397, + 477, 349, 0, 0, 445, 426, 519, 355, 394, 447, + 432, 458, 459, 460, 461, 462, 0, 463, 464, 404, + 339, 340, 788, 387, 500, 713, 750, 751, 635, 0, + 699, 636, 646, 380, 671, 683, 682, 494, 595, 0, + 694, 697, 625, 787, 0, 691, 705, 792, 704, 784, + 506, 0, 538, 702, 649, 0, 695, 668, 669, 0, + 696, 664, 700, 356, 433, 524, 581, 0, 637, 0, + 606, 609, 639, 726, 727, 728, 346, 608, 730, 731, + 732, 733, 734, 735, 736, 729, 577, 672, 648, 675, + 587, 651, 650, 0, 0, 686, 604, 687, 688, 488, + 489, 490, 491, 408, 714, 371, 607, 521, 522, 0, + 673, 0, 0, 0, 0, 0, 0, 0, 0, 678, + 679, 676, 797, 0, 737, 738, 0, 0, 601, 602, + 403, 0, 620, 411, 370, 505, 405, 585, 436, 0, + 613, 680, 614, 525, 526, 741, 746, 742, 743, 745, + 766, 495, 425, 431, 542, 446, 468, 528, 584, 503, + 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 0, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 284, - 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, - 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, - 308, 309, 310, 708, 301, 302, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 0, 0, 0, 0, 333, 767, 768, 769, 770, 771, - 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, - 549, 328, 329, 330, 331, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 753, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 758, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 337, 338, 702, - 703, 0, 0, 534, 480, 634, 500, 0, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 0, 680, 629, 542, - 482, 0, 697, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 5226, 0, 268, 1069, 0, 0, 0, 0, - 0, 365, 269, 624, 751, 626, 625, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 0, 0, 0, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 0, 0, 565, 595, - 387, 585, 0, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 611, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 0, 0, - 748, 0, 578, 0, 0, 0, 0, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 596, 0, 529, 502, - 789, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 386, 498, - 709, 746, 747, 631, 0, 695, 632, 642, 379, 667, - 679, 678, 492, 591, 0, 690, 693, 621, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 574, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 600, 683, 684, - 486, 487, 488, 489, 407, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, - 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 0, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 284, 285, 286, 287, 288, 289, - 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, - 303, 304, 305, 306, 307, 308, 309, 310, 708, 301, - 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, - 767, 768, 769, 770, 771, 0, 0, 334, 335, 336, - 0, 0, 299, 300, 327, 549, 328, 329, 330, 331, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 753, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 758, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 744, - 343, 0, 337, 338, 702, 703, 0, 0, 534, 480, - 634, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 394, - 0, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 0, 680, 629, 542, 482, 0, 697, 0, 0, + 0, 0, 0, 0, 722, 721, 720, 719, 718, 717, + 716, 715, 0, 0, 662, 385, 785, 779, 786, 767, + 770, 769, 744, 0, 341, 642, 466, 520, 402, 709, + 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, + 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, + 304, 305, 306, 307, 308, 309, 310, 712, 301, 302, + 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 0, 0, 0, 0, 333, 771, + 772, 773, 774, 775, 0, 0, 334, 335, 336, 0, + 0, 299, 300, 327, 552, 328, 329, 330, 331, 0, + 0, 591, 592, 593, 616, 0, 594, 575, 641, 412, + 342, 556, 583, 782, 783, 0, 0, 0, 0, 0, + 0, 0, 692, 703, 739, 740, 0, 753, 754, 756, + 758, 757, 760, 549, 550, 768, 0, 0, 437, 358, + 359, 496, 497, 535, 0, 438, 439, 440, 444, 441, + 442, 443, 762, 763, 764, 761, 470, 534, 557, 543, + 781, 483, 0, 789, 631, 632, 790, 749, 748, 343, + 0, 337, 338, 706, 707, 0, 0, 537, 482, 638, + 502, 0, 0, 647, 681, 670, 759, 634, 0, 0, + 1204, 0, 0, 0, 0, 0, 0, 1209, 395, 0, + 0, 465, 685, 1205, 677, 667, 1207, 652, 653, 654, + 661, 407, 655, 791, 657, 626, 658, 627, 659, 660, + 0, 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, - 0, 0, 1866, 0, 0, 0, 365, 269, 624, 751, - 626, 625, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 1864, - 0, 0, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 0, 0, 565, 595, 387, 585, 0, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 611, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 0, 0, 748, 0, 578, 0, 0, - 0, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 596, 0, 529, 502, 789, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 386, 498, 709, 746, 747, 631, 0, - 695, 632, 642, 379, 667, 679, 678, 492, 591, 0, - 690, 693, 621, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 574, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 600, 683, 684, 486, 487, 488, 489, 407, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 268, 0, + 0, 0, 0, 0, 0, 366, 269, 628, 755, 630, + 629, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 369, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 546, 574, 0, 588, 0, 434, 435, 0, 0, + 0, 0, 0, 0, 0, 350, 553, 571, 367, 540, + 586, 372, 548, 564, 362, 501, 536, 0, 0, 352, + 569, 547, 479, 351, 0, 529, 392, 409, 389, 499, + 0, 0, 568, 599, 388, 589, 0, 579, 354, 0, + 578, 498, 471, 565, 570, 480, 473, 0, 353, 567, + 478, 472, 448, 399, 615, 449, 450, 451, 452, 453, + 454, 413, 514, 469, 515, 414, 486, 485, 487, 415, + 416, 417, 418, 419, 420, 421, 422, 423, 424, 0, + 0, 0, 0, 0, 610, 611, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 747, 0, 0, 752, 0, 582, 0, 1208, 0, + 0, 0, 0, 551, 0, 0, 455, 0, 0, 0, + 600, 0, 532, 504, 793, 0, 0, 530, 467, 566, + 516, 572, 554, 580, 523, 517, 344, 555, 391, 481, + 363, 365, 780, 393, 396, 400, 401, 492, 493, 510, + 539, 558, 559, 560, 390, 377, 531, 378, 410, 379, + 345, 382, 381, 383, 541, 384, 347, 511, 563, 0, + 406, 527, 476, 348, 475, 512, 562, 561, 364, 590, + 597, 598, 689, 0, 603, 794, 795, 796, 612, 0, + 518, 360, 357, 0, 0, 0, 386, 513, 373, 375, + 376, 374, 507, 509, 617, 618, 619, 621, 0, 622, + 623, 0, 0, 0, 0, 624, 690, 708, 674, 643, + 605, 698, 640, 644, 645, 427, 428, 429, 430, 711, + 0, 0, 0, 596, 456, 457, 0, 398, 397, 477, + 349, 0, 0, 445, 426, 519, 355, 394, 447, 432, + 458, 459, 460, 461, 462, 0, 463, 464, 404, 339, + 340, 788, 387, 500, 713, 750, 751, 635, 0, 699, + 636, 646, 380, 671, 683, 682, 494, 595, 0, 694, + 697, 625, 787, 0, 691, 705, 792, 704, 784, 506, + 0, 538, 702, 649, 0, 695, 668, 669, 0, 696, + 664, 700, 356, 433, 524, 581, 0, 637, 0, 606, + 609, 639, 726, 727, 728, 346, 608, 730, 731, 732, + 733, 734, 735, 736, 729, 577, 672, 648, 675, 587, + 651, 650, 0, 0, 686, 604, 687, 688, 488, 489, + 490, 491, 408, 714, 371, 607, 521, 522, 0, 673, + 0, 0, 0, 0, 0, 0, 0, 0, 678, 679, + 676, 797, 0, 737, 738, 0, 0, 601, 602, 403, + 0, 620, 411, 370, 505, 405, 585, 436, 0, 613, + 680, 614, 525, 526, 741, 746, 742, 743, 745, 766, + 495, 425, 431, 542, 446, 468, 528, 584, 503, 533, + 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 0, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 284, - 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, - 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, - 308, 309, 310, 708, 301, 302, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 0, 0, 0, 0, 333, 767, 768, 769, 770, 771, - 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, - 549, 328, 329, 330, 331, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 753, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 758, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 337, 338, 702, - 703, 0, 0, 534, 480, 634, 500, 0, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 0, 680, 629, 542, - 482, 0, 697, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 268, 0, 0, 1866, 0, 0, - 0, 365, 269, 624, 751, 626, 625, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 2184, 0, 0, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 0, 0, 565, 595, - 387, 585, 0, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 611, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 0, 0, - 748, 0, 578, 0, 0, 0, 0, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 596, 0, 529, 502, - 789, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 386, 498, - 709, 746, 747, 631, 0, 695, 632, 642, 379, 667, - 679, 678, 492, 591, 0, 690, 693, 621, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 574, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 600, 683, 684, - 486, 487, 488, 489, 407, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, - 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 0, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 284, 285, 286, 287, 288, 289, - 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, - 303, 304, 305, 306, 307, 308, 309, 310, 708, 301, - 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, - 767, 768, 769, 770, 771, 0, 0, 334, 335, 336, - 0, 0, 299, 300, 327, 549, 328, 329, 330, 331, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 753, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 758, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 744, - 343, 0, 337, 338, 702, 703, 0, 0, 534, 480, - 634, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 394, - 0, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 0, 680, 629, 542, 482, 0, 697, 0, 0, + 0, 0, 0, 722, 721, 720, 719, 718, 717, 716, + 715, 0, 0, 662, 385, 785, 779, 786, 767, 770, + 769, 744, 0, 341, 642, 466, 520, 402, 709, 710, + 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, + 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, + 305, 306, 307, 308, 309, 310, 712, 301, 302, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 0, 0, 0, 0, 333, 771, 772, + 773, 774, 775, 0, 0, 334, 335, 336, 0, 0, + 299, 300, 327, 552, 328, 329, 330, 331, 0, 0, + 591, 592, 593, 616, 0, 594, 575, 641, 412, 342, + 556, 583, 782, 783, 0, 0, 0, 0, 0, 0, + 0, 692, 703, 739, 740, 0, 753, 754, 756, 758, + 757, 760, 549, 550, 768, 0, 0, 437, 358, 359, + 496, 497, 535, 0, 438, 439, 440, 444, 441, 442, + 443, 762, 763, 764, 761, 470, 534, 557, 543, 781, + 483, 0, 789, 631, 632, 790, 749, 748, 343, 0, + 337, 338, 706, 707, 0, 0, 537, 482, 638, 502, + 0, 0, 647, 681, 670, 759, 634, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 395, 0, 0, + 465, 685, 666, 677, 667, 508, 652, 653, 654, 661, + 407, 655, 791, 657, 626, 658, 627, 659, 660, 0, + 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5230, 0, 268, 1073, 0, + 0, 0, 0, 0, 366, 269, 628, 755, 630, 629, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 369, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 546, 574, 0, 588, 0, 434, 435, 0, 0, 0, + 0, 0, 0, 0, 350, 553, 571, 367, 540, 586, + 372, 548, 564, 362, 501, 536, 0, 0, 352, 569, + 547, 479, 351, 0, 529, 392, 409, 389, 499, 0, + 0, 568, 599, 388, 589, 0, 579, 354, 0, 578, + 498, 471, 565, 570, 480, 473, 0, 353, 567, 478, + 472, 448, 399, 615, 449, 450, 451, 452, 453, 454, + 413, 514, 469, 515, 414, 486, 485, 487, 415, 416, + 417, 418, 419, 420, 421, 422, 423, 424, 0, 0, + 0, 0, 0, 610, 611, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 747, 0, 0, 752, 0, 582, 0, 0, 0, 0, + 0, 0, 551, 0, 0, 455, 0, 0, 0, 600, + 0, 532, 504, 793, 0, 0, 530, 467, 566, 516, + 572, 554, 580, 523, 517, 344, 555, 391, 481, 363, + 365, 780, 393, 396, 400, 401, 492, 493, 510, 539, + 558, 559, 560, 390, 377, 531, 378, 410, 379, 345, + 382, 381, 383, 541, 384, 347, 511, 563, 0, 406, + 527, 476, 348, 475, 512, 562, 561, 364, 590, 597, + 598, 689, 0, 603, 794, 795, 796, 612, 0, 518, + 360, 357, 0, 0, 0, 386, 513, 373, 375, 376, + 374, 507, 509, 617, 618, 619, 621, 0, 622, 623, + 0, 0, 0, 0, 624, 690, 708, 674, 643, 605, + 698, 640, 644, 645, 427, 428, 429, 430, 711, 0, + 0, 0, 596, 456, 457, 0, 398, 397, 477, 349, + 0, 0, 445, 426, 519, 355, 394, 447, 432, 458, + 459, 460, 461, 462, 0, 463, 464, 404, 339, 340, + 788, 387, 500, 713, 750, 751, 635, 0, 699, 636, + 646, 380, 671, 683, 682, 494, 595, 0, 694, 697, + 625, 787, 0, 691, 705, 792, 704, 784, 506, 0, + 538, 702, 649, 0, 695, 668, 669, 0, 696, 664, + 700, 356, 433, 524, 581, 0, 637, 0, 606, 609, + 639, 726, 727, 728, 346, 608, 730, 731, 732, 733, + 734, 735, 736, 729, 577, 672, 648, 675, 587, 651, + 650, 0, 0, 686, 604, 687, 688, 488, 489, 490, + 491, 408, 714, 371, 607, 521, 522, 0, 673, 0, + 0, 0, 0, 0, 0, 0, 0, 678, 679, 676, + 797, 0, 737, 738, 0, 0, 601, 602, 403, 0, + 620, 411, 370, 505, 405, 585, 436, 0, 613, 680, + 614, 525, 526, 741, 746, 742, 743, 745, 766, 495, + 425, 431, 542, 446, 468, 528, 584, 503, 533, 368, + 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, - 0, 0, 0, 0, 0, 0, 365, 269, 624, 751, - 626, 625, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 368, 0, 0, 0, 0, 0, 0, 4638, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4639, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 0, - 0, 0, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 0, 0, 565, 595, 387, 585, 0, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 611, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 0, 0, 748, 0, 578, 0, 0, - 0, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 596, 0, 529, 502, 789, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 386, 498, 709, 746, 747, 631, 0, - 695, 632, 642, 379, 667, 679, 678, 492, 591, 0, - 690, 693, 621, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 574, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 600, 683, 684, 486, 487, 488, 489, 407, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 722, 721, 720, 719, 718, 717, 716, 715, + 0, 0, 662, 385, 785, 779, 786, 767, 770, 769, + 744, 0, 341, 642, 466, 520, 402, 709, 710, 0, + 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, + 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, + 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 0, 0, 0, 0, 333, 771, 772, 773, + 774, 775, 0, 0, 334, 335, 336, 0, 0, 299, + 300, 327, 552, 328, 329, 330, 331, 0, 0, 591, + 592, 593, 616, 0, 594, 575, 641, 412, 342, 556, + 583, 782, 783, 0, 0, 0, 0, 0, 0, 0, + 692, 703, 739, 740, 0, 753, 754, 756, 758, 757, + 760, 549, 550, 768, 0, 0, 437, 358, 359, 496, + 497, 535, 0, 438, 439, 440, 444, 441, 442, 443, + 762, 763, 764, 761, 470, 534, 557, 543, 781, 483, + 0, 789, 631, 632, 790, 749, 748, 343, 0, 337, + 338, 706, 707, 0, 0, 537, 482, 638, 502, 0, + 0, 647, 681, 670, 759, 634, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 395, 0, 0, 465, + 685, 666, 677, 667, 508, 652, 653, 654, 661, 407, + 655, 791, 657, 626, 658, 627, 659, 660, 0, 684, + 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 268, 0, 0, 1870, + 0, 0, 0, 366, 269, 628, 755, 630, 629, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 369, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 546, + 574, 0, 588, 0, 434, 435, 1868, 0, 0, 0, + 0, 0, 0, 350, 553, 571, 367, 540, 586, 372, + 548, 564, 362, 501, 536, 0, 0, 352, 569, 547, + 479, 351, 0, 529, 392, 409, 389, 499, 0, 0, + 568, 599, 388, 589, 0, 579, 354, 0, 578, 498, + 471, 565, 570, 480, 473, 0, 353, 567, 478, 472, + 448, 399, 615, 449, 450, 451, 452, 453, 454, 413, + 514, 469, 515, 414, 486, 485, 487, 415, 416, 417, + 418, 419, 420, 421, 422, 423, 424, 0, 0, 0, + 0, 0, 610, 611, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 747, + 0, 0, 752, 0, 582, 0, 0, 0, 0, 0, + 0, 551, 0, 0, 455, 0, 0, 0, 600, 0, + 532, 504, 793, 0, 0, 530, 467, 566, 516, 572, + 554, 580, 523, 517, 344, 555, 391, 481, 363, 365, + 780, 393, 396, 400, 401, 492, 493, 510, 539, 558, + 559, 560, 390, 377, 531, 378, 410, 379, 345, 382, + 381, 383, 541, 384, 347, 511, 563, 0, 406, 527, + 476, 348, 475, 512, 562, 561, 364, 590, 597, 598, + 689, 0, 603, 794, 795, 796, 612, 0, 518, 360, + 357, 0, 0, 0, 386, 513, 373, 375, 376, 374, + 507, 509, 617, 618, 619, 621, 0, 622, 623, 0, + 0, 0, 0, 624, 690, 708, 674, 643, 605, 698, + 640, 644, 645, 427, 428, 429, 430, 711, 0, 0, + 0, 596, 456, 457, 0, 398, 397, 477, 349, 0, + 0, 445, 426, 519, 355, 394, 447, 432, 458, 459, + 460, 461, 462, 0, 463, 464, 404, 339, 340, 788, + 387, 500, 713, 750, 751, 635, 0, 699, 636, 646, + 380, 671, 683, 682, 494, 595, 0, 694, 697, 625, + 787, 0, 691, 705, 792, 704, 784, 506, 0, 538, + 702, 649, 0, 695, 668, 669, 0, 696, 664, 700, + 356, 433, 524, 581, 0, 637, 0, 606, 609, 639, + 726, 727, 728, 346, 608, 730, 731, 732, 733, 734, + 735, 736, 729, 577, 672, 648, 675, 587, 651, 650, + 0, 0, 686, 604, 687, 688, 488, 489, 490, 491, + 408, 714, 371, 607, 521, 522, 0, 673, 0, 0, + 0, 0, 0, 0, 0, 0, 678, 679, 676, 797, + 0, 737, 738, 0, 0, 601, 602, 403, 0, 620, + 411, 370, 505, 405, 585, 436, 0, 613, 680, 614, + 525, 526, 741, 746, 742, 743, 745, 766, 495, 425, + 431, 542, 446, 468, 528, 584, 503, 533, 368, 573, + 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 722, 721, 720, 719, 718, 717, 716, 715, 0, + 0, 662, 385, 785, 779, 786, 767, 770, 769, 744, + 0, 341, 642, 466, 520, 402, 709, 710, 0, 765, + 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, + 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, + 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, + 324, 0, 0, 0, 0, 333, 771, 772, 773, 774, + 775, 0, 0, 334, 335, 336, 0, 0, 299, 300, + 327, 552, 328, 329, 330, 331, 0, 0, 591, 592, + 593, 616, 0, 594, 575, 641, 412, 342, 556, 583, + 782, 783, 0, 0, 0, 0, 0, 0, 0, 692, + 703, 739, 740, 0, 753, 754, 756, 758, 757, 760, + 549, 550, 768, 0, 0, 437, 358, 359, 496, 497, + 535, 0, 438, 439, 440, 444, 441, 442, 443, 762, + 763, 764, 761, 470, 534, 557, 543, 781, 483, 0, + 789, 631, 632, 790, 749, 748, 343, 0, 337, 338, + 706, 707, 0, 0, 537, 482, 638, 502, 0, 0, + 647, 681, 670, 759, 634, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 395, 0, 0, 465, 685, + 666, 677, 667, 508, 652, 653, 654, 661, 407, 655, + 791, 657, 626, 658, 627, 659, 660, 0, 684, 633, + 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 268, 0, 0, 1870, 0, + 0, 0, 366, 269, 628, 755, 630, 629, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 369, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 546, 574, + 0, 588, 0, 434, 435, 2188, 0, 0, 0, 0, + 0, 0, 350, 553, 571, 367, 540, 586, 372, 548, + 564, 362, 501, 536, 0, 0, 352, 569, 547, 479, + 351, 0, 529, 392, 409, 389, 499, 0, 0, 568, + 599, 388, 589, 0, 579, 354, 0, 578, 498, 471, + 565, 570, 480, 473, 0, 353, 567, 478, 472, 448, + 399, 615, 449, 450, 451, 452, 453, 454, 413, 514, + 469, 515, 414, 486, 485, 487, 415, 416, 417, 418, + 419, 420, 421, 422, 423, 424, 0, 0, 0, 0, + 0, 610, 611, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 747, 0, + 0, 752, 0, 582, 0, 0, 0, 0, 0, 0, + 551, 0, 0, 455, 0, 0, 0, 600, 0, 532, + 504, 793, 0, 0, 530, 467, 566, 516, 572, 554, + 580, 523, 517, 344, 555, 391, 481, 363, 365, 780, + 393, 396, 400, 401, 492, 493, 510, 539, 558, 559, + 560, 390, 377, 531, 378, 410, 379, 345, 382, 381, + 383, 541, 384, 347, 511, 563, 0, 406, 527, 476, + 348, 475, 512, 562, 561, 364, 590, 597, 598, 689, + 0, 603, 794, 795, 796, 612, 0, 518, 360, 357, + 0, 0, 0, 386, 513, 373, 375, 376, 374, 507, + 509, 617, 618, 619, 621, 0, 622, 623, 0, 0, + 0, 0, 624, 690, 708, 674, 643, 605, 698, 640, + 644, 645, 427, 428, 429, 430, 711, 0, 0, 0, + 596, 456, 457, 0, 398, 397, 477, 349, 0, 0, + 445, 426, 519, 355, 394, 447, 432, 458, 459, 460, + 461, 462, 0, 463, 464, 404, 339, 340, 788, 387, + 500, 713, 750, 751, 635, 0, 699, 636, 646, 380, + 671, 683, 682, 494, 595, 0, 694, 697, 625, 787, + 0, 691, 705, 792, 704, 784, 506, 0, 538, 702, + 649, 0, 695, 668, 669, 0, 696, 664, 700, 356, + 433, 524, 581, 0, 637, 0, 606, 609, 639, 726, + 727, 728, 346, 608, 730, 731, 732, 733, 734, 735, + 736, 729, 577, 672, 648, 675, 587, 651, 650, 0, + 0, 686, 604, 687, 688, 488, 489, 490, 491, 408, + 714, 371, 607, 521, 522, 0, 673, 0, 0, 0, + 0, 0, 0, 0, 0, 678, 679, 676, 797, 0, + 737, 738, 0, 0, 601, 602, 403, 0, 620, 411, + 370, 505, 405, 585, 436, 0, 613, 680, 614, 525, + 526, 741, 746, 742, 743, 745, 766, 495, 425, 431, + 542, 446, 468, 528, 584, 503, 533, 368, 573, 544, + 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 0, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 284, + 722, 721, 720, 719, 718, 717, 716, 715, 0, 0, + 662, 385, 785, 779, 786, 767, 770, 769, 744, 0, + 341, 642, 466, 520, 402, 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, - 308, 309, 310, 708, 301, 302, 311, 312, 313, 314, + 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 0, 0, 0, 0, 333, 767, 768, 769, 770, 771, + 0, 0, 0, 0, 333, 771, 772, 773, 774, 775, 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, - 549, 328, 329, 330, 331, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 753, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 758, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 337, 338, 702, - 703, 0, 0, 534, 480, 634, 500, 0, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 2621, - 0, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 0, 680, 629, 542, - 482, 0, 697, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 268, 0, 0, 2622, 0, 0, - 0, 365, 269, 624, 751, 626, 625, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 0, 0, 0, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 0, 0, 565, 595, - 387, 585, 0, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 611, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 0, 0, - 748, 0, 578, 0, 0, 0, 0, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 596, 0, 529, 502, - 789, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 386, 498, - 709, 746, 747, 631, 0, 695, 632, 642, 379, 667, - 679, 678, 492, 591, 0, 690, 693, 621, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 574, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 600, 683, 684, - 486, 487, 488, 489, 407, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, - 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 0, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 284, 285, 286, 287, 288, 289, - 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, - 303, 304, 305, 306, 307, 308, 309, 310, 708, 301, - 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, - 767, 768, 769, 770, 771, 0, 0, 334, 335, 336, - 0, 0, 299, 300, 327, 549, 328, 329, 330, 331, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 753, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 758, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 744, - 343, 0, 337, 338, 702, 703, 0, 0, 534, 480, - 634, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 394, - 0, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 0, 680, 629, 542, 482, 0, 697, 0, 0, + 552, 328, 329, 330, 331, 0, 0, 591, 592, 593, + 616, 0, 594, 575, 641, 412, 342, 556, 583, 782, + 783, 0, 0, 0, 0, 0, 0, 0, 692, 703, + 739, 740, 0, 753, 754, 756, 758, 757, 760, 549, + 550, 768, 0, 0, 437, 358, 359, 496, 497, 535, + 0, 438, 439, 440, 444, 441, 442, 443, 762, 763, + 764, 761, 470, 534, 557, 543, 781, 483, 0, 789, + 631, 632, 790, 749, 748, 343, 0, 337, 338, 706, + 707, 0, 0, 537, 482, 638, 502, 0, 0, 647, + 681, 670, 759, 634, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 395, 0, 0, 465, 685, 666, + 677, 667, 508, 652, 653, 654, 661, 407, 655, 791, + 657, 626, 658, 627, 659, 660, 0, 684, 633, 545, + 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, - 0, 0, 4227, 4228, 0, 0, 365, 269, 624, 751, - 626, 625, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 0, - 0, 0, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 0, 0, 565, 595, 387, 585, 0, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 611, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 0, 0, 748, 0, 578, 0, 0, - 0, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 596, 0, 529, 502, 789, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 386, 498, 709, 746, 747, 631, 0, - 695, 632, 642, 379, 667, 679, 678, 492, 591, 0, - 690, 693, 621, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 574, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 600, 683, 684, 486, 487, 488, 489, 407, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, + 0, 0, 0, 0, 268, 0, 0, 0, 0, 0, + 0, 366, 269, 628, 755, 630, 629, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 369, 0, 0, 0, + 0, 0, 0, 4642, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4643, 0, 0, 0, 0, 546, 574, 0, + 588, 0, 434, 435, 0, 0, 0, 0, 0, 0, + 0, 350, 553, 571, 367, 540, 586, 372, 548, 564, + 362, 501, 536, 0, 0, 352, 569, 547, 479, 351, + 0, 529, 392, 409, 389, 499, 0, 0, 568, 599, + 388, 589, 0, 579, 354, 0, 578, 498, 471, 565, + 570, 480, 473, 0, 353, 567, 478, 472, 448, 399, + 615, 449, 450, 451, 452, 453, 454, 413, 514, 469, + 515, 414, 486, 485, 487, 415, 416, 417, 418, 419, + 420, 421, 422, 423, 424, 0, 0, 0, 0, 0, + 610, 611, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 747, 0, 0, + 752, 0, 582, 0, 0, 0, 0, 0, 0, 551, + 0, 0, 455, 0, 0, 0, 600, 0, 532, 504, + 793, 0, 0, 530, 467, 566, 516, 572, 554, 580, + 523, 517, 344, 555, 391, 481, 363, 365, 780, 393, + 396, 400, 401, 492, 493, 510, 539, 558, 559, 560, + 390, 377, 531, 378, 410, 379, 345, 382, 381, 383, + 541, 384, 347, 511, 563, 0, 406, 527, 476, 348, + 475, 512, 562, 561, 364, 590, 597, 598, 689, 0, + 603, 794, 795, 796, 612, 0, 518, 360, 357, 0, + 0, 0, 386, 513, 373, 375, 376, 374, 507, 509, + 617, 618, 619, 621, 0, 622, 623, 0, 0, 0, + 0, 624, 690, 708, 674, 643, 605, 698, 640, 644, + 645, 427, 428, 429, 430, 711, 0, 0, 0, 596, + 456, 457, 0, 398, 397, 477, 349, 0, 0, 445, + 426, 519, 355, 394, 447, 432, 458, 459, 460, 461, + 462, 0, 463, 464, 404, 339, 340, 788, 387, 500, + 713, 750, 751, 635, 0, 699, 636, 646, 380, 671, + 683, 682, 494, 595, 0, 694, 697, 625, 787, 0, + 691, 705, 792, 704, 784, 506, 0, 538, 702, 649, + 0, 695, 668, 669, 0, 696, 664, 700, 356, 433, + 524, 581, 0, 637, 0, 606, 609, 639, 726, 727, + 728, 346, 608, 730, 731, 732, 733, 734, 735, 736, + 729, 577, 672, 648, 675, 587, 651, 650, 0, 0, + 686, 604, 687, 688, 488, 489, 490, 491, 408, 714, + 371, 607, 521, 522, 0, 673, 0, 0, 0, 0, + 0, 0, 0, 0, 678, 679, 676, 797, 0, 737, + 738, 0, 0, 601, 602, 403, 0, 620, 411, 370, + 505, 405, 585, 436, 0, 613, 680, 614, 525, 526, + 741, 746, 742, 743, 745, 766, 495, 425, 431, 542, + 446, 468, 528, 584, 503, 533, 368, 573, 544, 474, + 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 722, + 721, 720, 719, 718, 717, 716, 715, 0, 0, 662, + 385, 785, 779, 786, 767, 770, 769, 744, 0, 341, + 642, 466, 520, 402, 709, 710, 0, 765, 284, 285, + 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, + 295, 296, 297, 298, 303, 304, 305, 306, 307, 308, + 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, + 0, 0, 0, 333, 771, 772, 773, 774, 775, 0, + 0, 334, 335, 336, 0, 0, 299, 300, 327, 552, + 328, 329, 330, 331, 0, 0, 591, 592, 593, 616, + 0, 594, 575, 641, 412, 342, 556, 583, 782, 783, + 0, 0, 0, 0, 0, 0, 0, 692, 703, 739, + 740, 0, 753, 754, 756, 758, 757, 760, 549, 550, + 768, 0, 0, 437, 358, 359, 496, 497, 535, 0, + 438, 439, 440, 444, 441, 442, 443, 762, 763, 764, + 761, 470, 534, 557, 543, 781, 483, 0, 789, 631, + 632, 790, 749, 748, 343, 0, 337, 338, 706, 707, + 0, 0, 537, 482, 638, 502, 0, 0, 647, 681, + 670, 759, 634, 0, 0, 0, 0, 0, 2625, 0, + 0, 0, 0, 395, 0, 0, 465, 685, 666, 677, + 667, 508, 652, 653, 654, 661, 407, 655, 791, 657, + 626, 658, 627, 659, 660, 0, 684, 633, 545, 484, + 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 268, 0, 0, 2626, 0, 0, 0, + 366, 269, 628, 755, 630, 629, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 369, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 546, 574, 0, 588, + 0, 434, 435, 0, 0, 0, 0, 0, 0, 0, + 350, 553, 571, 367, 540, 586, 372, 548, 564, 362, + 501, 536, 0, 0, 352, 569, 547, 479, 351, 0, + 529, 392, 409, 389, 499, 0, 0, 568, 599, 388, + 589, 0, 579, 354, 0, 578, 498, 471, 565, 570, + 480, 473, 0, 353, 567, 478, 472, 448, 399, 615, + 449, 450, 451, 452, 453, 454, 413, 514, 469, 515, + 414, 486, 485, 487, 415, 416, 417, 418, 419, 420, + 421, 422, 423, 424, 0, 0, 0, 0, 0, 610, + 611, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 747, 0, 0, 752, + 0, 582, 0, 0, 0, 0, 0, 0, 551, 0, + 0, 455, 0, 0, 0, 600, 0, 532, 504, 793, + 0, 0, 530, 467, 566, 516, 572, 554, 580, 523, + 517, 344, 555, 391, 481, 363, 365, 780, 393, 396, + 400, 401, 492, 493, 510, 539, 558, 559, 560, 390, + 377, 531, 378, 410, 379, 345, 382, 381, 383, 541, + 384, 347, 511, 563, 0, 406, 527, 476, 348, 475, + 512, 562, 561, 364, 590, 597, 598, 689, 0, 603, + 794, 795, 796, 612, 0, 518, 360, 357, 0, 0, + 0, 386, 513, 373, 375, 376, 374, 507, 509, 617, + 618, 619, 621, 0, 622, 623, 0, 0, 0, 0, + 624, 690, 708, 674, 643, 605, 698, 640, 644, 645, + 427, 428, 429, 430, 711, 0, 0, 0, 596, 456, + 457, 0, 398, 397, 477, 349, 0, 0, 445, 426, + 519, 355, 394, 447, 432, 458, 459, 460, 461, 462, + 0, 463, 464, 404, 339, 340, 788, 387, 500, 713, + 750, 751, 635, 0, 699, 636, 646, 380, 671, 683, + 682, 494, 595, 0, 694, 697, 625, 787, 0, 691, + 705, 792, 704, 784, 506, 0, 538, 702, 649, 0, + 695, 668, 669, 0, 696, 664, 700, 356, 433, 524, + 581, 0, 637, 0, 606, 609, 639, 726, 727, 728, + 346, 608, 730, 731, 732, 733, 734, 735, 736, 729, + 577, 672, 648, 675, 587, 651, 650, 0, 0, 686, + 604, 687, 688, 488, 489, 490, 491, 408, 714, 371, + 607, 521, 522, 0, 673, 0, 0, 0, 0, 0, + 0, 0, 0, 678, 679, 676, 797, 0, 737, 738, + 0, 0, 601, 602, 403, 0, 620, 411, 370, 505, + 405, 585, 436, 0, 613, 680, 614, 525, 526, 741, + 746, 742, 743, 745, 766, 495, 425, 431, 542, 446, + 468, 528, 584, 503, 533, 368, 573, 544, 474, 665, + 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 722, 721, + 720, 719, 718, 717, 716, 715, 0, 0, 662, 385, + 785, 779, 786, 767, 770, 769, 744, 0, 341, 642, + 466, 520, 402, 709, 710, 0, 765, 284, 285, 286, + 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, + 296, 297, 298, 303, 304, 305, 306, 307, 308, 309, + 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 0, 0, + 0, 0, 333, 771, 772, 773, 774, 775, 0, 0, + 334, 335, 336, 0, 0, 299, 300, 327, 552, 328, + 329, 330, 331, 0, 0, 591, 592, 593, 616, 0, + 594, 575, 641, 412, 342, 556, 583, 782, 783, 0, + 0, 0, 0, 0, 0, 0, 692, 703, 739, 740, + 0, 753, 754, 756, 758, 757, 760, 549, 550, 768, + 0, 0, 437, 358, 359, 496, 497, 535, 0, 438, + 439, 440, 444, 441, 442, 443, 762, 763, 764, 761, + 470, 534, 557, 543, 781, 483, 0, 789, 631, 632, + 790, 749, 748, 343, 0, 337, 338, 706, 707, 0, + 0, 537, 482, 638, 502, 0, 0, 647, 681, 670, + 759, 634, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 395, 0, 0, 465, 685, 666, 677, 667, + 508, 652, 653, 654, 661, 407, 655, 791, 657, 626, + 658, 627, 659, 660, 0, 684, 633, 545, 484, 0, + 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 268, 0, 0, 4231, 4232, 0, 0, 366, + 269, 628, 755, 630, 629, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 369, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 546, 574, 0, 588, 0, + 434, 435, 0, 0, 0, 0, 0, 0, 0, 350, + 553, 571, 367, 540, 586, 372, 548, 564, 362, 501, + 536, 0, 0, 352, 569, 547, 479, 351, 0, 529, + 392, 409, 389, 499, 0, 0, 568, 599, 388, 589, + 0, 579, 354, 0, 578, 498, 471, 565, 570, 480, + 473, 0, 353, 567, 478, 472, 448, 399, 615, 449, + 450, 451, 452, 453, 454, 413, 514, 469, 515, 414, + 486, 485, 487, 415, 416, 417, 418, 419, 420, 421, + 422, 423, 424, 0, 0, 0, 0, 0, 610, 611, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 747, 0, 0, 752, 0, + 582, 0, 0, 0, 0, 0, 0, 551, 0, 0, + 455, 0, 0, 0, 600, 0, 532, 504, 793, 0, + 0, 530, 467, 566, 516, 572, 554, 580, 523, 517, + 344, 555, 391, 481, 363, 365, 780, 393, 396, 400, + 401, 492, 493, 510, 539, 558, 559, 560, 390, 377, + 531, 378, 410, 379, 345, 382, 381, 383, 541, 384, + 347, 511, 563, 0, 406, 527, 476, 348, 475, 512, + 562, 561, 364, 590, 597, 598, 689, 0, 603, 794, + 795, 796, 612, 0, 518, 360, 357, 0, 0, 0, + 386, 513, 373, 375, 376, 374, 507, 509, 617, 618, + 619, 621, 0, 622, 623, 0, 0, 0, 0, 624, + 690, 708, 674, 643, 605, 698, 640, 644, 645, 427, + 428, 429, 430, 711, 0, 0, 0, 596, 456, 457, + 0, 398, 397, 477, 349, 0, 0, 445, 426, 519, + 355, 394, 447, 432, 458, 459, 460, 461, 462, 0, + 463, 464, 404, 339, 340, 788, 387, 500, 713, 750, + 751, 635, 0, 699, 636, 646, 380, 671, 683, 682, + 494, 595, 0, 694, 697, 625, 787, 0, 691, 705, + 792, 704, 784, 506, 0, 538, 702, 649, 0, 695, + 668, 669, 0, 696, 664, 700, 356, 433, 524, 581, + 0, 637, 0, 606, 609, 639, 726, 727, 728, 346, + 608, 730, 731, 732, 733, 734, 735, 736, 729, 577, + 672, 648, 675, 587, 651, 650, 0, 0, 686, 604, + 687, 688, 488, 489, 490, 491, 408, 714, 371, 607, + 521, 522, 0, 673, 0, 0, 0, 0, 0, 0, + 0, 0, 678, 679, 676, 797, 0, 737, 738, 0, + 0, 601, 602, 403, 0, 620, 411, 370, 505, 405, + 585, 436, 0, 613, 680, 614, 525, 526, 741, 746, + 742, 743, 745, 766, 495, 425, 431, 542, 446, 468, + 528, 584, 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 0, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 284, - 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, - 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, - 308, 309, 310, 708, 301, 302, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 0, 0, 0, 0, 333, 767, 768, 769, 770, 771, - 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, - 549, 328, 329, 330, 331, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 753, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 758, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 337, 338, 702, - 703, 0, 0, 534, 480, 634, 500, 0, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 0, 680, 629, 542, - 482, 0, 697, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 268, 0, 0, 3992, 3994, 0, - 0, 365, 269, 624, 751, 626, 625, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 0, 0, 0, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 0, 0, 565, 595, - 387, 585, 0, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 611, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 0, 0, - 748, 0, 578, 0, 0, 0, 0, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 596, 0, 529, 502, - 789, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 386, 498, - 709, 746, 747, 631, 0, 695, 632, 642, 379, 667, - 679, 678, 492, 591, 0, 690, 693, 621, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 574, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 600, 683, 684, - 486, 487, 488, 489, 407, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, - 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 0, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 284, 285, 286, 287, 288, 289, - 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, - 303, 304, 305, 306, 307, 308, 309, 310, 708, 301, - 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, - 767, 768, 769, 770, 771, 0, 0, 334, 335, 336, - 0, 0, 299, 300, 327, 549, 328, 329, 330, 331, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 753, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 758, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 744, - 343, 0, 337, 338, 702, 703, 0, 0, 534, 480, - 634, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 394, - 0, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 0, 680, 629, 542, 482, 0, 697, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3622, 0, 0, 268, - 0, 0, 3626, 0, 0, 0, 365, 269, 624, 751, - 626, 625, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 0, - 0, 0, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 0, 0, 565, 595, 387, 585, 0, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 611, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 0, 0, 748, 0, 578, 0, 0, - 0, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 596, 0, 529, 502, 789, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 386, 498, 709, 746, 747, 631, 0, - 695, 632, 642, 379, 667, 679, 678, 492, 591, 0, - 690, 693, 621, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 574, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 600, 683, 684, 486, 487, 488, 489, 407, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, + 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 722, 721, 720, + 719, 718, 717, 716, 715, 0, 0, 662, 385, 785, + 779, 786, 767, 770, 769, 744, 0, 341, 642, 466, + 520, 402, 709, 710, 0, 765, 284, 285, 286, 287, + 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, + 297, 298, 303, 304, 305, 306, 307, 308, 309, 310, + 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 0, 0, 0, + 0, 333, 771, 772, 773, 774, 775, 0, 0, 334, + 335, 336, 0, 0, 299, 300, 327, 552, 328, 329, + 330, 331, 0, 0, 591, 592, 593, 616, 0, 594, + 575, 641, 412, 342, 556, 583, 782, 783, 0, 0, + 0, 0, 0, 0, 0, 692, 703, 739, 740, 0, + 753, 754, 756, 758, 757, 760, 549, 550, 768, 0, + 0, 437, 358, 359, 496, 497, 535, 0, 438, 439, + 440, 444, 441, 442, 443, 762, 763, 764, 761, 470, + 534, 557, 543, 781, 483, 0, 789, 631, 632, 790, + 749, 748, 343, 0, 337, 338, 706, 707, 0, 0, + 537, 482, 638, 502, 0, 0, 647, 681, 670, 759, + 634, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 395, 0, 0, 465, 685, 666, 677, 667, 508, + 652, 653, 654, 661, 407, 655, 791, 657, 626, 658, + 627, 659, 660, 0, 684, 633, 545, 484, 0, 701, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 268, 0, 0, 3996, 3998, 0, 0, 366, 269, + 628, 755, 630, 629, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 369, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 546, 574, 0, 588, 0, 434, + 435, 0, 0, 0, 0, 0, 0, 0, 350, 553, + 571, 367, 540, 586, 372, 548, 564, 362, 501, 536, + 0, 0, 352, 569, 547, 479, 351, 0, 529, 392, + 409, 389, 499, 0, 0, 568, 599, 388, 589, 0, + 579, 354, 0, 578, 498, 471, 565, 570, 480, 473, + 0, 353, 567, 478, 472, 448, 399, 615, 449, 450, + 451, 452, 453, 454, 413, 514, 469, 515, 414, 486, + 485, 487, 415, 416, 417, 418, 419, 420, 421, 422, + 423, 424, 0, 0, 0, 0, 0, 610, 611, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 747, 0, 0, 752, 0, 582, + 0, 0, 0, 0, 0, 0, 551, 0, 0, 455, + 0, 0, 0, 600, 0, 532, 504, 793, 0, 0, + 530, 467, 566, 516, 572, 554, 580, 523, 517, 344, + 555, 391, 481, 363, 365, 780, 393, 396, 400, 401, + 492, 493, 510, 539, 558, 559, 560, 390, 377, 531, + 378, 410, 379, 345, 382, 381, 383, 541, 384, 347, + 511, 563, 0, 406, 527, 476, 348, 475, 512, 562, + 561, 364, 590, 597, 598, 689, 0, 603, 794, 795, + 796, 612, 0, 518, 360, 357, 0, 0, 0, 386, + 513, 373, 375, 376, 374, 507, 509, 617, 618, 619, + 621, 0, 622, 623, 0, 0, 0, 0, 624, 690, + 708, 674, 643, 605, 698, 640, 644, 645, 427, 428, + 429, 430, 711, 0, 0, 0, 596, 456, 457, 0, + 398, 397, 477, 349, 0, 0, 445, 426, 519, 355, + 394, 447, 432, 458, 459, 460, 461, 462, 0, 463, + 464, 404, 339, 340, 788, 387, 500, 713, 750, 751, + 635, 0, 699, 636, 646, 380, 671, 683, 682, 494, + 595, 0, 694, 697, 625, 787, 0, 691, 705, 792, + 704, 784, 506, 0, 538, 702, 649, 0, 695, 668, + 669, 0, 696, 664, 700, 356, 433, 524, 581, 0, + 637, 0, 606, 609, 639, 726, 727, 728, 346, 608, + 730, 731, 732, 733, 734, 735, 736, 729, 577, 672, + 648, 675, 587, 651, 650, 0, 0, 686, 604, 687, + 688, 488, 489, 490, 491, 408, 714, 371, 607, 521, + 522, 0, 673, 0, 0, 0, 0, 0, 0, 0, + 0, 678, 679, 676, 797, 0, 737, 738, 0, 0, + 601, 602, 403, 0, 620, 411, 370, 505, 405, 585, + 436, 0, 613, 680, 614, 525, 526, 741, 746, 742, + 743, 745, 766, 495, 425, 431, 542, 446, 468, 528, + 584, 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 0, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 284, - 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, - 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, - 308, 309, 310, 708, 301, 302, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 0, 0, 0, 0, 333, 767, 768, 769, 770, 771, - 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, - 549, 328, 329, 330, 331, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 753, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 758, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 337, 338, 702, - 703, 0, 0, 534, 480, 634, 500, 0, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 0, 680, 629, 542, - 482, 0, 697, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3616, 0, 0, 268, 0, 0, 3620, 0, 0, - 0, 365, 269, 624, 751, 626, 625, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 0, 0, 0, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 0, 0, 565, 595, - 387, 585, 0, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 611, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 0, 0, - 748, 0, 578, 0, 0, 0, 0, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 596, 0, 529, 502, - 789, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 386, 498, - 709, 746, 747, 631, 0, 695, 632, 642, 379, 667, - 679, 678, 492, 591, 0, 690, 693, 621, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 574, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 600, 683, 684, - 486, 487, 488, 489, 407, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 0, 0, + 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 722, 721, 720, 719, + 718, 717, 716, 715, 0, 0, 662, 385, 785, 779, + 786, 767, 770, 769, 744, 0, 341, 642, 466, 520, + 402, 709, 710, 0, 765, 284, 285, 286, 287, 288, + 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, + 298, 303, 304, 305, 306, 307, 308, 309, 310, 712, + 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, + 333, 771, 772, 773, 774, 775, 0, 0, 334, 335, + 336, 0, 0, 299, 300, 327, 552, 328, 329, 330, + 331, 0, 0, 591, 592, 593, 616, 0, 594, 575, + 641, 412, 342, 556, 583, 782, 783, 0, 0, 0, + 0, 0, 0, 0, 692, 703, 739, 740, 0, 753, + 754, 756, 758, 757, 760, 549, 550, 768, 0, 0, + 437, 358, 359, 496, 497, 535, 0, 438, 439, 440, + 444, 441, 442, 443, 762, 763, 764, 761, 470, 534, + 557, 543, 781, 483, 0, 789, 631, 632, 790, 749, + 748, 343, 0, 337, 338, 706, 707, 0, 0, 537, + 482, 638, 502, 0, 0, 647, 681, 670, 759, 634, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 395, 0, 0, 465, 685, 666, 677, 667, 508, 652, + 653, 654, 661, 407, 655, 791, 657, 626, 658, 627, + 659, 660, 0, 684, 633, 545, 484, 0, 701, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3626, 0, 0, + 268, 0, 0, 3630, 0, 0, 0, 366, 269, 628, + 755, 630, 629, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 369, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 546, 574, 0, 588, 0, 434, 435, + 0, 0, 0, 0, 0, 0, 0, 350, 553, 571, + 367, 540, 586, 372, 548, 564, 362, 501, 536, 0, + 0, 352, 569, 547, 479, 351, 0, 529, 392, 409, + 389, 499, 0, 0, 568, 599, 388, 589, 0, 579, + 354, 0, 578, 498, 471, 565, 570, 480, 473, 0, + 353, 567, 478, 472, 448, 399, 615, 449, 450, 451, + 452, 453, 454, 413, 514, 469, 515, 414, 486, 485, + 487, 415, 416, 417, 418, 419, 420, 421, 422, 423, + 424, 0, 0, 0, 0, 0, 610, 611, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 747, 0, 0, 752, 0, 582, 0, + 0, 0, 0, 0, 0, 551, 0, 0, 455, 0, + 0, 0, 600, 0, 532, 504, 793, 0, 0, 530, + 467, 566, 516, 572, 554, 580, 523, 517, 344, 555, + 391, 481, 363, 365, 780, 393, 396, 400, 401, 492, + 493, 510, 539, 558, 559, 560, 390, 377, 531, 378, + 410, 379, 345, 382, 381, 383, 541, 384, 347, 511, + 563, 0, 406, 527, 476, 348, 475, 512, 562, 561, + 364, 590, 597, 598, 689, 0, 603, 794, 795, 796, + 612, 0, 518, 360, 357, 0, 0, 0, 386, 513, + 373, 375, 376, 374, 507, 509, 617, 618, 619, 621, + 0, 622, 623, 0, 0, 0, 0, 624, 690, 708, + 674, 643, 605, 698, 640, 644, 645, 427, 428, 429, + 430, 711, 0, 0, 0, 596, 456, 457, 0, 398, + 397, 477, 349, 0, 0, 445, 426, 519, 355, 394, + 447, 432, 458, 459, 460, 461, 462, 0, 463, 464, + 404, 339, 340, 788, 387, 500, 713, 750, 751, 635, + 0, 699, 636, 646, 380, 671, 683, 682, 494, 595, + 0, 694, 697, 625, 787, 0, 691, 705, 792, 704, + 784, 506, 0, 538, 702, 649, 0, 695, 668, 669, + 0, 696, 664, 700, 356, 433, 524, 581, 0, 637, + 0, 606, 609, 639, 726, 727, 728, 346, 608, 730, + 731, 732, 733, 734, 735, 736, 729, 577, 672, 648, + 675, 587, 651, 650, 0, 0, 686, 604, 687, 688, + 488, 489, 490, 491, 408, 714, 371, 607, 521, 522, + 0, 673, 0, 0, 0, 0, 0, 0, 0, 0, + 678, 679, 676, 797, 0, 737, 738, 0, 0, 601, + 602, 403, 0, 620, 411, 370, 505, 405, 585, 436, + 0, 613, 680, 614, 525, 526, 741, 746, 742, 743, + 745, 766, 495, 425, 431, 542, 446, 468, 528, 584, + 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 0, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 284, 285, 286, 287, 288, 289, + 0, 0, 0, 0, 0, 722, 721, 720, 719, 718, + 717, 716, 715, 0, 0, 662, 385, 785, 779, 786, + 767, 770, 769, 744, 0, 341, 642, 466, 520, 402, + 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, - 303, 304, 305, 306, 307, 308, 309, 310, 708, 301, + 303, 304, 305, 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, - 767, 768, 769, 770, 771, 0, 0, 334, 335, 336, - 0, 0, 299, 300, 327, 549, 328, 329, 330, 331, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 753, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 758, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 744, - 343, 0, 337, 338, 702, 703, 0, 0, 534, 480, - 634, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 394, - 3150, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 0, 680, 629, 542, 482, 0, 697, 0, 0, + 771, 772, 773, 774, 775, 0, 0, 334, 335, 336, + 0, 0, 299, 300, 327, 552, 328, 329, 330, 331, + 0, 0, 591, 592, 593, 616, 0, 594, 575, 641, + 412, 342, 556, 583, 782, 783, 0, 0, 0, 0, + 0, 0, 0, 692, 703, 739, 740, 0, 753, 754, + 756, 758, 757, 760, 549, 550, 768, 0, 0, 437, + 358, 359, 496, 497, 535, 0, 438, 439, 440, 444, + 441, 442, 443, 762, 763, 764, 761, 470, 534, 557, + 543, 781, 483, 0, 789, 631, 632, 790, 749, 748, + 343, 0, 337, 338, 706, 707, 0, 0, 537, 482, + 638, 502, 0, 0, 647, 681, 670, 759, 634, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 395, + 0, 0, 465, 685, 666, 677, 667, 508, 652, 653, + 654, 661, 407, 655, 791, 657, 626, 658, 627, 659, + 660, 0, 684, 633, 545, 484, 0, 701, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3620, 0, 0, 268, + 0, 0, 3624, 0, 0, 0, 366, 269, 628, 755, + 630, 629, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 369, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 546, 574, 0, 588, 0, 434, 435, 0, + 0, 0, 0, 0, 0, 0, 350, 553, 571, 367, + 540, 586, 372, 548, 564, 362, 501, 536, 0, 0, + 352, 569, 547, 479, 351, 0, 529, 392, 409, 389, + 499, 0, 0, 568, 599, 388, 589, 0, 579, 354, + 0, 578, 498, 471, 565, 570, 480, 473, 0, 353, + 567, 478, 472, 448, 399, 615, 449, 450, 451, 452, + 453, 454, 413, 514, 469, 515, 414, 486, 485, 487, + 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, + 0, 0, 0, 0, 0, 610, 611, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 747, 0, 0, 752, 0, 582, 0, 0, + 0, 0, 0, 0, 551, 0, 0, 455, 0, 0, + 0, 600, 0, 532, 504, 793, 0, 0, 530, 467, + 566, 516, 572, 554, 580, 523, 517, 344, 555, 391, + 481, 363, 365, 780, 393, 396, 400, 401, 492, 493, + 510, 539, 558, 559, 560, 390, 377, 531, 378, 410, + 379, 345, 382, 381, 383, 541, 384, 347, 511, 563, + 0, 406, 527, 476, 348, 475, 512, 562, 561, 364, + 590, 597, 598, 689, 0, 603, 794, 795, 796, 612, + 0, 518, 360, 357, 0, 0, 0, 386, 513, 373, + 375, 376, 374, 507, 509, 617, 618, 619, 621, 0, + 622, 623, 0, 0, 0, 0, 624, 690, 708, 674, + 643, 605, 698, 640, 644, 645, 427, 428, 429, 430, + 711, 0, 0, 0, 596, 456, 457, 0, 398, 397, + 477, 349, 0, 0, 445, 426, 519, 355, 394, 447, + 432, 458, 459, 460, 461, 462, 0, 463, 464, 404, + 339, 340, 788, 387, 500, 713, 750, 751, 635, 0, + 699, 636, 646, 380, 671, 683, 682, 494, 595, 0, + 694, 697, 625, 787, 0, 691, 705, 792, 704, 784, + 506, 0, 538, 702, 649, 0, 695, 668, 669, 0, + 696, 664, 700, 356, 433, 524, 581, 0, 637, 0, + 606, 609, 639, 726, 727, 728, 346, 608, 730, 731, + 732, 733, 734, 735, 736, 729, 577, 672, 648, 675, + 587, 651, 650, 0, 0, 686, 604, 687, 688, 488, + 489, 490, 491, 408, 714, 371, 607, 521, 522, 0, + 673, 0, 0, 0, 0, 0, 0, 0, 0, 678, + 679, 676, 797, 0, 737, 738, 0, 0, 601, 602, + 403, 0, 620, 411, 370, 505, 405, 585, 436, 0, + 613, 680, 614, 525, 526, 741, 746, 742, 743, 745, + 766, 495, 425, 431, 542, 446, 468, 528, 584, 503, + 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, - 0, 0, 1866, 0, 0, 0, 365, 269, 624, 751, - 626, 625, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 0, - 0, 0, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 0, 0, 565, 595, 387, 585, 0, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 611, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 0, 0, 748, 0, 578, 0, 0, - 0, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 596, 0, 529, 502, 789, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 386, 498, 709, 746, 747, 631, 0, - 695, 632, 642, 379, 667, 679, 678, 492, 591, 0, - 690, 693, 621, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 574, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 600, 683, 684, 486, 487, 488, 489, 407, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, + 0, 0, 0, 0, 722, 721, 720, 719, 718, 717, + 716, 715, 0, 0, 662, 385, 785, 779, 786, 767, + 770, 769, 744, 0, 341, 642, 466, 520, 402, 709, + 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, + 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, + 304, 305, 306, 307, 308, 309, 310, 712, 301, 302, + 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 0, 0, 0, 0, 333, 771, + 772, 773, 774, 775, 0, 0, 334, 335, 336, 0, + 0, 299, 300, 327, 552, 328, 329, 330, 331, 0, + 0, 591, 592, 593, 616, 0, 594, 575, 641, 412, + 342, 556, 583, 782, 783, 0, 0, 0, 0, 0, + 0, 0, 692, 703, 739, 740, 0, 753, 754, 756, + 758, 757, 760, 549, 550, 768, 0, 0, 437, 358, + 359, 496, 497, 535, 0, 438, 439, 440, 444, 441, + 442, 443, 762, 763, 764, 761, 470, 534, 557, 543, + 781, 483, 0, 789, 631, 632, 790, 749, 748, 343, + 0, 337, 338, 706, 707, 0, 0, 537, 482, 638, + 502, 0, 0, 647, 681, 670, 759, 634, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 395, 3154, + 0, 465, 685, 666, 677, 667, 508, 652, 653, 654, + 661, 407, 655, 791, 657, 626, 658, 627, 659, 660, + 0, 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 0, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 284, - 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, - 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, - 308, 309, 310, 708, 301, 302, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 0, 0, 0, 0, 333, 767, 768, 769, 770, 771, - 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, - 549, 328, 329, 330, 331, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 753, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 758, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 337, 338, 702, - 703, 0, 0, 534, 480, 634, 500, 0, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 0, 680, 629, 542, - 482, 0, 697, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 268, 0, 0, 5305, 0, 0, - 0, 365, 269, 624, 751, 626, 625, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 0, 0, 0, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 0, 0, 565, 595, - 387, 585, 0, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 611, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 0, 0, - 748, 0, 578, 0, 0, 0, 0, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 596, 0, 529, 502, - 789, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 386, 498, - 709, 746, 747, 631, 0, 695, 632, 642, 379, 667, - 679, 678, 492, 591, 0, 690, 693, 621, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 574, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 600, 683, 684, - 486, 487, 488, 489, 407, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, - 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 0, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 284, 285, 286, 287, 288, 289, - 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, - 303, 304, 305, 306, 307, 308, 309, 310, 708, 301, - 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, - 767, 768, 769, 770, 771, 0, 0, 334, 335, 336, - 0, 0, 299, 300, 327, 549, 328, 329, 330, 331, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 753, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 758, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 744, - 343, 0, 337, 338, 702, 703, 0, 0, 534, 480, - 634, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 394, - 0, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 0, 680, 629, 542, 482, 0, 697, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 268, 0, + 0, 1870, 0, 0, 0, 366, 269, 628, 755, 630, + 629, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 369, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 546, 574, 0, 588, 0, 434, 435, 0, 0, + 0, 0, 0, 0, 0, 350, 553, 571, 367, 540, + 586, 372, 548, 564, 362, 501, 536, 0, 0, 352, + 569, 547, 479, 351, 0, 529, 392, 409, 389, 499, + 0, 0, 568, 599, 388, 589, 0, 579, 354, 0, + 578, 498, 471, 565, 570, 480, 473, 0, 353, 567, + 478, 472, 448, 399, 615, 449, 450, 451, 452, 453, + 454, 413, 514, 469, 515, 414, 486, 485, 487, 415, + 416, 417, 418, 419, 420, 421, 422, 423, 424, 0, + 0, 0, 0, 0, 610, 611, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 747, 0, 0, 752, 0, 582, 0, 0, 0, + 0, 0, 0, 551, 0, 0, 455, 0, 0, 0, + 600, 0, 532, 504, 793, 0, 0, 530, 467, 566, + 516, 572, 554, 580, 523, 517, 344, 555, 391, 481, + 363, 365, 780, 393, 396, 400, 401, 492, 493, 510, + 539, 558, 559, 560, 390, 377, 531, 378, 410, 379, + 345, 382, 381, 383, 541, 384, 347, 511, 563, 0, + 406, 527, 476, 348, 475, 512, 562, 561, 364, 590, + 597, 598, 689, 0, 603, 794, 795, 796, 612, 0, + 518, 360, 357, 0, 0, 0, 386, 513, 373, 375, + 376, 374, 507, 509, 617, 618, 619, 621, 0, 622, + 623, 0, 0, 0, 0, 624, 690, 708, 674, 643, + 605, 698, 640, 644, 645, 427, 428, 429, 430, 711, + 0, 0, 0, 596, 456, 457, 0, 398, 397, 477, + 349, 0, 0, 445, 426, 519, 355, 394, 447, 432, + 458, 459, 460, 461, 462, 0, 463, 464, 404, 339, + 340, 788, 387, 500, 713, 750, 751, 635, 0, 699, + 636, 646, 380, 671, 683, 682, 494, 595, 0, 694, + 697, 625, 787, 0, 691, 705, 792, 704, 784, 506, + 0, 538, 702, 649, 0, 695, 668, 669, 0, 696, + 664, 700, 356, 433, 524, 581, 0, 637, 0, 606, + 609, 639, 726, 727, 728, 346, 608, 730, 731, 732, + 733, 734, 735, 736, 729, 577, 672, 648, 675, 587, + 651, 650, 0, 0, 686, 604, 687, 688, 488, 489, + 490, 491, 408, 714, 371, 607, 521, 522, 0, 673, + 0, 0, 0, 0, 0, 0, 0, 0, 678, 679, + 676, 797, 0, 737, 738, 0, 0, 601, 602, 403, + 0, 620, 411, 370, 505, 405, 585, 436, 0, 613, + 680, 614, 525, 526, 741, 746, 742, 743, 745, 766, + 495, 425, 431, 542, 446, 468, 528, 584, 503, 533, + 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, - 0, 0, 5247, 0, 0, 0, 365, 269, 624, 751, - 626, 625, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 0, - 0, 0, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 0, 0, 565, 595, 387, 585, 0, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 611, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 0, 0, 748, 0, 578, 0, 0, - 0, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 596, 0, 529, 502, 789, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 386, 498, 709, 746, 747, 631, 0, - 695, 632, 642, 379, 667, 679, 678, 492, 591, 0, - 690, 693, 621, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 574, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 600, 683, 684, 486, 487, 488, 489, 407, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, + 0, 0, 0, 722, 721, 720, 719, 718, 717, 716, + 715, 0, 0, 662, 385, 785, 779, 786, 767, 770, + 769, 744, 0, 341, 642, 466, 520, 402, 709, 710, + 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, + 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, + 305, 306, 307, 308, 309, 310, 712, 301, 302, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 0, 0, 0, 0, 333, 771, 772, + 773, 774, 775, 0, 0, 334, 335, 336, 0, 0, + 299, 300, 327, 552, 328, 329, 330, 331, 0, 0, + 591, 592, 593, 616, 0, 594, 575, 641, 412, 342, + 556, 583, 782, 783, 0, 0, 0, 0, 0, 0, + 0, 692, 703, 739, 740, 0, 753, 754, 756, 758, + 757, 760, 549, 550, 768, 0, 0, 437, 358, 359, + 496, 497, 535, 0, 438, 439, 440, 444, 441, 442, + 443, 762, 763, 764, 761, 470, 534, 557, 543, 781, + 483, 0, 789, 631, 632, 790, 749, 748, 343, 0, + 337, 338, 706, 707, 0, 0, 537, 482, 638, 502, + 0, 0, 647, 681, 670, 759, 634, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 395, 0, 0, + 465, 685, 666, 677, 667, 508, 652, 653, 654, 661, + 407, 655, 791, 657, 626, 658, 627, 659, 660, 0, + 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 268, 0, 0, + 5320, 0, 0, 0, 366, 269, 628, 755, 630, 629, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 369, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 546, 574, 0, 588, 0, 434, 435, 0, 0, 0, + 0, 0, 0, 0, 350, 553, 571, 367, 540, 586, + 372, 548, 564, 362, 501, 536, 0, 0, 352, 569, + 547, 479, 351, 0, 529, 392, 409, 389, 499, 0, + 0, 568, 599, 388, 589, 0, 579, 354, 0, 578, + 498, 471, 565, 570, 480, 473, 0, 353, 567, 478, + 472, 448, 399, 615, 449, 450, 451, 452, 453, 454, + 413, 514, 469, 515, 414, 486, 485, 487, 415, 416, + 417, 418, 419, 420, 421, 422, 423, 424, 0, 0, + 0, 0, 0, 610, 611, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 747, 0, 0, 752, 0, 582, 0, 0, 0, 0, + 0, 0, 551, 0, 0, 455, 0, 0, 0, 600, + 0, 532, 504, 793, 0, 0, 530, 467, 566, 516, + 572, 554, 580, 523, 517, 344, 555, 391, 481, 363, + 365, 780, 393, 396, 400, 401, 492, 493, 510, 539, + 558, 559, 560, 390, 377, 531, 378, 410, 379, 345, + 382, 381, 383, 541, 384, 347, 511, 563, 0, 406, + 527, 476, 348, 475, 512, 562, 561, 364, 590, 597, + 598, 689, 0, 603, 794, 795, 796, 612, 0, 518, + 360, 357, 0, 0, 0, 386, 513, 373, 375, 376, + 374, 507, 509, 617, 618, 619, 621, 0, 622, 623, + 0, 0, 0, 0, 624, 690, 708, 674, 643, 605, + 698, 640, 644, 645, 427, 428, 429, 430, 711, 0, + 0, 0, 596, 456, 457, 0, 398, 397, 477, 349, + 0, 0, 445, 426, 519, 355, 394, 447, 432, 458, + 459, 460, 461, 462, 0, 463, 464, 404, 339, 340, + 788, 387, 500, 713, 750, 751, 635, 0, 699, 636, + 646, 380, 671, 683, 682, 494, 595, 0, 694, 697, + 625, 787, 0, 691, 705, 792, 704, 784, 506, 0, + 538, 702, 649, 0, 695, 668, 669, 0, 696, 664, + 700, 356, 433, 524, 581, 0, 637, 0, 606, 609, + 639, 726, 727, 728, 346, 608, 730, 731, 732, 733, + 734, 735, 736, 729, 577, 672, 648, 675, 587, 651, + 650, 0, 0, 686, 604, 687, 688, 488, 489, 490, + 491, 408, 714, 371, 607, 521, 522, 0, 673, 0, + 0, 0, 0, 0, 0, 0, 0, 678, 679, 676, + 797, 0, 737, 738, 0, 0, 601, 602, 403, 0, + 620, 411, 370, 505, 405, 585, 436, 0, 613, 680, + 614, 525, 526, 741, 746, 742, 743, 745, 766, 495, + 425, 431, 542, 446, 468, 528, 584, 503, 533, 368, + 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 0, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 284, - 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, - 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, - 308, 309, 310, 708, 301, 302, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 0, 0, 0, 0, 333, 767, 768, 769, 770, 771, - 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, - 549, 328, 329, 330, 331, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 753, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 758, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 337, 338, 702, - 703, 0, 0, 534, 480, 634, 500, 0, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 0, 680, 629, 542, - 482, 0, 697, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 268, 1069, 0, 0, 0, 0, - 0, 365, 269, 624, 751, 626, 625, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 0, 0, 0, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 0, 0, 565, 595, - 387, 585, 0, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 611, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 0, 0, - 748, 0, 578, 0, 0, 0, 0, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 596, 0, 529, 502, - 789, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 386, 498, - 709, 746, 747, 631, 0, 695, 632, 642, 379, 667, - 679, 678, 492, 591, 0, 690, 693, 621, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 574, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 600, 683, 684, - 486, 487, 488, 489, 407, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, - 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 0, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 284, 285, 286, 287, 288, 289, - 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, - 303, 304, 305, 306, 307, 308, 309, 310, 708, 301, - 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, - 767, 768, 769, 770, 771, 0, 0, 334, 335, 336, - 0, 0, 299, 300, 327, 549, 328, 329, 330, 331, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 753, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 758, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 744, - 343, 0, 337, 338, 702, 703, 0, 0, 534, 480, - 634, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 394, - 0, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 0, 680, 629, 542, 482, 0, 697, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 5194, 0, 0, 268, - 0, 0, 0, 0, 0, 0, 365, 269, 624, 751, - 626, 625, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 0, - 0, 0, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 0, 0, 565, 595, 387, 585, 0, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 611, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 0, 0, 748, 0, 578, 0, 0, - 0, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 596, 0, 529, 502, 789, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 386, 498, 709, 746, 747, 631, 0, - 695, 632, 642, 379, 667, 679, 678, 492, 591, 0, - 690, 693, 621, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 574, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 600, 683, 684, 486, 487, 488, 489, 407, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, + 0, 0, 722, 721, 720, 719, 718, 717, 716, 715, + 0, 0, 662, 385, 785, 779, 786, 767, 770, 769, + 744, 0, 341, 642, 466, 520, 402, 709, 710, 0, + 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, + 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, + 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 0, 0, 0, 0, 333, 771, 772, 773, + 774, 775, 0, 0, 334, 335, 336, 0, 0, 299, + 300, 327, 552, 328, 329, 330, 331, 0, 0, 591, + 592, 593, 616, 0, 594, 575, 641, 412, 342, 556, + 583, 782, 783, 0, 0, 0, 0, 0, 0, 0, + 692, 703, 739, 740, 0, 753, 754, 756, 758, 757, + 760, 549, 550, 768, 0, 0, 437, 358, 359, 496, + 497, 535, 0, 438, 439, 440, 444, 441, 442, 443, + 762, 763, 764, 761, 470, 534, 557, 543, 781, 483, + 0, 789, 631, 632, 790, 749, 748, 343, 0, 337, + 338, 706, 707, 0, 0, 537, 482, 638, 502, 0, + 0, 647, 681, 670, 759, 634, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 395, 0, 0, 465, + 685, 666, 677, 667, 508, 652, 653, 654, 661, 407, + 655, 791, 657, 626, 658, 627, 659, 660, 0, 684, + 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 268, 0, 0, 5251, + 0, 0, 0, 366, 269, 628, 755, 630, 629, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 369, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 546, + 574, 0, 588, 0, 434, 435, 0, 0, 0, 0, + 0, 0, 0, 350, 553, 571, 367, 540, 586, 372, + 548, 564, 362, 501, 536, 0, 0, 352, 569, 547, + 479, 351, 0, 529, 392, 409, 389, 499, 0, 0, + 568, 599, 388, 589, 0, 579, 354, 0, 578, 498, + 471, 565, 570, 480, 473, 0, 353, 567, 478, 472, + 448, 399, 615, 449, 450, 451, 452, 453, 454, 413, + 514, 469, 515, 414, 486, 485, 487, 415, 416, 417, + 418, 419, 420, 421, 422, 423, 424, 0, 0, 0, + 0, 0, 610, 611, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 747, + 0, 0, 752, 0, 582, 0, 0, 0, 0, 0, + 0, 551, 0, 0, 455, 0, 0, 0, 600, 0, + 532, 504, 793, 0, 0, 530, 467, 566, 516, 572, + 554, 580, 523, 517, 344, 555, 391, 481, 363, 365, + 780, 393, 396, 400, 401, 492, 493, 510, 539, 558, + 559, 560, 390, 377, 531, 378, 410, 379, 345, 382, + 381, 383, 541, 384, 347, 511, 563, 0, 406, 527, + 476, 348, 475, 512, 562, 561, 364, 590, 597, 598, + 689, 0, 603, 794, 795, 796, 612, 0, 518, 360, + 357, 0, 0, 0, 386, 513, 373, 375, 376, 374, + 507, 509, 617, 618, 619, 621, 0, 622, 623, 0, + 0, 0, 0, 624, 690, 708, 674, 643, 605, 698, + 640, 644, 645, 427, 428, 429, 430, 711, 0, 0, + 0, 596, 456, 457, 0, 398, 397, 477, 349, 0, + 0, 445, 426, 519, 355, 394, 447, 432, 458, 459, + 460, 461, 462, 0, 463, 464, 404, 339, 340, 788, + 387, 500, 713, 750, 751, 635, 0, 699, 636, 646, + 380, 671, 683, 682, 494, 595, 0, 694, 697, 625, + 787, 0, 691, 705, 792, 704, 784, 506, 0, 538, + 702, 649, 0, 695, 668, 669, 0, 696, 664, 700, + 356, 433, 524, 581, 0, 637, 0, 606, 609, 639, + 726, 727, 728, 346, 608, 730, 731, 732, 733, 734, + 735, 736, 729, 577, 672, 648, 675, 587, 651, 650, + 0, 0, 686, 604, 687, 688, 488, 489, 490, 491, + 408, 714, 371, 607, 521, 522, 0, 673, 0, 0, + 0, 0, 0, 0, 0, 0, 678, 679, 676, 797, + 0, 737, 738, 0, 0, 601, 602, 403, 0, 620, + 411, 370, 505, 405, 585, 436, 0, 613, 680, 614, + 525, 526, 741, 746, 742, 743, 745, 766, 495, 425, + 431, 542, 446, 468, 528, 584, 503, 533, 368, 573, + 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 0, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 284, - 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, - 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, - 308, 309, 310, 708, 301, 302, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 0, 0, 0, 0, 333, 767, 768, 769, 770, 771, - 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, - 549, 328, 329, 330, 331, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 753, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 758, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 337, 338, 702, - 703, 0, 0, 534, 480, 634, 500, 0, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 0, 680, 629, 542, - 482, 0, 697, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2198, 0, 0, 268, 0, 0, 0, 0, 0, - 0, 365, 269, 624, 751, 626, 625, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 0, 0, 0, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 0, 0, 565, 595, - 387, 585, 0, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 611, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 0, 0, - 748, 0, 578, 0, 0, 0, 0, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 596, 0, 529, 502, - 789, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 386, 498, - 709, 746, 747, 631, 0, 695, 632, 642, 379, 667, - 679, 678, 492, 591, 0, 690, 693, 621, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 574, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 600, 683, 684, - 486, 487, 488, 489, 407, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, - 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 0, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 284, 285, 286, 287, 288, 289, - 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, - 303, 304, 305, 306, 307, 308, 309, 310, 708, 301, - 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, - 767, 768, 769, 770, 771, 0, 0, 334, 335, 336, - 0, 0, 299, 300, 327, 549, 328, 329, 330, 331, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 753, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 758, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 744, - 343, 0, 337, 338, 702, 703, 0, 0, 534, 480, - 634, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 394, - 0, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 0, 680, 629, 542, 482, 0, 697, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4867, 0, 268, - 0, 0, 0, 0, 0, 0, 365, 269, 624, 751, - 626, 625, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 0, - 0, 0, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 0, 0, 565, 595, 387, 585, 0, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 611, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 0, 0, 748, 0, 578, 0, 0, - 0, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 596, 0, 529, 502, 789, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 386, 498, 709, 746, 747, 631, 0, - 695, 632, 642, 379, 667, 679, 678, 492, 591, 0, - 690, 693, 621, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 574, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 600, 683, 684, 486, 487, 488, 489, 407, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 0, 0, 0, 0, 0, 0, 0, + 0, 722, 721, 720, 719, 718, 717, 716, 715, 0, + 0, 662, 385, 785, 779, 786, 767, 770, 769, 744, + 0, 341, 642, 466, 520, 402, 709, 710, 0, 765, + 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, + 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, + 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, + 324, 0, 0, 0, 0, 333, 771, 772, 773, 774, + 775, 0, 0, 334, 335, 336, 0, 0, 299, 300, + 327, 552, 328, 329, 330, 331, 0, 0, 591, 592, + 593, 616, 0, 594, 575, 641, 412, 342, 556, 583, + 782, 783, 0, 0, 0, 0, 0, 0, 0, 692, + 703, 739, 740, 0, 753, 754, 756, 758, 757, 760, + 549, 550, 768, 0, 0, 437, 358, 359, 496, 497, + 535, 0, 438, 439, 440, 444, 441, 442, 443, 762, + 763, 764, 761, 470, 534, 557, 543, 781, 483, 0, + 789, 631, 632, 790, 749, 748, 343, 0, 337, 338, + 706, 707, 0, 0, 537, 482, 638, 502, 0, 0, + 647, 681, 670, 759, 634, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 395, 0, 0, 465, 685, + 666, 677, 667, 508, 652, 653, 654, 661, 407, 655, + 791, 657, 626, 658, 627, 659, 660, 0, 684, 633, + 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 268, 1073, 0, 0, 0, + 0, 0, 366, 269, 628, 755, 630, 629, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 369, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 546, 574, + 0, 588, 0, 434, 435, 0, 0, 0, 0, 0, + 0, 0, 350, 553, 571, 367, 540, 586, 372, 548, + 564, 362, 501, 536, 0, 0, 352, 569, 547, 479, + 351, 0, 529, 392, 409, 389, 499, 0, 0, 568, + 599, 388, 589, 0, 579, 354, 0, 578, 498, 471, + 565, 570, 480, 473, 0, 353, 567, 478, 472, 448, + 399, 615, 449, 450, 451, 452, 453, 454, 413, 514, + 469, 515, 414, 486, 485, 487, 415, 416, 417, 418, + 419, 420, 421, 422, 423, 424, 0, 0, 0, 0, + 0, 610, 611, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 747, 0, + 0, 752, 0, 582, 0, 0, 0, 0, 0, 0, + 551, 0, 0, 455, 0, 0, 0, 600, 0, 532, + 504, 793, 0, 0, 530, 467, 566, 516, 572, 554, + 580, 523, 517, 344, 555, 391, 481, 363, 365, 780, + 393, 396, 400, 401, 492, 493, 510, 539, 558, 559, + 560, 390, 377, 531, 378, 410, 379, 345, 382, 381, + 383, 541, 384, 347, 511, 563, 0, 406, 527, 476, + 348, 475, 512, 562, 561, 364, 590, 597, 598, 689, + 0, 603, 794, 795, 796, 612, 0, 518, 360, 357, + 0, 0, 0, 386, 513, 373, 375, 376, 374, 507, + 509, 617, 618, 619, 621, 0, 622, 623, 0, 0, + 0, 0, 624, 690, 708, 674, 643, 605, 698, 640, + 644, 645, 427, 428, 429, 430, 711, 0, 0, 0, + 596, 456, 457, 0, 398, 397, 477, 349, 0, 0, + 445, 426, 519, 355, 394, 447, 432, 458, 459, 460, + 461, 462, 0, 463, 464, 404, 339, 340, 788, 387, + 500, 713, 750, 751, 635, 0, 699, 636, 646, 380, + 671, 683, 682, 494, 595, 0, 694, 697, 625, 787, + 0, 691, 705, 792, 704, 784, 506, 0, 538, 702, + 649, 0, 695, 668, 669, 0, 696, 664, 700, 356, + 433, 524, 581, 0, 637, 0, 606, 609, 639, 726, + 727, 728, 346, 608, 730, 731, 732, 733, 734, 735, + 736, 729, 577, 672, 648, 675, 587, 651, 650, 0, + 0, 686, 604, 687, 688, 488, 489, 490, 491, 408, + 714, 371, 607, 521, 522, 0, 673, 0, 0, 0, + 0, 0, 0, 0, 0, 678, 679, 676, 797, 0, + 737, 738, 0, 0, 601, 602, 403, 0, 620, 411, + 370, 505, 405, 585, 436, 0, 613, 680, 614, 525, + 526, 741, 746, 742, 743, 745, 766, 495, 425, 431, + 542, 446, 468, 528, 584, 503, 533, 368, 573, 544, + 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 0, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 284, + 722, 721, 720, 719, 718, 717, 716, 715, 0, 0, + 662, 385, 785, 779, 786, 767, 770, 769, 744, 0, + 341, 642, 466, 520, 402, 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, - 308, 309, 310, 708, 301, 302, 311, 312, 313, 314, + 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 0, 0, 0, 0, 333, 767, 768, 769, 770, 771, + 0, 0, 0, 0, 333, 771, 772, 773, 774, 775, 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, - 549, 328, 329, 330, 331, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 753, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 758, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 337, 338, 702, - 703, 0, 0, 534, 480, 634, 500, 0, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 0, 680, 629, 542, - 482, 0, 697, 0, 0, 0, 0, 0, 0, 0, + 552, 328, 329, 330, 331, 0, 0, 591, 592, 593, + 616, 0, 594, 575, 641, 412, 342, 556, 583, 782, + 783, 0, 0, 0, 0, 0, 0, 0, 692, 703, + 739, 740, 0, 753, 754, 756, 758, 757, 760, 549, + 550, 768, 0, 0, 437, 358, 359, 496, 497, 535, + 0, 438, 439, 440, 444, 441, 442, 443, 762, 763, + 764, 761, 470, 534, 557, 543, 781, 483, 0, 789, + 631, 632, 790, 749, 748, 343, 0, 337, 338, 706, + 707, 0, 0, 537, 482, 638, 502, 0, 0, 647, + 681, 670, 759, 634, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 395, 0, 0, 465, 685, 666, + 677, 667, 508, 652, 653, 654, 661, 407, 655, 791, + 657, 626, 658, 627, 659, 660, 0, 684, 633, 545, + 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5198, 0, 0, 268, 0, 0, 0, 0, 0, + 0, 366, 269, 628, 755, 630, 629, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 369, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 546, 574, 0, + 588, 0, 434, 435, 0, 0, 0, 0, 0, 0, + 0, 350, 553, 571, 367, 540, 586, 372, 548, 564, + 362, 501, 536, 0, 0, 352, 569, 547, 479, 351, + 0, 529, 392, 409, 389, 499, 0, 0, 568, 599, + 388, 589, 0, 579, 354, 0, 578, 498, 471, 565, + 570, 480, 473, 0, 353, 567, 478, 472, 448, 399, + 615, 449, 450, 451, 452, 453, 454, 413, 514, 469, + 515, 414, 486, 485, 487, 415, 416, 417, 418, 419, + 420, 421, 422, 423, 424, 0, 0, 0, 0, 0, + 610, 611, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 747, 0, 0, + 752, 0, 582, 0, 0, 0, 0, 0, 0, 551, + 0, 0, 455, 0, 0, 0, 600, 0, 532, 504, + 793, 0, 0, 530, 467, 566, 516, 572, 554, 580, + 523, 517, 344, 555, 391, 481, 363, 365, 780, 393, + 396, 400, 401, 492, 493, 510, 539, 558, 559, 560, + 390, 377, 531, 378, 410, 379, 345, 382, 381, 383, + 541, 384, 347, 511, 563, 0, 406, 527, 476, 348, + 475, 512, 562, 561, 364, 590, 597, 598, 689, 0, + 603, 794, 795, 796, 612, 0, 518, 360, 357, 0, + 0, 0, 386, 513, 373, 375, 376, 374, 507, 509, + 617, 618, 619, 621, 0, 622, 623, 0, 0, 0, + 0, 624, 690, 708, 674, 643, 605, 698, 640, 644, + 645, 427, 428, 429, 430, 711, 0, 0, 0, 596, + 456, 457, 0, 398, 397, 477, 349, 0, 0, 445, + 426, 519, 355, 394, 447, 432, 458, 459, 460, 461, + 462, 0, 463, 464, 404, 339, 340, 788, 387, 500, + 713, 750, 751, 635, 0, 699, 636, 646, 380, 671, + 683, 682, 494, 595, 0, 694, 697, 625, 787, 0, + 691, 705, 792, 704, 784, 506, 0, 538, 702, 649, + 0, 695, 668, 669, 0, 696, 664, 700, 356, 433, + 524, 581, 0, 637, 0, 606, 609, 639, 726, 727, + 728, 346, 608, 730, 731, 732, 733, 734, 735, 736, + 729, 577, 672, 648, 675, 587, 651, 650, 0, 0, + 686, 604, 687, 688, 488, 489, 490, 491, 408, 714, + 371, 607, 521, 522, 0, 673, 0, 0, 0, 0, + 0, 0, 0, 0, 678, 679, 676, 797, 0, 737, + 738, 0, 0, 601, 602, 403, 0, 620, 411, 370, + 505, 405, 585, 436, 0, 613, 680, 614, 525, 526, + 741, 746, 742, 743, 745, 766, 495, 425, 431, 542, + 446, 468, 528, 584, 503, 533, 368, 573, 544, 474, + 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 722, + 721, 720, 719, 718, 717, 716, 715, 0, 0, 662, + 385, 785, 779, 786, 767, 770, 769, 744, 0, 341, + 642, 466, 520, 402, 709, 710, 0, 765, 284, 285, + 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, + 295, 296, 297, 298, 303, 304, 305, 306, 307, 308, + 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, + 0, 0, 0, 333, 771, 772, 773, 774, 775, 0, + 0, 334, 335, 336, 0, 0, 299, 300, 327, 552, + 328, 329, 330, 331, 0, 0, 591, 592, 593, 616, + 0, 594, 575, 641, 412, 342, 556, 583, 782, 783, + 0, 0, 0, 0, 0, 0, 0, 692, 703, 739, + 740, 0, 753, 754, 756, 758, 757, 760, 549, 550, + 768, 0, 0, 437, 358, 359, 496, 497, 535, 0, + 438, 439, 440, 444, 441, 442, 443, 762, 763, 764, + 761, 470, 534, 557, 543, 781, 483, 0, 789, 631, + 632, 790, 749, 748, 343, 0, 337, 338, 706, 707, + 0, 0, 537, 482, 638, 502, 0, 0, 647, 681, + 670, 759, 634, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 395, 0, 0, 465, 685, 666, 677, + 667, 508, 652, 653, 654, 661, 407, 655, 791, 657, + 626, 658, 627, 659, 660, 0, 684, 633, 545, 484, + 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2202, 0, 0, 268, 0, 0, 0, 0, 0, 0, + 366, 269, 628, 755, 630, 629, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 369, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 546, 574, 0, 588, + 0, 434, 435, 0, 0, 0, 0, 0, 0, 0, + 350, 553, 571, 367, 540, 586, 372, 548, 564, 362, + 501, 536, 0, 0, 352, 569, 547, 479, 351, 0, + 529, 392, 409, 389, 499, 0, 0, 568, 599, 388, + 589, 0, 579, 354, 0, 578, 498, 471, 565, 570, + 480, 473, 0, 353, 567, 478, 472, 448, 399, 615, + 449, 450, 451, 452, 453, 454, 413, 514, 469, 515, + 414, 486, 485, 487, 415, 416, 417, 418, 419, 420, + 421, 422, 423, 424, 0, 0, 0, 0, 0, 610, + 611, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 747, 0, 0, 752, + 0, 582, 0, 0, 0, 0, 0, 0, 551, 0, + 0, 455, 0, 0, 0, 600, 0, 532, 504, 793, + 0, 0, 530, 467, 566, 516, 572, 554, 580, 523, + 517, 344, 555, 391, 481, 363, 365, 780, 393, 396, + 400, 401, 492, 493, 510, 539, 558, 559, 560, 390, + 377, 531, 378, 410, 379, 345, 382, 381, 383, 541, + 384, 347, 511, 563, 0, 406, 527, 476, 348, 475, + 512, 562, 561, 364, 590, 597, 598, 689, 0, 603, + 794, 795, 796, 612, 0, 518, 360, 357, 0, 0, + 0, 386, 513, 373, 375, 376, 374, 507, 509, 617, + 618, 619, 621, 0, 622, 623, 0, 0, 0, 0, + 624, 690, 708, 674, 643, 605, 698, 640, 644, 645, + 427, 428, 429, 430, 711, 0, 0, 0, 596, 456, + 457, 0, 398, 397, 477, 349, 0, 0, 445, 426, + 519, 355, 394, 447, 432, 458, 459, 460, 461, 462, + 0, 463, 464, 404, 339, 340, 788, 387, 500, 713, + 750, 751, 635, 0, 699, 636, 646, 380, 671, 683, + 682, 494, 595, 0, 694, 697, 625, 787, 0, 691, + 705, 792, 704, 784, 506, 0, 538, 702, 649, 0, + 695, 668, 669, 0, 696, 664, 700, 356, 433, 524, + 581, 0, 637, 0, 606, 609, 639, 726, 727, 728, + 346, 608, 730, 731, 732, 733, 734, 735, 736, 729, + 577, 672, 648, 675, 587, 651, 650, 0, 0, 686, + 604, 687, 688, 488, 489, 490, 491, 408, 714, 371, + 607, 521, 522, 0, 673, 0, 0, 0, 0, 0, + 0, 0, 0, 678, 679, 676, 797, 0, 737, 738, + 0, 0, 601, 602, 403, 0, 620, 411, 370, 505, + 405, 585, 436, 0, 613, 680, 614, 525, 526, 741, + 746, 742, 743, 745, 766, 495, 425, 431, 542, 446, + 468, 528, 584, 503, 533, 368, 573, 544, 474, 665, + 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 722, 721, + 720, 719, 718, 717, 716, 715, 0, 0, 662, 385, + 785, 779, 786, 767, 770, 769, 744, 0, 341, 642, + 466, 520, 402, 709, 710, 0, 765, 284, 285, 286, + 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, + 296, 297, 298, 303, 304, 305, 306, 307, 308, 309, + 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 0, 0, + 0, 0, 333, 771, 772, 773, 774, 775, 0, 0, + 334, 335, 336, 0, 0, 299, 300, 327, 552, 328, + 329, 330, 331, 0, 0, 591, 592, 593, 616, 0, + 594, 575, 641, 412, 342, 556, 583, 782, 783, 0, + 0, 0, 0, 0, 0, 0, 692, 703, 739, 740, + 0, 753, 754, 756, 758, 757, 760, 549, 550, 768, + 0, 0, 437, 358, 359, 496, 497, 535, 0, 438, + 439, 440, 444, 441, 442, 443, 762, 763, 764, 761, + 470, 534, 557, 543, 781, 483, 0, 789, 631, 632, + 790, 749, 748, 343, 0, 337, 338, 706, 707, 0, + 0, 537, 482, 638, 502, 0, 0, 647, 681, 670, + 759, 634, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 395, 0, 0, 465, 685, 666, 677, 667, + 508, 652, 653, 654, 661, 407, 655, 791, 657, 626, + 658, 627, 659, 660, 0, 684, 633, 545, 484, 0, + 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4871, 0, 268, 0, 0, 0, 0, 0, 0, 366, + 269, 628, 755, 630, 629, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 369, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 546, 574, 0, 588, 0, + 434, 435, 0, 0, 0, 0, 0, 0, 0, 350, + 553, 571, 367, 540, 586, 372, 548, 564, 362, 501, + 536, 0, 0, 352, 569, 547, 479, 351, 0, 529, + 392, 409, 389, 499, 0, 0, 568, 599, 388, 589, + 0, 579, 354, 0, 578, 498, 471, 565, 570, 480, + 473, 0, 353, 567, 478, 472, 448, 399, 615, 449, + 450, 451, 452, 453, 454, 413, 514, 469, 515, 414, + 486, 485, 487, 415, 416, 417, 418, 419, 420, 421, + 422, 423, 424, 0, 0, 0, 0, 0, 610, 611, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 747, 0, 0, 752, 0, + 582, 0, 0, 0, 0, 0, 0, 551, 0, 0, + 455, 0, 0, 0, 600, 0, 532, 504, 793, 0, + 0, 530, 467, 566, 516, 572, 554, 580, 523, 517, + 344, 555, 391, 481, 363, 365, 780, 393, 396, 400, + 401, 492, 493, 510, 539, 558, 559, 560, 390, 377, + 531, 378, 410, 379, 345, 382, 381, 383, 541, 384, + 347, 511, 563, 0, 406, 527, 476, 348, 475, 512, + 562, 561, 364, 590, 597, 598, 689, 0, 603, 794, + 795, 796, 612, 0, 518, 360, 357, 0, 0, 0, + 386, 513, 373, 375, 376, 374, 507, 509, 617, 618, + 619, 621, 0, 622, 623, 0, 0, 0, 0, 624, + 690, 708, 674, 643, 605, 698, 640, 644, 645, 427, + 428, 429, 430, 711, 0, 0, 0, 596, 456, 457, + 0, 398, 397, 477, 349, 0, 0, 445, 426, 519, + 355, 394, 447, 432, 458, 459, 460, 461, 462, 0, + 463, 464, 404, 339, 340, 788, 387, 500, 713, 750, + 751, 635, 0, 699, 636, 646, 380, 671, 683, 682, + 494, 595, 0, 694, 697, 625, 787, 0, 691, 705, + 792, 704, 784, 506, 0, 538, 702, 649, 0, 695, + 668, 669, 0, 696, 664, 700, 356, 433, 524, 581, + 0, 637, 0, 606, 609, 639, 726, 727, 728, 346, + 608, 730, 731, 732, 733, 734, 735, 736, 729, 577, + 672, 648, 675, 587, 651, 650, 0, 0, 686, 604, + 687, 688, 488, 489, 490, 491, 408, 714, 371, 607, + 521, 522, 0, 673, 0, 0, 0, 0, 0, 0, + 0, 0, 678, 679, 676, 797, 0, 737, 738, 0, + 0, 601, 602, 403, 0, 620, 411, 370, 505, 405, + 585, 436, 0, 613, 680, 614, 525, 526, 741, 746, + 742, 743, 745, 766, 495, 425, 431, 542, 446, 468, + 528, 584, 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 268, 0, 0, 0, 0, 0, - 0, 365, 269, 624, 751, 626, 625, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 0, 0, 0, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 0, 0, 565, 595, - 387, 585, 0, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 611, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 0, 0, - 748, 0, 578, 0, 0, 0, 4860, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 596, 0, 529, 502, - 789, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 386, 498, - 709, 746, 747, 631, 0, 695, 632, 642, 379, 667, - 679, 678, 492, 591, 0, 690, 693, 621, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 574, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 600, 683, 684, - 486, 487, 488, 489, 407, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 0, 0, + 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 722, 721, 720, + 719, 718, 717, 716, 715, 0, 0, 662, 385, 785, + 779, 786, 767, 770, 769, 744, 0, 341, 642, 466, + 520, 402, 709, 710, 0, 765, 284, 285, 286, 287, + 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, + 297, 298, 303, 304, 305, 306, 307, 308, 309, 310, + 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 0, 0, 0, + 0, 333, 771, 772, 773, 774, 775, 0, 0, 334, + 335, 336, 0, 0, 299, 300, 327, 552, 328, 329, + 330, 331, 0, 0, 591, 592, 593, 616, 0, 594, + 575, 641, 412, 342, 556, 583, 782, 783, 0, 0, + 0, 0, 0, 0, 0, 692, 703, 739, 740, 0, + 753, 754, 756, 758, 757, 760, 549, 550, 768, 0, + 0, 437, 358, 359, 496, 497, 535, 0, 438, 439, + 440, 444, 441, 442, 443, 762, 763, 764, 761, 470, + 534, 557, 543, 781, 483, 0, 789, 631, 632, 790, + 749, 748, 343, 0, 337, 338, 706, 707, 0, 0, + 537, 482, 638, 502, 0, 0, 647, 681, 670, 759, + 634, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 395, 0, 0, 465, 685, 666, 677, 667, 508, + 652, 653, 654, 661, 407, 655, 791, 657, 626, 658, + 627, 659, 660, 0, 684, 633, 545, 484, 0, 701, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 268, 0, 0, 0, 0, 0, 0, 366, 269, + 628, 755, 630, 629, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 369, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 546, 574, 0, 588, 0, 434, + 435, 0, 0, 0, 0, 0, 0, 0, 350, 553, + 571, 367, 540, 586, 372, 548, 564, 362, 501, 536, + 0, 0, 352, 569, 547, 479, 351, 0, 529, 392, + 409, 389, 499, 0, 0, 568, 599, 388, 589, 0, + 579, 354, 0, 578, 498, 471, 565, 570, 480, 473, + 0, 353, 567, 478, 472, 448, 399, 615, 449, 450, + 451, 452, 453, 454, 413, 514, 469, 515, 414, 486, + 485, 487, 415, 416, 417, 418, 419, 420, 421, 422, + 423, 424, 0, 0, 0, 0, 0, 610, 611, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 747, 0, 0, 752, 0, 582, + 0, 0, 0, 4864, 0, 0, 551, 0, 0, 455, + 0, 0, 0, 600, 0, 532, 504, 793, 0, 0, + 530, 467, 566, 516, 572, 554, 580, 523, 517, 344, + 555, 391, 481, 363, 365, 780, 393, 396, 400, 401, + 492, 493, 510, 539, 558, 559, 560, 390, 377, 531, + 378, 410, 379, 345, 382, 381, 383, 541, 384, 347, + 511, 563, 0, 406, 527, 476, 348, 475, 512, 562, + 561, 364, 590, 597, 598, 689, 0, 603, 794, 795, + 796, 612, 0, 518, 360, 357, 0, 0, 0, 386, + 513, 373, 375, 376, 374, 507, 509, 617, 618, 619, + 621, 0, 622, 623, 0, 0, 0, 0, 624, 690, + 708, 674, 643, 605, 698, 640, 644, 645, 427, 428, + 429, 430, 711, 0, 0, 0, 596, 456, 457, 0, + 398, 397, 477, 349, 0, 0, 445, 426, 519, 355, + 394, 447, 432, 458, 459, 460, 461, 462, 0, 463, + 464, 404, 339, 340, 788, 387, 500, 713, 750, 751, + 635, 0, 699, 636, 646, 380, 671, 683, 682, 494, + 595, 0, 694, 697, 625, 787, 0, 691, 705, 792, + 704, 784, 506, 0, 538, 702, 649, 0, 695, 668, + 669, 0, 696, 664, 700, 356, 433, 524, 581, 0, + 637, 0, 606, 609, 639, 726, 727, 728, 346, 608, + 730, 731, 732, 733, 734, 735, 736, 729, 577, 672, + 648, 675, 587, 651, 650, 0, 0, 686, 604, 687, + 688, 488, 489, 490, 491, 408, 714, 371, 607, 521, + 522, 0, 673, 0, 0, 0, 0, 0, 0, 0, + 0, 678, 679, 676, 797, 0, 737, 738, 0, 0, + 601, 602, 403, 0, 620, 411, 370, 505, 405, 585, + 436, 0, 613, 680, 614, 525, 526, 741, 746, 742, + 743, 745, 766, 495, 425, 431, 542, 446, 468, 528, + 584, 503, 533, 368, 573, 544, 474, 665, 693, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 722, 721, 720, 719, + 718, 717, 716, 715, 0, 0, 662, 385, 785, 779, + 786, 767, 770, 769, 744, 0, 341, 642, 466, 520, + 402, 709, 710, 0, 765, 284, 285, 286, 287, 288, + 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, + 298, 303, 304, 305, 306, 307, 308, 309, 310, 712, + 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, + 333, 771, 772, 773, 774, 775, 0, 0, 334, 335, + 336, 0, 0, 299, 300, 327, 552, 328, 329, 330, + 331, 0, 0, 591, 592, 593, 616, 0, 594, 575, + 641, 412, 342, 556, 583, 782, 783, 0, 0, 0, + 0, 0, 0, 0, 692, 703, 739, 740, 0, 753, + 754, 756, 758, 757, 760, 549, 550, 768, 0, 0, + 437, 358, 359, 496, 497, 535, 0, 438, 439, 440, + 444, 441, 442, 443, 762, 763, 764, 761, 470, 534, + 557, 543, 781, 483, 0, 789, 631, 632, 790, 749, + 748, 343, 0, 337, 338, 706, 707, 0, 0, 537, + 482, 638, 502, 0, 0, 647, 681, 670, 759, 634, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 395, 0, 0, 465, 685, 666, 677, 667, 508, 652, + 653, 654, 661, 407, 655, 791, 657, 626, 658, 627, + 659, 660, 0, 684, 633, 545, 484, 0, 701, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 268, 0, 0, 4557, 0, 0, 0, 366, 269, 628, + 755, 630, 629, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 369, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 546, 574, 0, 588, 0, 434, 435, + 0, 0, 0, 0, 0, 0, 0, 350, 553, 571, + 367, 540, 586, 372, 548, 564, 362, 501, 536, 0, + 0, 352, 569, 547, 479, 351, 0, 529, 392, 409, + 389, 499, 0, 0, 568, 599, 388, 589, 0, 579, + 354, 0, 578, 498, 471, 565, 570, 480, 473, 0, + 353, 567, 478, 472, 448, 399, 615, 449, 450, 451, + 452, 453, 454, 413, 514, 469, 515, 414, 486, 485, + 487, 415, 416, 417, 418, 419, 420, 421, 422, 423, + 424, 0, 0, 0, 0, 0, 610, 611, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 747, 0, 0, 752, 0, 582, 0, + 0, 0, 0, 0, 0, 551, 0, 0, 455, 0, + 0, 0, 600, 0, 532, 504, 793, 0, 0, 530, + 467, 566, 516, 572, 554, 580, 523, 517, 344, 555, + 391, 481, 363, 365, 780, 393, 396, 400, 401, 492, + 493, 510, 539, 558, 559, 560, 390, 377, 531, 378, + 410, 379, 345, 382, 381, 383, 541, 384, 347, 511, + 563, 0, 406, 527, 476, 348, 475, 512, 562, 561, + 364, 590, 597, 598, 689, 0, 603, 794, 795, 796, + 612, 0, 518, 360, 357, 0, 0, 0, 386, 513, + 373, 375, 376, 374, 507, 509, 617, 618, 619, 621, + 0, 622, 623, 0, 0, 0, 0, 624, 690, 708, + 674, 643, 605, 698, 640, 644, 645, 427, 428, 429, + 430, 711, 0, 0, 0, 596, 456, 457, 0, 398, + 397, 477, 349, 0, 0, 445, 426, 519, 355, 394, + 447, 432, 458, 459, 460, 461, 462, 0, 463, 464, + 404, 339, 340, 788, 387, 500, 713, 750, 751, 635, + 0, 699, 636, 646, 380, 671, 683, 682, 494, 595, + 0, 694, 697, 625, 787, 0, 691, 705, 792, 704, + 784, 506, 0, 538, 702, 649, 0, 695, 668, 669, + 0, 696, 664, 700, 356, 433, 524, 581, 0, 637, + 0, 606, 609, 639, 726, 727, 728, 346, 608, 730, + 731, 732, 733, 734, 735, 736, 729, 577, 672, 648, + 675, 587, 651, 650, 0, 0, 686, 604, 687, 688, + 488, 489, 490, 491, 408, 714, 371, 607, 521, 522, + 0, 673, 0, 0, 0, 0, 0, 0, 0, 0, + 678, 679, 676, 797, 0, 737, 738, 0, 0, 601, + 602, 403, 0, 620, 411, 370, 505, 405, 585, 436, + 0, 613, 680, 614, 525, 526, 741, 746, 742, 743, + 745, 766, 495, 425, 431, 542, 446, 468, 528, 584, + 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 0, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 284, 285, 286, 287, 288, 289, + 0, 0, 0, 0, 0, 722, 721, 720, 719, 718, + 717, 716, 715, 0, 0, 662, 385, 785, 779, 786, + 767, 770, 769, 744, 0, 341, 642, 466, 520, 402, + 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, - 303, 304, 305, 306, 307, 308, 309, 310, 708, 301, + 303, 304, 305, 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, - 767, 768, 769, 770, 771, 0, 0, 334, 335, 336, - 0, 0, 299, 300, 327, 549, 328, 329, 330, 331, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 753, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 758, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 744, - 343, 0, 337, 338, 702, 703, 0, 0, 534, 480, - 634, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 394, - 0, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 0, 680, 629, 542, 482, 0, 697, 0, 0, + 771, 772, 773, 774, 775, 0, 0, 334, 335, 336, + 0, 0, 299, 300, 327, 552, 328, 329, 330, 331, + 0, 0, 591, 592, 593, 616, 0, 594, 575, 641, + 412, 342, 556, 583, 782, 783, 0, 0, 0, 0, + 0, 0, 0, 692, 703, 739, 740, 0, 753, 754, + 756, 758, 757, 760, 549, 550, 768, 0, 0, 437, + 358, 359, 496, 497, 535, 0, 438, 439, 440, 444, + 441, 442, 443, 762, 763, 764, 761, 470, 534, 557, + 543, 781, 483, 0, 789, 631, 632, 790, 749, 748, + 343, 0, 337, 338, 706, 707, 0, 0, 537, 482, + 638, 502, 0, 0, 647, 681, 670, 759, 634, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 395, + 0, 0, 465, 685, 666, 677, 667, 508, 652, 653, + 654, 661, 407, 655, 791, 657, 626, 658, 627, 659, + 660, 0, 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, - 0, 0, 4553, 0, 0, 0, 365, 269, 624, 751, - 626, 625, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 0, - 0, 0, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 0, 0, 565, 595, 387, 585, 0, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 611, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 0, 0, 748, 0, 578, 0, 0, - 0, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 596, 0, 529, 502, 789, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 386, 498, 709, 746, 747, 631, 0, - 695, 632, 642, 379, 667, 679, 678, 492, 591, 0, - 690, 693, 621, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 574, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 600, 683, 684, 486, 487, 488, 489, 407, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, + 0, 0, 4392, 0, 0, 0, 366, 269, 628, 755, + 630, 629, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 369, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 546, 574, 0, 588, 0, 434, 435, 0, + 0, 0, 0, 0, 0, 0, 350, 553, 571, 367, + 540, 586, 372, 548, 564, 362, 501, 536, 0, 0, + 352, 569, 547, 479, 351, 0, 529, 392, 409, 389, + 499, 0, 0, 568, 599, 388, 589, 0, 579, 354, + 0, 578, 498, 471, 565, 570, 480, 473, 0, 353, + 567, 478, 472, 448, 399, 615, 449, 450, 451, 452, + 453, 454, 413, 514, 469, 515, 414, 486, 485, 487, + 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, + 0, 0, 0, 0, 0, 610, 611, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 747, 0, 0, 752, 0, 582, 0, 0, + 0, 0, 0, 0, 551, 0, 0, 455, 0, 0, + 0, 600, 0, 532, 504, 793, 0, 0, 530, 467, + 566, 516, 572, 554, 580, 523, 517, 344, 555, 391, + 481, 363, 365, 780, 393, 396, 400, 401, 492, 493, + 510, 539, 558, 559, 560, 390, 377, 531, 378, 410, + 379, 345, 382, 381, 383, 541, 384, 347, 511, 563, + 0, 406, 527, 476, 348, 475, 512, 562, 561, 364, + 590, 597, 598, 689, 0, 603, 794, 795, 796, 612, + 0, 518, 360, 357, 0, 0, 0, 386, 513, 373, + 375, 376, 374, 507, 509, 617, 618, 619, 621, 0, + 622, 623, 0, 0, 0, 0, 624, 690, 708, 674, + 643, 605, 698, 640, 644, 645, 427, 428, 429, 430, + 711, 0, 0, 0, 596, 456, 457, 0, 398, 397, + 477, 349, 0, 0, 445, 426, 519, 355, 394, 447, + 432, 458, 459, 460, 461, 462, 0, 463, 464, 404, + 339, 340, 788, 387, 500, 713, 750, 751, 635, 0, + 699, 636, 646, 380, 671, 683, 682, 494, 595, 0, + 694, 697, 625, 787, 0, 691, 705, 792, 704, 784, + 506, 0, 538, 702, 649, 0, 695, 668, 669, 0, + 696, 664, 700, 356, 433, 524, 581, 0, 637, 0, + 606, 609, 639, 726, 727, 728, 346, 608, 730, 731, + 732, 733, 734, 735, 736, 729, 577, 672, 648, 675, + 587, 651, 650, 0, 0, 686, 604, 687, 688, 488, + 489, 490, 491, 408, 714, 371, 607, 521, 522, 0, + 673, 0, 0, 0, 0, 0, 0, 0, 0, 678, + 679, 676, 797, 0, 737, 738, 0, 0, 601, 602, + 403, 0, 620, 411, 370, 505, 405, 585, 436, 0, + 613, 680, 614, 525, 526, 741, 746, 742, 743, 745, + 766, 495, 425, 431, 542, 446, 468, 528, 584, 503, + 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 0, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 284, - 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, - 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, - 308, 309, 310, 708, 301, 302, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 0, 0, 0, 0, 333, 767, 768, 769, 770, 771, - 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, - 549, 328, 329, 330, 331, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 753, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 758, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 337, 338, 702, - 703, 0, 0, 534, 480, 634, 500, 0, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 0, 680, 629, 542, - 482, 0, 697, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 268, 0, 0, 4388, 0, 0, - 0, 365, 269, 624, 751, 626, 625, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 0, 0, 0, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 0, 0, 565, 595, - 387, 585, 0, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 611, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 0, 0, - 748, 0, 578, 0, 0, 0, 0, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 596, 0, 529, 502, - 789, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 386, 498, - 709, 746, 747, 631, 0, 695, 632, 642, 379, 667, - 679, 678, 492, 591, 0, 690, 693, 621, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 574, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 600, 683, 684, - 486, 487, 488, 489, 407, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, - 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 0, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 284, 285, 286, 287, 288, 289, - 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, - 303, 304, 305, 306, 307, 308, 309, 310, 708, 301, - 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, - 767, 768, 769, 770, 771, 0, 0, 334, 335, 336, - 0, 0, 299, 300, 327, 549, 328, 329, 330, 331, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 753, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 758, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 744, - 343, 0, 337, 338, 702, 703, 0, 0, 534, 480, - 634, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 394, - 0, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 0, 680, 629, 542, 482, 0, 697, 0, 0, + 0, 0, 0, 0, 722, 721, 720, 719, 718, 717, + 716, 715, 0, 0, 662, 385, 785, 779, 786, 767, + 770, 769, 744, 0, 341, 642, 466, 520, 402, 709, + 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, + 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, + 304, 305, 306, 307, 308, 309, 310, 712, 301, 302, + 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 0, 0, 0, 0, 333, 771, + 772, 773, 774, 775, 0, 0, 334, 335, 336, 0, + 0, 299, 300, 327, 552, 328, 329, 330, 331, 0, + 0, 591, 592, 593, 616, 0, 594, 575, 641, 412, + 342, 556, 583, 782, 783, 0, 0, 0, 0, 0, + 0, 0, 692, 703, 739, 740, 0, 753, 754, 756, + 758, 757, 760, 549, 550, 768, 0, 0, 437, 358, + 359, 496, 497, 535, 0, 438, 439, 440, 444, 441, + 442, 443, 762, 763, 764, 761, 470, 534, 557, 543, + 781, 483, 0, 789, 631, 632, 790, 749, 748, 343, + 0, 337, 338, 706, 707, 0, 0, 537, 482, 638, + 502, 0, 0, 647, 681, 670, 759, 634, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 395, 0, + 0, 465, 685, 666, 677, 667, 508, 652, 653, 654, + 661, 407, 655, 791, 657, 626, 658, 627, 659, 660, + 0, 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, - 0, 0, 3626, 0, 0, 0, 365, 269, 624, 751, - 626, 625, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 0, - 0, 0, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 0, 0, 565, 595, 387, 585, 0, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 611, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 0, 0, 748, 0, 578, 0, 0, - 0, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 596, 0, 529, 502, 789, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 386, 498, 709, 746, 747, 631, 0, - 695, 632, 642, 379, 667, 679, 678, 492, 591, 0, - 690, 693, 621, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 574, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 600, 683, 684, 486, 487, 488, 489, 407, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 268, 0, + 0, 3630, 0, 0, 0, 366, 269, 628, 755, 630, + 629, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 369, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 546, 574, 0, 588, 0, 434, 435, 0, 0, + 0, 0, 0, 0, 0, 350, 553, 571, 367, 540, + 586, 372, 548, 564, 362, 501, 536, 0, 0, 352, + 569, 547, 479, 351, 0, 529, 392, 409, 389, 499, + 0, 0, 568, 599, 388, 589, 0, 579, 354, 0, + 578, 498, 471, 565, 570, 480, 473, 0, 353, 567, + 478, 472, 448, 399, 615, 449, 450, 451, 452, 453, + 454, 413, 514, 469, 515, 414, 486, 485, 487, 415, + 416, 417, 418, 419, 420, 421, 422, 423, 424, 0, + 0, 0, 0, 0, 610, 611, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 747, 0, 0, 752, 0, 582, 0, 0, 0, + 0, 0, 0, 551, 0, 0, 455, 0, 0, 0, + 600, 0, 532, 504, 793, 0, 0, 530, 467, 566, + 516, 572, 554, 580, 523, 517, 344, 555, 391, 481, + 363, 365, 780, 393, 396, 400, 401, 492, 493, 510, + 539, 558, 559, 560, 390, 377, 531, 378, 410, 379, + 345, 382, 381, 383, 541, 384, 347, 511, 563, 0, + 406, 527, 476, 348, 475, 512, 562, 561, 364, 590, + 597, 598, 689, 0, 603, 794, 795, 796, 612, 0, + 518, 360, 357, 0, 0, 0, 386, 513, 373, 375, + 376, 374, 507, 509, 617, 618, 619, 621, 0, 622, + 623, 0, 0, 0, 0, 624, 690, 708, 674, 643, + 605, 698, 640, 644, 645, 427, 428, 429, 430, 711, + 0, 0, 0, 596, 456, 457, 0, 398, 397, 477, + 349, 0, 0, 445, 426, 519, 355, 394, 447, 432, + 458, 459, 460, 461, 462, 0, 463, 464, 404, 339, + 340, 788, 387, 500, 713, 750, 751, 635, 0, 699, + 636, 646, 380, 671, 683, 682, 494, 595, 0, 694, + 697, 625, 787, 0, 691, 705, 792, 704, 784, 506, + 0, 538, 702, 649, 0, 695, 668, 669, 0, 696, + 664, 700, 356, 433, 524, 581, 0, 637, 0, 606, + 609, 639, 726, 727, 728, 346, 608, 730, 731, 732, + 733, 734, 735, 736, 729, 577, 672, 648, 675, 587, + 651, 650, 0, 0, 686, 604, 687, 688, 488, 489, + 490, 491, 408, 714, 371, 607, 521, 522, 0, 673, + 0, 0, 0, 0, 0, 0, 0, 0, 678, 679, + 676, 797, 0, 737, 738, 0, 0, 601, 602, 403, + 0, 620, 411, 370, 505, 405, 585, 436, 0, 613, + 680, 614, 525, 526, 741, 746, 742, 743, 745, 766, + 495, 425, 431, 542, 446, 468, 528, 584, 503, 533, + 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 0, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 284, - 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, - 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, - 308, 309, 310, 708, 301, 302, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 0, 0, 0, 0, 333, 767, 768, 769, 770, 771, - 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, - 549, 328, 329, 330, 331, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 753, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 758, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 337, 338, 702, - 703, 0, 0, 534, 480, 634, 500, 0, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 0, 680, 629, 542, - 482, 0, 697, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 268, 0, 0, 3252, 0, 0, - 0, 365, 269, 624, 751, 626, 625, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 0, 0, 0, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 0, 0, 565, 595, - 387, 585, 0, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 611, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 0, 0, - 748, 0, 578, 0, 0, 0, 0, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 596, 0, 529, 502, - 789, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 386, 498, - 709, 746, 747, 631, 0, 695, 632, 642, 379, 667, - 679, 678, 492, 591, 0, 690, 693, 621, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 574, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 600, 683, 684, - 486, 487, 488, 489, 407, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, - 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 0, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 284, 285, 286, 287, 288, 289, - 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, - 303, 304, 305, 306, 307, 308, 309, 310, 708, 301, - 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, - 767, 768, 769, 770, 771, 0, 0, 334, 335, 336, - 0, 0, 299, 300, 327, 549, 328, 329, 330, 331, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 753, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 758, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 744, - 343, 0, 337, 338, 702, 703, 0, 0, 534, 480, - 634, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 394, - 0, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 0, 680, 629, 542, 482, 0, 697, 0, 0, + 0, 0, 0, 722, 721, 720, 719, 718, 717, 716, + 715, 0, 0, 662, 385, 785, 779, 786, 767, 770, + 769, 744, 0, 341, 642, 466, 520, 402, 709, 710, + 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, + 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, + 305, 306, 307, 308, 309, 310, 712, 301, 302, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 0, 0, 0, 0, 333, 771, 772, + 773, 774, 775, 0, 0, 334, 335, 336, 0, 0, + 299, 300, 327, 552, 328, 329, 330, 331, 0, 0, + 591, 592, 593, 616, 0, 594, 575, 641, 412, 342, + 556, 583, 782, 783, 0, 0, 0, 0, 0, 0, + 0, 692, 703, 739, 740, 0, 753, 754, 756, 758, + 757, 760, 549, 550, 768, 0, 0, 437, 358, 359, + 496, 497, 535, 0, 438, 439, 440, 444, 441, 442, + 443, 762, 763, 764, 761, 470, 534, 557, 543, 781, + 483, 0, 789, 631, 632, 790, 749, 748, 343, 0, + 337, 338, 706, 707, 0, 0, 537, 482, 638, 502, + 0, 0, 647, 681, 670, 759, 634, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 395, 0, 0, + 465, 685, 666, 677, 667, 508, 652, 653, 654, 661, + 407, 655, 791, 657, 626, 658, 627, 659, 660, 0, + 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 268, 0, 0, + 3256, 0, 0, 0, 366, 269, 628, 755, 630, 629, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 369, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 546, 574, 0, 588, 0, 434, 435, 0, 0, 0, + 0, 0, 0, 0, 350, 553, 571, 367, 540, 586, + 372, 548, 564, 362, 501, 536, 0, 0, 352, 569, + 547, 479, 351, 0, 529, 392, 409, 389, 499, 0, + 0, 568, 599, 388, 589, 0, 579, 354, 0, 578, + 498, 471, 565, 570, 480, 473, 0, 353, 567, 478, + 472, 448, 399, 615, 449, 450, 451, 452, 453, 454, + 413, 514, 469, 515, 414, 486, 485, 487, 415, 416, + 417, 418, 419, 420, 421, 422, 423, 424, 0, 0, + 0, 0, 0, 610, 611, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 747, 0, 0, 752, 0, 582, 0, 0, 0, 0, + 0, 0, 551, 0, 0, 455, 0, 0, 0, 600, + 0, 532, 504, 793, 0, 0, 530, 467, 566, 516, + 572, 554, 580, 523, 517, 344, 555, 391, 481, 363, + 365, 780, 393, 396, 400, 401, 492, 493, 510, 539, + 558, 559, 560, 390, 377, 531, 378, 410, 379, 345, + 382, 381, 383, 541, 384, 347, 511, 563, 0, 406, + 527, 476, 348, 475, 512, 562, 561, 364, 590, 597, + 598, 689, 0, 603, 794, 795, 796, 612, 0, 518, + 360, 357, 0, 0, 0, 386, 513, 373, 375, 376, + 374, 507, 509, 617, 618, 619, 621, 0, 622, 623, + 0, 0, 0, 0, 624, 690, 708, 674, 643, 605, + 698, 640, 644, 645, 427, 428, 429, 430, 711, 0, + 0, 0, 596, 456, 457, 0, 398, 397, 477, 349, + 0, 0, 445, 426, 519, 355, 394, 447, 432, 458, + 459, 460, 461, 462, 0, 463, 464, 404, 339, 340, + 788, 387, 500, 713, 750, 751, 635, 0, 699, 636, + 646, 380, 671, 683, 682, 494, 595, 0, 694, 697, + 625, 787, 0, 691, 705, 792, 704, 784, 506, 0, + 538, 702, 649, 0, 695, 668, 669, 0, 696, 664, + 700, 356, 433, 524, 581, 0, 637, 0, 606, 609, + 639, 726, 727, 728, 346, 608, 730, 731, 732, 733, + 734, 735, 736, 729, 577, 672, 648, 675, 587, 651, + 650, 0, 0, 686, 604, 687, 688, 488, 489, 490, + 491, 408, 714, 371, 607, 521, 522, 0, 673, 0, + 0, 0, 0, 0, 0, 0, 0, 678, 679, 676, + 797, 0, 737, 738, 0, 0, 601, 602, 403, 0, + 620, 411, 370, 505, 405, 585, 436, 0, 613, 680, + 614, 525, 526, 741, 746, 742, 743, 745, 766, 495, + 425, 431, 542, 446, 468, 528, 584, 503, 533, 368, + 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, - 0, 0, 3620, 0, 0, 0, 365, 269, 624, 751, - 626, 625, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 0, - 0, 0, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 0, 0, 565, 595, 387, 585, 0, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 611, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 0, 0, 748, 0, 578, 0, 0, - 0, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 596, 0, 529, 502, 789, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 386, 498, 709, 746, 747, 631, 0, - 695, 632, 642, 379, 667, 679, 678, 492, 591, 0, - 690, 693, 621, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 574, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 600, 683, 684, 486, 487, 488, 489, 407, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 722, 721, 720, 719, 718, 717, 716, 715, + 0, 0, 662, 385, 785, 779, 786, 767, 770, 769, + 744, 0, 341, 642, 466, 520, 402, 709, 710, 0, + 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, + 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, + 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 0, 0, 0, 0, 333, 771, 772, 773, + 774, 775, 0, 0, 334, 335, 336, 0, 0, 299, + 300, 327, 552, 328, 329, 330, 331, 0, 0, 591, + 592, 593, 616, 0, 594, 575, 641, 412, 342, 556, + 583, 782, 783, 0, 0, 0, 0, 0, 0, 0, + 692, 703, 739, 740, 0, 753, 754, 756, 758, 757, + 760, 549, 550, 768, 0, 0, 437, 358, 359, 496, + 497, 535, 0, 438, 439, 440, 444, 441, 442, 443, + 762, 763, 764, 761, 470, 534, 557, 543, 781, 483, + 0, 789, 631, 632, 790, 749, 748, 343, 0, 337, + 338, 706, 707, 0, 0, 537, 482, 638, 502, 0, + 0, 647, 681, 670, 759, 634, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 395, 0, 0, 465, + 685, 666, 677, 667, 508, 652, 653, 654, 661, 407, + 655, 791, 657, 626, 658, 627, 659, 660, 0, 684, + 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 268, 0, 0, 3624, + 0, 0, 0, 366, 269, 628, 755, 630, 629, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 369, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 546, + 574, 0, 588, 0, 434, 435, 0, 0, 0, 0, + 0, 0, 0, 350, 553, 571, 367, 540, 586, 372, + 548, 564, 362, 501, 536, 0, 0, 352, 569, 547, + 479, 351, 0, 529, 392, 409, 389, 499, 0, 0, + 568, 599, 388, 589, 0, 579, 354, 0, 578, 498, + 471, 565, 570, 480, 473, 0, 353, 567, 478, 472, + 448, 399, 615, 449, 450, 451, 452, 453, 454, 413, + 514, 469, 515, 414, 486, 485, 487, 415, 416, 417, + 418, 419, 420, 421, 422, 423, 424, 0, 0, 0, + 0, 0, 610, 611, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 747, + 0, 0, 752, 0, 582, 0, 0, 0, 0, 0, + 0, 551, 0, 0, 455, 0, 0, 0, 600, 0, + 532, 504, 793, 0, 0, 530, 467, 566, 516, 572, + 554, 580, 523, 517, 344, 555, 391, 481, 363, 365, + 780, 393, 396, 400, 401, 492, 493, 510, 539, 558, + 559, 560, 390, 377, 531, 378, 410, 379, 345, 382, + 381, 383, 541, 384, 347, 511, 563, 0, 406, 527, + 476, 348, 475, 512, 562, 561, 364, 590, 597, 598, + 689, 0, 603, 794, 795, 796, 612, 0, 518, 360, + 357, 0, 0, 0, 386, 513, 373, 375, 376, 374, + 507, 509, 617, 618, 619, 621, 0, 622, 623, 0, + 0, 0, 0, 624, 690, 708, 674, 643, 605, 698, + 640, 644, 645, 427, 428, 429, 430, 711, 0, 0, + 0, 596, 456, 457, 0, 398, 397, 477, 349, 0, + 0, 445, 426, 519, 355, 394, 447, 432, 458, 459, + 460, 461, 462, 0, 463, 464, 404, 339, 340, 788, + 387, 500, 713, 750, 751, 635, 0, 699, 636, 646, + 380, 671, 683, 682, 494, 595, 0, 694, 697, 625, + 787, 0, 691, 705, 792, 704, 784, 506, 0, 538, + 702, 649, 0, 695, 668, 669, 0, 696, 664, 700, + 356, 433, 524, 581, 0, 637, 0, 606, 609, 639, + 726, 727, 728, 346, 608, 730, 731, 732, 733, 734, + 735, 736, 729, 577, 672, 648, 675, 587, 651, 650, + 0, 0, 686, 604, 687, 688, 488, 489, 490, 491, + 408, 714, 371, 607, 521, 522, 0, 673, 0, 0, + 0, 0, 0, 0, 0, 0, 678, 679, 676, 797, + 0, 737, 738, 0, 0, 601, 602, 403, 0, 620, + 411, 370, 505, 405, 585, 436, 0, 613, 680, 614, + 525, 526, 741, 746, 742, 743, 745, 766, 495, 425, + 431, 542, 446, 468, 528, 584, 503, 533, 368, 573, + 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 722, 721, 720, 719, 718, 717, 716, 715, 0, + 0, 662, 385, 785, 779, 786, 767, 770, 769, 744, + 0, 341, 642, 466, 520, 402, 709, 710, 0, 765, + 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, + 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, + 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, + 324, 0, 0, 0, 0, 333, 771, 772, 773, 774, + 775, 0, 0, 334, 335, 336, 0, 0, 299, 300, + 327, 552, 328, 329, 330, 331, 0, 0, 591, 592, + 593, 616, 0, 594, 575, 641, 412, 342, 556, 583, + 782, 783, 0, 0, 0, 0, 0, 0, 0, 692, + 703, 739, 740, 0, 753, 754, 756, 758, 757, 760, + 549, 550, 768, 0, 0, 437, 358, 359, 496, 497, + 535, 0, 438, 439, 440, 444, 441, 442, 443, 762, + 763, 764, 761, 470, 534, 557, 543, 781, 483, 0, + 789, 631, 632, 790, 749, 748, 343, 0, 337, 338, + 706, 707, 0, 0, 537, 482, 638, 502, 0, 0, + 647, 681, 670, 759, 634, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 395, 0, 0, 465, 685, + 666, 677, 667, 508, 652, 653, 654, 661, 407, 655, + 791, 657, 626, 658, 627, 659, 660, 0, 684, 633, + 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 268, 0, 0, 0, 0, + 0, 0, 366, 269, 628, 755, 630, 629, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 369, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 546, 574, + 0, 588, 0, 434, 435, 0, 0, 0, 0, 0, + 0, 0, 350, 553, 571, 367, 540, 586, 372, 548, + 564, 362, 501, 536, 0, 0, 352, 569, 547, 479, + 351, 0, 529, 392, 409, 389, 499, 0, 0, 568, + 599, 388, 589, 0, 579, 354, 0, 578, 498, 471, + 565, 570, 480, 473, 0, 353, 567, 478, 472, 448, + 399, 615, 449, 450, 451, 452, 453, 454, 413, 514, + 469, 515, 414, 486, 485, 487, 415, 416, 417, 418, + 419, 420, 421, 422, 423, 424, 0, 0, 0, 0, + 0, 610, 611, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 747, 0, + 0, 752, 0, 582, 0, 0, 0, 4382, 0, 0, + 551, 0, 0, 455, 0, 0, 0, 600, 0, 532, + 504, 793, 0, 0, 530, 467, 566, 516, 572, 554, + 580, 523, 517, 344, 555, 391, 481, 363, 365, 780, + 393, 396, 400, 401, 492, 493, 510, 539, 558, 559, + 560, 390, 377, 531, 378, 410, 379, 345, 382, 381, + 383, 541, 384, 347, 511, 563, 0, 406, 527, 476, + 348, 475, 512, 562, 561, 364, 590, 597, 598, 689, + 0, 603, 794, 795, 796, 612, 0, 518, 360, 357, + 0, 0, 0, 386, 513, 373, 375, 376, 374, 507, + 509, 617, 618, 619, 621, 0, 622, 623, 0, 0, + 0, 0, 624, 690, 708, 674, 643, 605, 698, 640, + 644, 645, 427, 428, 429, 430, 711, 0, 0, 0, + 596, 456, 457, 0, 398, 397, 477, 349, 0, 0, + 445, 426, 519, 355, 394, 447, 432, 458, 459, 460, + 461, 462, 0, 463, 464, 404, 339, 340, 788, 387, + 500, 713, 750, 751, 635, 0, 699, 636, 646, 380, + 671, 683, 682, 494, 595, 0, 694, 697, 625, 787, + 0, 691, 705, 792, 704, 784, 506, 0, 538, 702, + 649, 0, 695, 668, 669, 0, 696, 664, 700, 356, + 433, 524, 581, 0, 637, 0, 606, 609, 639, 726, + 727, 728, 346, 608, 730, 731, 732, 733, 734, 735, + 736, 729, 577, 672, 648, 675, 587, 651, 650, 0, + 0, 686, 604, 687, 688, 488, 489, 490, 491, 408, + 714, 371, 607, 521, 522, 0, 673, 0, 0, 0, + 0, 0, 0, 0, 0, 678, 679, 676, 797, 0, + 737, 738, 0, 0, 601, 602, 403, 0, 620, 411, + 370, 505, 405, 585, 436, 0, 613, 680, 614, 525, + 526, 741, 746, 742, 743, 745, 766, 495, 425, 431, + 542, 446, 468, 528, 584, 503, 533, 368, 573, 544, + 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 0, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 284, + 722, 721, 720, 719, 718, 717, 716, 715, 0, 0, + 662, 385, 785, 779, 786, 767, 770, 769, 744, 0, + 341, 642, 466, 520, 402, 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, - 308, 309, 310, 708, 301, 302, 311, 312, 313, 314, + 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 0, 0, 0, 0, 333, 767, 768, 769, 770, 771, + 0, 0, 0, 0, 333, 771, 772, 773, 774, 775, 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, - 549, 328, 329, 330, 331, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 753, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 758, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 337, 338, 702, - 703, 0, 0, 534, 480, 634, 500, 0, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 0, 680, 629, 542, - 482, 0, 697, 0, 0, 0, 0, 0, 0, 0, + 552, 328, 329, 330, 331, 0, 0, 591, 592, 593, + 616, 0, 594, 575, 641, 412, 342, 556, 583, 782, + 783, 0, 0, 0, 0, 0, 0, 0, 692, 703, + 739, 740, 0, 753, 754, 756, 758, 757, 760, 549, + 550, 768, 0, 0, 437, 358, 359, 496, 497, 535, + 0, 438, 439, 440, 444, 441, 442, 443, 762, 763, + 764, 761, 470, 534, 557, 543, 781, 483, 0, 789, + 631, 632, 790, 749, 748, 343, 0, 337, 338, 706, + 707, 0, 0, 537, 482, 638, 502, 0, 0, 647, + 681, 670, 759, 634, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 395, 0, 0, 465, 685, 666, + 677, 667, 508, 652, 653, 654, 661, 407, 655, 791, + 657, 626, 658, 627, 659, 660, 0, 684, 633, 545, + 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, 0, 0, 0, 0, 0, - 0, 365, 269, 624, 751, 626, 625, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 0, 0, 0, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 0, 0, 565, 595, - 387, 585, 0, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 611, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 0, 0, - 748, 0, 578, 0, 0, 0, 4378, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 596, 0, 529, 502, - 789, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 386, 498, - 709, 746, 747, 631, 0, 695, 632, 642, 379, 667, - 679, 678, 492, 591, 0, 690, 693, 621, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 574, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 600, 683, 684, - 486, 487, 488, 489, 407, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, - 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 0, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 284, 285, 286, 287, 288, 289, - 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, - 303, 304, 305, 306, 307, 308, 309, 310, 708, 301, - 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, - 767, 768, 769, 770, 771, 0, 0, 334, 335, 336, - 0, 0, 299, 300, 327, 549, 328, 329, 330, 331, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 753, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 758, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 744, - 343, 0, 337, 338, 702, 703, 0, 0, 534, 480, - 634, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 394, - 0, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 0, 680, 629, 542, 482, 0, 697, 0, 0, + 0, 366, 269, 628, 755, 630, 629, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 369, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4073, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 546, 574, 0, + 588, 0, 434, 435, 0, 0, 0, 0, 0, 0, + 0, 350, 553, 571, 367, 540, 586, 372, 548, 564, + 362, 501, 536, 0, 0, 352, 569, 547, 479, 351, + 0, 529, 392, 409, 389, 499, 0, 0, 568, 599, + 388, 589, 0, 579, 354, 0, 578, 498, 471, 565, + 570, 480, 473, 0, 353, 567, 478, 472, 448, 399, + 615, 449, 450, 451, 452, 453, 454, 413, 514, 469, + 515, 414, 486, 485, 487, 415, 416, 417, 418, 419, + 420, 421, 422, 423, 424, 0, 0, 0, 0, 0, + 610, 611, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 747, 0, 0, + 752, 0, 582, 0, 0, 0, 0, 0, 0, 551, + 0, 0, 455, 0, 0, 0, 600, 0, 532, 504, + 793, 0, 0, 530, 467, 566, 516, 572, 554, 580, + 523, 517, 344, 555, 391, 481, 363, 365, 780, 393, + 396, 400, 401, 492, 493, 510, 539, 558, 559, 560, + 390, 377, 531, 378, 410, 379, 345, 382, 381, 383, + 541, 384, 347, 511, 563, 0, 406, 527, 476, 348, + 475, 512, 562, 561, 364, 590, 597, 598, 689, 0, + 603, 794, 795, 796, 612, 0, 518, 360, 357, 0, + 0, 0, 386, 513, 373, 375, 376, 374, 507, 509, + 617, 618, 619, 621, 0, 622, 623, 0, 0, 0, + 0, 624, 690, 708, 674, 643, 605, 698, 640, 644, + 645, 427, 428, 429, 430, 711, 0, 0, 0, 596, + 456, 457, 0, 398, 397, 477, 349, 0, 0, 445, + 426, 519, 355, 394, 447, 432, 458, 459, 460, 461, + 462, 0, 463, 464, 404, 339, 340, 788, 387, 500, + 713, 750, 751, 635, 0, 699, 636, 646, 380, 671, + 683, 682, 494, 595, 0, 694, 697, 625, 787, 0, + 691, 705, 792, 704, 784, 506, 0, 538, 702, 649, + 0, 695, 668, 669, 0, 696, 664, 700, 356, 433, + 524, 581, 0, 637, 0, 606, 609, 639, 726, 727, + 728, 346, 608, 730, 731, 732, 733, 734, 735, 736, + 729, 577, 672, 648, 675, 587, 651, 650, 0, 0, + 686, 604, 687, 688, 488, 489, 490, 491, 408, 714, + 371, 607, 521, 522, 0, 673, 0, 0, 0, 0, + 0, 0, 0, 0, 678, 679, 676, 797, 0, 737, + 738, 0, 0, 601, 602, 403, 0, 620, 411, 370, + 505, 405, 585, 436, 0, 613, 680, 614, 525, 526, + 741, 746, 742, 743, 745, 766, 495, 425, 431, 542, + 446, 468, 528, 584, 503, 533, 368, 573, 544, 474, + 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 722, + 721, 720, 719, 718, 717, 716, 715, 0, 0, 662, + 385, 785, 779, 786, 767, 770, 769, 744, 0, 341, + 642, 466, 520, 402, 709, 710, 0, 765, 284, 285, + 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, + 295, 296, 297, 298, 303, 304, 305, 306, 307, 308, + 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, + 0, 0, 0, 333, 771, 772, 773, 774, 775, 0, + 0, 334, 335, 336, 0, 0, 299, 300, 327, 552, + 328, 329, 330, 331, 0, 0, 591, 592, 593, 616, + 0, 594, 575, 641, 412, 342, 556, 583, 782, 783, + 0, 0, 0, 0, 0, 0, 0, 692, 703, 739, + 740, 0, 753, 754, 756, 758, 757, 760, 549, 550, + 768, 0, 0, 437, 358, 359, 496, 497, 535, 0, + 438, 439, 440, 444, 441, 442, 443, 762, 763, 764, + 761, 470, 534, 557, 543, 781, 483, 0, 789, 631, + 632, 790, 749, 748, 343, 0, 337, 338, 706, 707, + 0, 0, 537, 482, 638, 502, 0, 0, 647, 681, + 670, 759, 634, 0, 0, 0, 0, 0, 2451, 0, + 0, 0, 0, 395, 0, 0, 465, 685, 666, 677, + 667, 508, 652, 653, 654, 661, 407, 655, 791, 657, + 626, 658, 627, 659, 660, 0, 684, 633, 545, 484, + 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 268, 0, 0, 2453, 0, 0, 0, + 366, 269, 628, 755, 630, 629, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 369, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 546, 574, 0, 588, + 0, 434, 435, 0, 0, 0, 0, 0, 0, 0, + 350, 553, 571, 367, 540, 586, 372, 548, 564, 362, + 501, 536, 0, 0, 352, 569, 547, 479, 351, 0, + 529, 392, 409, 389, 499, 0, 0, 568, 599, 388, + 589, 0, 579, 354, 0, 578, 498, 471, 565, 570, + 480, 473, 0, 353, 567, 478, 472, 448, 399, 615, + 449, 450, 451, 452, 453, 454, 413, 514, 469, 515, + 414, 486, 485, 487, 415, 416, 417, 418, 419, 420, + 421, 422, 423, 424, 0, 0, 0, 0, 0, 610, + 611, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 747, 0, 0, 752, + 0, 582, 0, 0, 0, 0, 0, 0, 551, 0, + 0, 455, 0, 0, 0, 600, 0, 532, 504, 793, + 0, 0, 530, 467, 566, 516, 572, 554, 580, 523, + 517, 344, 555, 391, 481, 363, 365, 780, 393, 396, + 400, 401, 492, 493, 510, 539, 558, 559, 560, 390, + 377, 531, 378, 410, 379, 345, 382, 381, 383, 541, + 384, 347, 511, 563, 0, 406, 527, 476, 348, 475, + 512, 562, 561, 364, 590, 597, 598, 689, 0, 603, + 794, 795, 796, 612, 0, 518, 360, 357, 0, 0, + 0, 386, 513, 373, 375, 376, 374, 507, 509, 617, + 618, 619, 621, 0, 622, 623, 0, 0, 0, 0, + 624, 690, 708, 674, 643, 605, 698, 640, 644, 645, + 427, 428, 429, 430, 711, 0, 0, 0, 596, 456, + 457, 0, 398, 397, 477, 349, 0, 0, 445, 426, + 519, 355, 394, 447, 432, 458, 459, 460, 461, 462, + 0, 463, 464, 404, 339, 340, 788, 387, 500, 713, + 750, 751, 635, 0, 699, 636, 646, 380, 671, 683, + 682, 494, 595, 0, 694, 697, 625, 787, 0, 691, + 705, 792, 704, 784, 506, 0, 538, 702, 649, 0, + 695, 668, 669, 0, 696, 664, 700, 356, 433, 524, + 581, 0, 637, 0, 606, 609, 639, 726, 727, 728, + 346, 608, 730, 731, 732, 733, 734, 735, 736, 729, + 577, 672, 648, 675, 587, 651, 650, 0, 0, 686, + 604, 687, 688, 488, 489, 490, 491, 408, 714, 371, + 607, 521, 522, 0, 673, 0, 0, 0, 0, 0, + 0, 0, 0, 678, 679, 676, 797, 0, 737, 738, + 0, 0, 601, 602, 403, 0, 620, 411, 370, 505, + 405, 585, 436, 0, 613, 680, 614, 525, 526, 741, + 746, 742, 743, 745, 766, 495, 425, 431, 542, 446, + 468, 528, 584, 503, 533, 368, 573, 544, 474, 665, + 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 722, 721, + 720, 719, 718, 717, 716, 715, 0, 0, 662, 385, + 785, 779, 786, 767, 770, 769, 744, 0, 341, 642, + 466, 520, 402, 709, 710, 0, 765, 284, 285, 286, + 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, + 296, 297, 298, 303, 304, 305, 306, 307, 308, 309, + 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 0, 0, + 0, 0, 333, 771, 772, 773, 774, 775, 0, 0, + 334, 335, 336, 0, 0, 299, 300, 327, 552, 328, + 329, 330, 331, 0, 0, 591, 592, 593, 616, 0, + 594, 575, 641, 412, 342, 556, 583, 782, 783, 0, + 0, 0, 0, 0, 0, 0, 692, 703, 739, 740, + 0, 753, 754, 756, 758, 757, 760, 549, 550, 768, + 0, 0, 437, 358, 359, 496, 497, 535, 0, 438, + 439, 440, 444, 441, 442, 443, 762, 763, 764, 761, + 470, 534, 557, 543, 781, 483, 0, 789, 631, 632, + 790, 749, 0, 343, 0, 337, 338, 706, 707, 0, + 0, 537, 482, 638, 502, 0, 0, 647, 681, 670, + 759, 634, 0, 0, 4329, 0, 0, 0, 0, 0, + 0, 0, 395, 0, 0, 465, 685, 666, 677, 667, + 508, 652, 653, 654, 661, 407, 655, 791, 657, 626, + 658, 627, 659, 660, 0, 684, 633, 545, 484, 0, + 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 268, 0, 0, 0, 0, 0, 0, 366, + 269, 628, 755, 630, 629, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 369, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 546, 574, 0, 588, 0, + 434, 435, 0, 0, 0, 0, 0, 0, 0, 350, + 553, 571, 367, 540, 586, 372, 548, 564, 362, 501, + 536, 0, 0, 352, 569, 547, 479, 351, 0, 529, + 392, 409, 389, 499, 0, 0, 568, 599, 388, 589, + 0, 579, 354, 0, 578, 498, 471, 565, 570, 480, + 473, 0, 353, 567, 478, 472, 448, 399, 615, 449, + 450, 451, 452, 453, 454, 413, 514, 469, 515, 414, + 486, 485, 487, 415, 416, 417, 418, 419, 420, 421, + 422, 423, 424, 0, 0, 0, 0, 0, 610, 611, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 747, 0, 0, 752, 0, + 582, 0, 0, 0, 0, 0, 0, 551, 0, 0, + 455, 0, 0, 0, 600, 0, 532, 504, 793, 0, + 0, 530, 467, 566, 516, 572, 554, 580, 523, 517, + 344, 555, 391, 481, 363, 365, 780, 393, 396, 400, + 401, 492, 493, 510, 539, 558, 559, 560, 390, 377, + 531, 378, 410, 379, 345, 382, 381, 383, 541, 384, + 347, 511, 563, 0, 406, 527, 476, 348, 475, 512, + 562, 561, 364, 590, 597, 598, 689, 0, 603, 794, + 795, 796, 612, 0, 518, 360, 357, 0, 0, 0, + 386, 513, 373, 375, 376, 374, 507, 509, 617, 618, + 619, 621, 0, 622, 623, 0, 0, 0, 0, 624, + 690, 708, 674, 643, 605, 698, 640, 644, 645, 427, + 428, 429, 430, 711, 0, 0, 0, 596, 456, 457, + 0, 398, 397, 477, 349, 0, 0, 445, 426, 519, + 355, 394, 447, 432, 458, 459, 460, 461, 462, 0, + 463, 464, 404, 339, 340, 788, 387, 500, 713, 750, + 751, 635, 0, 699, 636, 646, 380, 671, 683, 682, + 494, 595, 0, 694, 697, 625, 787, 0, 691, 705, + 792, 704, 784, 506, 0, 538, 702, 649, 0, 695, + 668, 669, 0, 696, 664, 700, 356, 433, 524, 581, + 0, 637, 0, 606, 609, 639, 726, 727, 728, 346, + 608, 730, 731, 732, 733, 734, 735, 736, 729, 577, + 672, 648, 675, 587, 651, 650, 0, 0, 686, 604, + 687, 688, 488, 489, 490, 491, 408, 714, 371, 607, + 521, 522, 0, 673, 0, 0, 0, 0, 0, 0, + 0, 0, 678, 679, 676, 797, 0, 737, 738, 0, + 0, 601, 602, 403, 0, 620, 411, 370, 505, 405, + 585, 436, 0, 613, 680, 614, 525, 526, 741, 746, + 742, 743, 745, 766, 495, 425, 431, 542, 446, 468, + 528, 584, 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, - 0, 0, 0, 0, 0, 0, 365, 269, 624, 751, - 626, 625, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 4069, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 0, - 0, 0, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 0, 0, 565, 595, 387, 585, 0, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 611, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 0, 0, 748, 0, 578, 0, 0, - 0, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 596, 0, 529, 502, 789, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 386, 498, 709, 746, 747, 631, 0, - 695, 632, 642, 379, 667, 679, 678, 492, 591, 0, - 690, 693, 621, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 574, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 600, 683, 684, 486, 487, 488, 489, 407, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, + 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 722, 721, 720, + 719, 718, 717, 716, 715, 0, 0, 662, 385, 785, + 779, 786, 767, 770, 769, 744, 0, 341, 642, 466, + 520, 402, 709, 710, 0, 765, 284, 285, 286, 287, + 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, + 297, 298, 303, 304, 305, 306, 307, 308, 309, 310, + 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 0, 0, 0, + 0, 333, 771, 772, 773, 774, 775, 0, 0, 334, + 335, 336, 0, 0, 299, 300, 327, 552, 328, 329, + 330, 331, 0, 0, 591, 592, 593, 616, 0, 594, + 575, 641, 412, 342, 556, 583, 782, 783, 0, 0, + 0, 0, 0, 0, 0, 692, 703, 739, 740, 0, + 753, 754, 756, 758, 757, 760, 549, 550, 768, 0, + 0, 437, 358, 359, 496, 497, 535, 0, 438, 439, + 440, 444, 441, 442, 443, 762, 763, 764, 761, 470, + 534, 557, 543, 781, 483, 0, 789, 631, 632, 790, + 749, 748, 343, 0, 337, 338, 706, 707, 0, 0, + 537, 482, 638, 502, 0, 0, 647, 681, 670, 759, + 634, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 395, 0, 0, 465, 685, 666, 677, 667, 508, + 652, 653, 654, 661, 407, 655, 791, 657, 626, 658, + 627, 659, 660, 0, 684, 633, 545, 484, 0, 701, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 268, 0, 0, 0, 0, 0, 0, 366, 269, + 628, 755, 630, 629, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 369, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4192, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 546, 574, 0, 588, 0, 434, + 435, 0, 0, 0, 0, 0, 0, 0, 350, 553, + 571, 367, 540, 586, 372, 548, 564, 362, 501, 536, + 0, 0, 352, 569, 547, 479, 351, 0, 529, 392, + 409, 389, 499, 0, 0, 568, 599, 388, 589, 0, + 579, 354, 0, 578, 498, 471, 565, 570, 480, 473, + 0, 353, 567, 478, 472, 448, 399, 615, 449, 450, + 451, 452, 453, 454, 413, 514, 469, 515, 414, 486, + 485, 487, 415, 416, 417, 418, 419, 420, 421, 422, + 423, 424, 0, 0, 0, 0, 0, 610, 611, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 747, 0, 0, 752, 0, 582, + 0, 0, 0, 0, 0, 0, 551, 0, 0, 455, + 0, 0, 0, 600, 0, 532, 504, 793, 0, 0, + 530, 467, 566, 516, 572, 554, 580, 523, 517, 344, + 555, 391, 481, 363, 365, 780, 393, 396, 400, 401, + 492, 493, 510, 539, 558, 559, 560, 390, 377, 531, + 378, 410, 379, 345, 382, 381, 383, 541, 384, 347, + 511, 563, 0, 406, 527, 476, 348, 475, 512, 562, + 561, 364, 590, 597, 598, 689, 0, 603, 794, 795, + 796, 612, 0, 518, 360, 357, 0, 0, 0, 386, + 513, 373, 375, 376, 374, 507, 509, 617, 618, 619, + 621, 0, 622, 623, 0, 0, 0, 0, 624, 690, + 708, 674, 643, 605, 698, 640, 644, 645, 427, 428, + 429, 430, 711, 0, 0, 0, 596, 456, 457, 0, + 398, 397, 477, 349, 0, 0, 445, 426, 519, 355, + 394, 447, 432, 458, 459, 460, 461, 462, 0, 463, + 464, 404, 339, 340, 788, 387, 500, 713, 750, 751, + 635, 0, 699, 636, 646, 380, 671, 683, 682, 494, + 595, 0, 694, 697, 625, 787, 0, 691, 705, 792, + 704, 784, 506, 0, 538, 702, 649, 0, 695, 668, + 669, 0, 696, 664, 700, 356, 433, 524, 581, 0, + 637, 0, 606, 609, 639, 726, 727, 728, 346, 608, + 730, 731, 732, 733, 734, 735, 736, 729, 577, 672, + 648, 675, 587, 651, 650, 0, 0, 686, 604, 687, + 688, 488, 489, 490, 491, 408, 714, 371, 607, 521, + 522, 0, 673, 0, 0, 0, 0, 0, 0, 0, + 0, 678, 679, 676, 797, 0, 737, 738, 0, 0, + 601, 602, 403, 0, 620, 411, 370, 505, 405, 585, + 436, 0, 613, 680, 614, 525, 526, 741, 746, 742, + 743, 745, 766, 495, 425, 431, 542, 446, 468, 528, + 584, 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 0, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 284, - 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, - 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, - 308, 309, 310, 708, 301, 302, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 0, 0, 0, 0, 333, 767, 768, 769, 770, 771, - 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, - 549, 328, 329, 330, 331, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 753, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 758, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 337, 338, 702, - 703, 0, 0, 534, 480, 634, 500, 0, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 2447, - 0, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 0, 680, 629, 542, - 482, 0, 697, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 268, 0, 0, 2449, 0, 0, - 0, 365, 269, 624, 751, 626, 625, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 0, 0, 0, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 0, 0, 565, 595, - 387, 585, 0, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 611, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 0, 0, - 748, 0, 578, 0, 0, 0, 0, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 596, 0, 529, 502, - 789, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 386, 498, - 709, 746, 747, 631, 0, 695, 632, 642, 379, 667, - 679, 678, 492, 591, 0, 690, 693, 621, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 574, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 600, 683, 684, - 486, 487, 488, 489, 407, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 0, 0, + 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 722, 721, 720, 719, + 718, 717, 716, 715, 0, 0, 662, 385, 785, 779, + 786, 767, 770, 769, 744, 0, 341, 642, 466, 520, + 402, 709, 710, 0, 765, 284, 285, 286, 287, 288, + 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, + 298, 303, 304, 305, 306, 307, 308, 309, 310, 712, + 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, + 333, 771, 772, 773, 774, 775, 0, 0, 334, 335, + 336, 0, 0, 299, 300, 327, 552, 328, 329, 330, + 331, 0, 0, 591, 592, 593, 616, 0, 594, 575, + 641, 412, 342, 556, 583, 782, 783, 0, 0, 0, + 0, 0, 0, 0, 692, 703, 739, 740, 0, 753, + 754, 756, 758, 757, 760, 549, 550, 768, 0, 0, + 437, 358, 359, 496, 497, 535, 0, 438, 439, 440, + 444, 441, 442, 443, 762, 763, 764, 761, 470, 534, + 557, 543, 781, 483, 0, 789, 631, 632, 790, 749, + 748, 343, 0, 337, 338, 706, 707, 0, 0, 537, + 482, 638, 502, 0, 0, 647, 681, 670, 759, 634, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 395, 0, 0, 465, 685, 666, 677, 667, 508, 652, + 653, 654, 661, 407, 655, 791, 657, 626, 658, 627, + 659, 660, 0, 684, 633, 545, 484, 0, 701, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 268, 0, 0, 4039, 0, 0, 0, 366, 269, 628, + 755, 630, 629, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 369, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 546, 574, 0, 588, 0, 434, 435, + 0, 0, 0, 0, 0, 0, 0, 350, 553, 571, + 367, 540, 586, 372, 548, 564, 362, 501, 536, 0, + 0, 352, 569, 547, 479, 351, 0, 529, 392, 409, + 389, 499, 0, 0, 568, 599, 388, 589, 0, 579, + 354, 0, 578, 498, 471, 565, 570, 480, 473, 0, + 353, 567, 478, 472, 448, 399, 615, 449, 450, 451, + 452, 453, 454, 413, 514, 469, 515, 414, 486, 485, + 487, 415, 416, 417, 418, 419, 420, 421, 422, 423, + 424, 0, 0, 0, 0, 0, 610, 611, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 747, 0, 0, 752, 0, 582, 0, + 0, 0, 0, 0, 0, 551, 0, 0, 455, 0, + 0, 0, 600, 0, 532, 504, 793, 0, 0, 530, + 467, 566, 516, 572, 554, 580, 523, 517, 344, 555, + 391, 481, 363, 365, 780, 393, 396, 400, 401, 492, + 493, 510, 539, 558, 559, 560, 390, 377, 531, 378, + 410, 379, 345, 382, 381, 383, 541, 384, 347, 511, + 563, 0, 406, 527, 476, 348, 475, 512, 562, 561, + 364, 590, 597, 598, 689, 0, 603, 794, 795, 796, + 612, 0, 518, 360, 357, 0, 0, 0, 386, 513, + 373, 375, 376, 374, 507, 509, 617, 618, 619, 621, + 0, 622, 623, 0, 0, 0, 0, 624, 690, 708, + 674, 643, 605, 698, 640, 644, 645, 427, 428, 429, + 430, 711, 0, 0, 0, 596, 456, 457, 0, 398, + 397, 477, 349, 0, 0, 445, 426, 519, 355, 394, + 447, 432, 458, 459, 460, 461, 462, 0, 463, 464, + 404, 339, 340, 788, 387, 500, 713, 750, 751, 635, + 0, 699, 636, 646, 380, 671, 683, 682, 494, 595, + 0, 694, 697, 625, 787, 0, 691, 705, 792, 704, + 784, 506, 0, 538, 702, 649, 0, 695, 668, 669, + 0, 696, 664, 700, 356, 433, 524, 581, 0, 637, + 0, 606, 609, 639, 726, 727, 728, 346, 608, 730, + 731, 732, 733, 734, 735, 736, 729, 577, 672, 648, + 675, 587, 651, 650, 0, 0, 686, 604, 687, 688, + 488, 489, 490, 491, 408, 714, 371, 607, 521, 522, + 0, 673, 0, 0, 0, 0, 0, 0, 0, 0, + 678, 679, 676, 797, 0, 737, 738, 0, 0, 601, + 602, 403, 0, 620, 411, 370, 505, 405, 585, 436, + 0, 613, 680, 614, 525, 526, 741, 746, 742, 743, + 745, 766, 495, 425, 431, 542, 446, 468, 528, 584, + 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 0, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 284, 285, 286, 287, 288, 289, + 0, 0, 0, 0, 0, 722, 721, 720, 719, 718, + 717, 716, 715, 0, 0, 662, 385, 785, 779, 786, + 767, 770, 769, 744, 0, 341, 642, 466, 520, 402, + 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, - 303, 304, 305, 306, 307, 308, 309, 310, 708, 301, + 303, 304, 305, 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, - 767, 768, 769, 770, 771, 0, 0, 334, 335, 336, - 0, 0, 299, 300, 327, 549, 328, 329, 330, 331, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 753, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 758, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 0, - 343, 0, 337, 338, 702, 703, 0, 0, 534, 480, - 634, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 4325, 0, 0, 0, 0, 0, 0, 0, 394, - 0, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 0, 680, 629, 542, 482, 0, 697, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, - 0, 0, 0, 0, 0, 0, 365, 269, 624, 751, - 626, 625, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 0, - 0, 0, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 0, 0, 565, 595, 387, 585, 0, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 611, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 0, 0, 748, 0, 578, 0, 0, - 0, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 596, 0, 529, 502, 789, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 386, 498, 709, 746, 747, 631, 0, - 695, 632, 642, 379, 667, 679, 678, 492, 591, 0, - 690, 693, 621, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 574, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 600, 683, 684, 486, 487, 488, 489, 407, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 0, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 284, - 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, - 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, - 308, 309, 310, 708, 301, 302, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 0, 0, 0, 0, 333, 767, 768, 769, 770, 771, - 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, - 549, 328, 329, 330, 331, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 753, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 758, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 337, 338, 702, - 703, 0, 0, 534, 480, 634, 500, 0, 0, 643, - 677, 666, 755, 630, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 394, 0, 0, 463, 681, 662, - 673, 663, 506, 648, 649, 650, 657, 406, 651, 787, - 653, 622, 654, 623, 655, 656, 0, 680, 629, 542, - 482, 0, 697, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 268, 0, 0, 0, 0, 0, - 0, 365, 269, 624, 751, 626, 625, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4188, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 543, 571, 0, - 584, 0, 432, 433, 0, 0, 0, 0, 0, 0, - 0, 350, 550, 568, 366, 537, 582, 371, 545, 561, - 361, 499, 533, 0, 0, 352, 566, 544, 477, 351, - 0, 526, 391, 408, 388, 497, 0, 0, 565, 595, - 387, 585, 0, 576, 354, 0, 575, 496, 469, 562, - 567, 478, 471, 0, 353, 564, 476, 470, 446, 398, - 611, 447, 448, 449, 450, 451, 452, 412, 512, 467, - 513, 413, 484, 483, 485, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 0, 0, 0, 0, 0, - 606, 607, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 743, 0, 0, - 748, 0, 578, 0, 0, 0, 0, 0, 0, 548, - 0, 0, 453, 0, 0, 0, 596, 0, 529, 502, - 789, 0, 0, 527, 465, 563, 514, 569, 551, 577, - 521, 515, 344, 552, 390, 479, 362, 364, 776, 392, - 395, 399, 400, 490, 491, 508, 536, 555, 556, 557, - 389, 376, 528, 377, 409, 378, 345, 381, 380, 382, - 538, 383, 347, 509, 560, 0, 405, 524, 474, 348, - 473, 510, 559, 558, 363, 586, 593, 594, 685, 0, - 599, 790, 791, 792, 608, 0, 516, 359, 356, 0, - 0, 0, 385, 511, 372, 374, 375, 373, 505, 507, - 613, 614, 615, 617, 0, 618, 619, 0, 0, 0, - 0, 620, 686, 704, 670, 639, 601, 694, 636, 640, - 641, 426, 427, 428, 429, 707, 0, 0, 0, 592, - 454, 455, 0, 397, 396, 475, 349, 0, 0, 443, - 425, 517, 355, 393, 445, 431, 456, 457, 458, 459, - 460, 0, 461, 462, 403, 339, 340, 784, 386, 498, - 709, 746, 747, 631, 0, 695, 632, 642, 379, 667, - 679, 678, 492, 591, 0, 690, 693, 621, 783, 0, - 687, 701, 788, 700, 780, 504, 0, 535, 698, 645, - 0, 691, 664, 665, 0, 692, 660, 696, 0, 633, - 0, 602, 605, 635, 722, 723, 724, 346, 604, 726, - 727, 728, 729, 730, 731, 732, 725, 574, 668, 644, - 671, 583, 647, 646, 0, 0, 682, 600, 683, 684, - 486, 487, 488, 489, 407, 710, 370, 603, 519, 520, - 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, - 674, 675, 672, 793, 0, 733, 734, 0, 0, 597, - 598, 402, 0, 616, 410, 369, 503, 404, 581, 434, - 0, 609, 676, 610, 522, 523, 737, 742, 738, 739, - 741, 762, 493, 424, 430, 539, 444, 466, 525, 580, - 501, 530, 367, 570, 541, 472, 661, 689, 0, 0, + 771, 772, 773, 774, 775, 0, 0, 334, 335, 336, + 0, 0, 299, 300, 327, 552, 328, 329, 330, 331, + 0, 0, 591, 592, 593, 616, 0, 594, 575, 641, + 412, 342, 556, 583, 782, 783, 0, 0, 0, 0, + 0, 0, 0, 692, 703, 739, 740, 0, 753, 754, + 756, 758, 757, 760, 549, 550, 768, 0, 0, 437, + 358, 359, 496, 497, 535, 0, 438, 439, 440, 444, + 441, 442, 443, 762, 763, 764, 761, 470, 534, 557, + 543, 781, 483, 0, 789, 631, 632, 790, 749, 748, + 343, 0, 337, 338, 706, 707, 3968, 0, 537, 482, + 638, 0, 502, 0, 0, 647, 681, 670, 759, 634, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 395, 0, 0, 465, 685, 666, 677, 667, 508, 652, + 653, 654, 661, 407, 655, 791, 657, 626, 658, 627, + 659, 660, 0, 684, 633, 545, 484, 0, 701, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 268, 0, 0, 0, 0, 0, 0, 366, 269, 628, + 755, 630, 629, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 369, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 546, 574, 0, 588, 0, 434, 435, + 0, 0, 0, 0, 0, 0, 0, 350, 553, 571, + 367, 540, 586, 372, 548, 564, 362, 501, 536, 0, + 0, 352, 569, 547, 479, 351, 0, 529, 392, 409, + 389, 499, 0, 0, 568, 599, 388, 589, 0, 579, + 354, 0, 578, 498, 471, 565, 570, 480, 473, 0, + 353, 567, 478, 472, 448, 399, 615, 449, 450, 451, + 452, 453, 454, 413, 514, 469, 515, 414, 486, 485, + 487, 415, 416, 417, 418, 419, 420, 421, 422, 423, + 424, 0, 0, 0, 0, 0, 610, 611, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 747, 0, 0, 752, 0, 582, 0, + 0, 0, 0, 0, 0, 551, 0, 0, 455, 0, + 0, 0, 600, 0, 532, 504, 793, 0, 0, 530, + 467, 566, 516, 572, 554, 580, 523, 517, 344, 555, + 391, 481, 363, 365, 780, 393, 396, 400, 401, 492, + 493, 510, 539, 558, 559, 560, 390, 377, 531, 378, + 410, 379, 345, 382, 381, 383, 541, 384, 347, 511, + 563, 0, 406, 527, 476, 348, 475, 512, 562, 561, + 364, 590, 597, 598, 689, 0, 603, 794, 795, 796, + 612, 0, 518, 360, 357, 0, 0, 0, 386, 513, + 373, 375, 376, 374, 507, 509, 617, 618, 619, 621, + 0, 622, 623, 0, 0, 0, 0, 624, 690, 708, + 674, 643, 605, 698, 640, 644, 645, 427, 428, 429, + 430, 711, 0, 0, 0, 596, 456, 457, 0, 398, + 397, 477, 349, 0, 0, 445, 426, 519, 355, 394, + 447, 432, 458, 459, 460, 461, 462, 0, 463, 464, + 404, 339, 340, 788, 387, 500, 713, 750, 751, 635, + 0, 699, 636, 646, 380, 671, 683, 682, 494, 595, + 0, 694, 697, 625, 787, 0, 691, 705, 792, 704, + 784, 506, 0, 538, 702, 649, 0, 695, 668, 669, + 0, 696, 664, 700, 356, 433, 524, 581, 0, 637, + 0, 606, 609, 639, 726, 727, 728, 346, 608, 730, + 731, 732, 733, 734, 735, 736, 729, 577, 672, 648, + 675, 587, 651, 650, 0, 0, 686, 604, 687, 688, + 488, 489, 490, 491, 408, 714, 371, 607, 521, 522, + 0, 673, 0, 0, 0, 0, 0, 0, 0, 0, + 678, 679, 676, 797, 0, 737, 738, 0, 0, 601, + 602, 403, 0, 620, 411, 370, 505, 405, 585, 436, + 0, 613, 680, 614, 525, 526, 741, 746, 742, 743, + 745, 766, 495, 425, 431, 542, 446, 468, 528, 584, + 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 718, 717, 716, 715, 714, - 713, 712, 711, 0, 0, 658, 384, 781, 775, 782, - 763, 766, 765, 740, 0, 341, 638, 464, 518, 401, - 705, 706, 0, 761, 284, 285, 286, 287, 288, 289, + 0, 0, 0, 0, 0, 722, 721, 720, 719, 718, + 717, 716, 715, 0, 0, 662, 385, 785, 779, 786, + 767, 770, 769, 744, 0, 341, 642, 466, 520, 402, + 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, - 303, 304, 305, 306, 307, 308, 309, 310, 708, 301, + 303, 304, 305, 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, - 767, 768, 769, 770, 771, 0, 0, 334, 335, 336, - 0, 0, 299, 300, 327, 549, 328, 329, 330, 331, - 0, 0, 587, 588, 589, 612, 0, 590, 572, 637, - 411, 342, 553, 579, 778, 779, 0, 0, 0, 0, - 0, 0, 0, 688, 699, 735, 736, 0, 749, 750, - 752, 754, 753, 756, 546, 547, 764, 0, 0, 435, - 357, 358, 494, 495, 532, 0, 436, 437, 438, 442, - 439, 440, 441, 758, 759, 760, 757, 468, 531, 554, - 540, 777, 481, 0, 785, 627, 628, 786, 745, 744, - 343, 0, 337, 338, 702, 703, 0, 0, 534, 480, - 634, 500, 0, 0, 643, 677, 666, 755, 630, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 394, - 0, 0, 463, 681, 662, 673, 663, 506, 648, 649, - 650, 657, 406, 651, 787, 653, 622, 654, 623, 655, - 656, 0, 680, 629, 542, 482, 0, 697, 0, 0, + 771, 772, 773, 774, 775, 0, 0, 334, 335, 336, + 0, 0, 299, 300, 327, 552, 328, 329, 330, 331, + 0, 0, 591, 592, 593, 616, 0, 594, 575, 641, + 412, 342, 556, 583, 782, 783, 0, 0, 0, 0, + 0, 0, 0, 692, 703, 739, 740, 0, 753, 754, + 756, 758, 757, 760, 549, 550, 768, 0, 0, 437, + 358, 359, 496, 497, 535, 0, 438, 439, 440, 444, + 441, 442, 443, 762, 763, 764, 761, 470, 534, 557, + 543, 781, 483, 0, 789, 631, 632, 790, 749, 748, + 343, 0, 337, 338, 706, 707, 0, 0, 537, 482, + 638, 502, 0, 0, 647, 681, 670, 759, 634, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 395, + 0, 0, 465, 685, 666, 677, 667, 508, 652, 653, + 654, 661, 407, 655, 791, 657, 626, 658, 627, 659, + 660, 0, 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, - 0, 0, 4035, 0, 0, 0, 365, 269, 624, 751, - 626, 625, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 368, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 543, 571, 0, 584, 0, 432, 433, 0, - 0, 0, 0, 0, 0, 0, 350, 550, 568, 366, - 537, 582, 371, 545, 561, 361, 499, 533, 0, 0, - 352, 566, 544, 477, 351, 0, 526, 391, 408, 388, - 497, 0, 0, 565, 595, 387, 585, 0, 576, 354, - 0, 575, 496, 469, 562, 567, 478, 471, 0, 353, - 564, 476, 470, 446, 398, 611, 447, 448, 449, 450, - 451, 452, 412, 512, 467, 513, 413, 484, 483, 485, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 0, 0, 0, 0, 0, 606, 607, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 743, 0, 0, 748, 0, 578, 0, 0, - 0, 0, 0, 0, 548, 0, 0, 453, 0, 0, - 0, 596, 0, 529, 502, 789, 0, 0, 527, 465, - 563, 514, 569, 551, 577, 521, 515, 344, 552, 390, - 479, 362, 364, 776, 392, 395, 399, 400, 490, 491, - 508, 536, 555, 556, 557, 389, 376, 528, 377, 409, - 378, 345, 381, 380, 382, 538, 383, 347, 509, 560, - 0, 405, 524, 474, 348, 473, 510, 559, 558, 363, - 586, 593, 594, 685, 0, 599, 790, 791, 792, 608, - 0, 516, 359, 356, 0, 0, 0, 385, 511, 372, - 374, 375, 373, 505, 507, 613, 614, 615, 617, 0, - 618, 619, 0, 0, 0, 0, 620, 686, 704, 670, - 639, 601, 694, 636, 640, 641, 426, 427, 428, 429, - 707, 0, 0, 0, 592, 454, 455, 0, 397, 396, - 475, 349, 0, 0, 443, 425, 517, 355, 393, 445, - 431, 456, 457, 458, 459, 460, 0, 461, 462, 403, - 339, 340, 784, 386, 498, 709, 746, 747, 631, 0, - 695, 632, 642, 379, 667, 679, 678, 492, 591, 0, - 690, 693, 621, 783, 0, 687, 701, 788, 700, 780, - 504, 0, 535, 698, 645, 0, 691, 664, 665, 0, - 692, 660, 696, 0, 633, 0, 602, 605, 635, 722, - 723, 724, 346, 604, 726, 727, 728, 729, 730, 731, - 732, 725, 574, 668, 644, 671, 583, 647, 646, 0, - 0, 682, 600, 683, 684, 486, 487, 488, 489, 407, - 710, 370, 603, 519, 520, 0, 669, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 675, 672, 793, 0, - 733, 734, 0, 0, 597, 598, 402, 0, 616, 410, - 369, 503, 404, 581, 434, 0, 609, 676, 610, 522, - 523, 737, 742, 738, 739, 741, 762, 493, 424, 430, - 539, 444, 466, 525, 580, 501, 530, 367, 570, 541, - 472, 661, 689, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 366, 269, 628, 755, + 630, 629, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 369, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3839, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 546, 574, 0, 588, 0, 434, 435, 0, + 0, 0, 0, 0, 0, 0, 350, 553, 571, 367, + 540, 586, 372, 548, 564, 362, 501, 536, 0, 0, + 352, 569, 547, 479, 351, 0, 529, 392, 409, 389, + 499, 0, 0, 568, 599, 388, 589, 0, 579, 354, + 0, 578, 498, 471, 565, 570, 480, 473, 0, 353, + 567, 478, 472, 448, 399, 615, 449, 450, 451, 452, + 453, 454, 413, 514, 469, 515, 414, 486, 485, 487, + 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, + 0, 0, 0, 0, 0, 610, 611, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 747, 0, 0, 752, 0, 582, 0, 0, + 0, 0, 0, 0, 551, 0, 0, 455, 0, 0, + 0, 600, 0, 532, 504, 793, 0, 0, 530, 467, + 566, 516, 572, 554, 580, 523, 517, 344, 555, 391, + 481, 363, 365, 780, 393, 396, 400, 401, 492, 493, + 510, 539, 558, 559, 560, 390, 377, 531, 378, 410, + 379, 345, 382, 381, 383, 541, 384, 347, 511, 563, + 0, 406, 527, 476, 348, 475, 512, 562, 561, 364, + 590, 597, 598, 689, 0, 603, 794, 795, 796, 612, + 0, 518, 360, 357, 0, 0, 0, 386, 513, 373, + 375, 376, 374, 507, 509, 617, 618, 619, 621, 0, + 622, 623, 0, 0, 0, 0, 624, 690, 708, 674, + 643, 605, 698, 640, 644, 645, 427, 428, 429, 430, + 711, 0, 0, 0, 596, 456, 457, 0, 398, 397, + 477, 349, 0, 0, 445, 426, 519, 355, 394, 447, + 432, 458, 459, 460, 461, 462, 0, 463, 464, 404, + 339, 340, 788, 387, 500, 713, 750, 751, 635, 0, + 699, 636, 646, 380, 671, 683, 682, 494, 595, 0, + 694, 697, 625, 787, 0, 691, 705, 792, 704, 784, + 506, 0, 538, 702, 649, 0, 695, 668, 669, 0, + 696, 664, 700, 356, 433, 524, 581, 0, 637, 0, + 606, 609, 639, 726, 727, 728, 346, 608, 730, 731, + 732, 733, 734, 735, 736, 729, 577, 672, 648, 675, + 587, 651, 650, 0, 0, 686, 604, 687, 688, 488, + 489, 490, 491, 408, 714, 371, 607, 521, 522, 0, + 673, 0, 0, 0, 0, 0, 0, 0, 0, 678, + 679, 676, 797, 0, 737, 738, 0, 0, 601, 602, + 403, 0, 620, 411, 370, 505, 405, 585, 436, 0, + 613, 680, 614, 525, 526, 741, 746, 742, 743, 745, + 766, 495, 425, 431, 542, 446, 468, 528, 584, 503, + 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 718, 717, 716, 715, 714, 713, 712, 711, 0, 0, - 658, 384, 781, 775, 782, 763, 766, 765, 740, 0, - 341, 638, 464, 518, 401, 705, 706, 0, 761, 284, - 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, - 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, - 308, 309, 310, 708, 301, 302, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 0, 0, 0, 0, 333, 767, 768, 769, 770, 771, - 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, - 549, 328, 329, 330, 331, 0, 0, 587, 588, 589, - 612, 0, 590, 572, 637, 411, 342, 553, 579, 778, - 779, 0, 0, 0, 0, 0, 0, 0, 688, 699, - 735, 736, 0, 749, 750, 752, 754, 753, 756, 546, - 547, 764, 0, 0, 435, 357, 358, 494, 495, 532, - 0, 436, 437, 438, 442, 439, 440, 441, 758, 759, - 760, 757, 468, 531, 554, 540, 777, 481, 0, 785, - 627, 628, 786, 745, 744, 343, 0, 337, 338, 702, - 703, 3964, 0, 534, 480, 634, 0, 500, 0, 0, - 643, 677, 666, 755, 630, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 394, 0, 0, 463, 681, - 662, 673, 663, 506, 648, 649, 650, 657, 406, 651, - 787, 653, 622, 654, 623, 655, 656, 0, 680, 629, - 542, 482, 0, 697, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 722, 721, 720, 719, 718, 717, + 716, 715, 0, 0, 662, 385, 785, 779, 786, 767, + 770, 769, 744, 0, 341, 642, 466, 520, 402, 709, + 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, + 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, + 304, 305, 306, 307, 308, 309, 310, 712, 301, 302, + 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 0, 0, 0, 0, 333, 771, + 772, 773, 774, 775, 0, 0, 334, 335, 336, 0, + 0, 299, 300, 327, 552, 328, 329, 330, 331, 0, + 0, 591, 592, 593, 616, 0, 594, 575, 641, 412, + 342, 556, 583, 782, 783, 0, 0, 0, 0, 0, + 0, 0, 692, 703, 739, 740, 0, 753, 754, 756, + 758, 757, 760, 549, 550, 768, 0, 0, 437, 358, + 359, 496, 497, 535, 0, 438, 439, 440, 444, 441, + 442, 443, 762, 763, 764, 761, 470, 534, 557, 543, + 781, 483, 0, 789, 631, 632, 790, 749, 748, 343, + 0, 337, 338, 706, 707, 0, 0, 537, 482, 638, + 502, 0, 0, 647, 681, 670, 759, 634, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 395, 0, + 0, 465, 685, 666, 677, 667, 508, 652, 653, 654, + 661, 407, 655, 791, 657, 626, 658, 627, 659, 660, + 0, 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 268, 0, 0, 0, 0, - 0, 0, 365, 269, 624, 751, 626, 625, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 368, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 543, 571, - 0, 584, 0, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 350, 550, 568, 366, 537, 582, 371, 545, - 561, 361, 499, 533, 0, 0, 352, 566, 544, 477, - 351, 0, 526, 391, 408, 388, 497, 0, 0, 565, - 595, 387, 585, 0, 576, 354, 0, 575, 496, 469, - 562, 567, 478, 471, 0, 353, 564, 476, 470, 446, - 398, 611, 447, 448, 449, 450, 451, 452, 412, 512, - 467, 513, 413, 484, 483, 485, 414, 415, 416, 417, - 418, 419, 420, 421, 422, 423, 0, 0, 0, 0, - 0, 606, 607, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 743, 0, - 0, 748, 0, 578, 0, 0, 0, 0, 0, 0, - 548, 0, 0, 453, 0, 0, 0, 596, 0, 529, - 502, 789, 0, 0, 527, 465, 563, 514, 569, 551, - 577, 521, 515, 344, 552, 390, 479, 362, 364, 776, - 392, 395, 399, 400, 490, 491, 508, 536, 555, 556, - 557, 389, 376, 528, 377, 409, 378, 345, 381, 380, - 382, 538, 383, 347, 509, 560, 0, 405, 524, 474, - 348, 473, 510, 559, 558, 363, 586, 593, 594, 685, - 0, 599, 790, 791, 792, 608, 0, 516, 359, 356, - 0, 0, 0, 385, 511, 372, 374, 375, 373, 505, - 507, 613, 614, 615, 617, 0, 618, 619, 0, 0, - 0, 0, 620, 686, 704, 670, 639, 601, 694, 636, - 640, 641, 426, 427, 428, 429, 707, 0, 0, 0, - 592, 454, 455, 0, 397, 396, 475, 349, 0, 0, - 443, 425, 517, 355, 393, 445, 431, 456, 457, 458, - 459, 460, 0, 461, 462, 403, 339, 340, 784, 386, - 498, 709, 746, 747, 631, 0, 695, 632, 642, 379, - 667, 679, 678, 492, 591, 0, 690, 693, 621, 783, - 0, 687, 701, 788, 700, 780, 504, 0, 535, 698, - 645, 0, 691, 664, 665, 0, 692, 660, 696, 0, - 633, 0, 602, 605, 635, 722, 723, 724, 346, 604, - 726, 727, 728, 729, 730, 731, 732, 725, 574, 668, - 644, 671, 583, 647, 646, 0, 0, 682, 600, 683, - 684, 486, 487, 488, 489, 407, 710, 370, 603, 519, - 520, 0, 669, 0, 0, 0, 0, 0, 0, 0, - 0, 674, 675, 672, 793, 0, 733, 734, 0, 0, - 597, 598, 402, 0, 616, 410, 369, 503, 404, 581, - 434, 0, 609, 676, 610, 522, 523, 737, 742, 738, - 739, 741, 762, 493, 424, 430, 539, 444, 466, 525, - 580, 501, 530, 367, 570, 541, 472, 661, 689, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 268, 0, + 0, 1870, 0, 0, 0, 366, 269, 628, 755, 630, + 629, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 369, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 546, 574, 0, 588, 0, 434, 435, 0, 0, + 0, 0, 0, 0, 0, 350, 553, 571, 367, 540, + 586, 372, 548, 564, 362, 501, 536, 0, 0, 352, + 569, 547, 479, 351, 0, 529, 392, 409, 389, 499, + 0, 0, 568, 599, 388, 589, 0, 579, 354, 0, + 578, 498, 471, 565, 570, 480, 473, 0, 353, 567, + 478, 472, 448, 399, 615, 449, 450, 451, 452, 453, + 454, 413, 514, 469, 515, 414, 486, 485, 487, 415, + 416, 417, 418, 419, 420, 421, 422, 423, 424, 0, + 0, 0, 0, 0, 610, 611, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 747, 0, 0, 752, 0, 582, 0, 0, 0, + 0, 0, 0, 551, 0, 0, 455, 0, 0, 0, + 600, 0, 532, 504, 793, 0, 0, 530, 467, 566, + 516, 572, 554, 580, 523, 517, 344, 555, 391, 481, + 363, 365, 780, 393, 396, 400, 401, 492, 493, 510, + 539, 558, 559, 560, 390, 377, 531, 378, 410, 379, + 345, 382, 381, 383, 541, 384, 347, 511, 563, 0, + 406, 527, 476, 348, 475, 512, 562, 561, 364, 590, + 597, 598, 689, 0, 603, 794, 795, 796, 612, 0, + 518, 360, 357, 0, 0, 0, 386, 513, 373, 375, + 376, 374, 507, 509, 617, 618, 619, 621, 0, 622, + 623, 0, 0, 0, 0, 624, 690, 708, 674, 643, + 605, 698, 640, 644, 645, 427, 428, 429, 430, 711, + 0, 0, 0, 596, 456, 457, 0, 398, 397, 477, + 349, 0, 0, 445, 426, 519, 355, 394, 447, 432, + 458, 459, 460, 461, 462, 0, 463, 464, 404, 339, + 340, 788, 387, 500, 713, 750, 751, 635, 0, 699, + 636, 646, 380, 671, 683, 682, 494, 595, 0, 694, + 697, 625, 787, 0, 691, 705, 792, 704, 784, 506, + 0, 538, 702, 649, 0, 695, 668, 669, 0, 696, + 664, 700, 356, 433, 524, 581, 0, 637, 0, 606, + 609, 639, 726, 727, 728, 346, 608, 730, 731, 732, + 733, 734, 735, 736, 729, 577, 672, 648, 675, 587, + 651, 650, 0, 0, 686, 604, 687, 688, 488, 489, + 490, 491, 408, 714, 371, 607, 521, 522, 0, 673, + 0, 0, 0, 0, 0, 0, 0, 0, 678, 679, + 676, 797, 0, 737, 738, 0, 0, 601, 602, 403, + 0, 620, 411, 370, 505, 405, 585, 436, 0, 613, + 680, 614, 525, 526, 741, 746, 742, 743, 745, 766, + 495, 425, 431, 542, 446, 468, 528, 584, 503, 533, + 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 718, 717, 716, 715, - 714, 713, 712, 711, 0, 0, 658, 384, 781, 775, - 782, 763, 766, 765, 740, 0, 341, 638, 464, 518, - 401, 705, 706, 0, 761, 284, 285, 286, 287, 288, - 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, - 298, 303, 304, 305, 306, 307, 308, 309, 310, 708, - 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, - 333, 767, 768, 769, 770, 771, 0, 0, 334, 335, - 336, 0, 0, 299, 300, 327, 549, 328, 329, 330, - 331, 0, 0, 587, 588, 589, 612, 0, 590, 572, - 637, 411, 342, 553, 579, 778, 779, 0, 0, 0, - 0, 0, 0, 0, 688, 699, 735, 736, 0, 749, - 750, 752, 754, 753, 756, 546, 547, 764, 0, 0, - 435, 357, 358, 494, 495, 532, 0, 436, 437, 438, - 442, 439, 440, 441, 758, 759, 760, 757, 468, 531, - 554, 540, 777, 481, 0, 785, 627, 628, 786, 745, - 744, 343, 0, 337, 338, 702, 703, 0, 0, 534, - 480, 634, 500, 0, 0, 643, 677, 666, 755, 630, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 394, 0, 0, 463, 681, 662, 673, 663, 506, 648, - 649, 650, 657, 406, 651, 787, 653, 622, 654, 623, - 655, 656, 0, 680, 629, 542, 482, 0, 697, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 268, 0, 0, 0, 0, 0, 0, 365, 269, 624, - 751, 626, 625, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 368, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3835, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 543, 571, 0, 584, 0, 432, 433, - 0, 0, 0, 0, 0, 0, 0, 350, 550, 568, - 366, 537, 582, 371, 545, 561, 361, 499, 533, 0, - 0, 352, 566, 544, 477, 351, 0, 526, 391, 408, - 388, 497, 0, 0, 565, 595, 387, 585, 0, 576, - 354, 0, 575, 496, 469, 562, 567, 478, 471, 0, - 353, 564, 476, 470, 446, 398, 611, 447, 448, 449, - 450, 451, 452, 412, 512, 467, 513, 413, 484, 483, - 485, 414, 415, 416, 417, 418, 419, 420, 421, 422, - 423, 0, 0, 0, 0, 0, 606, 607, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 743, 0, 0, 748, 0, 578, 0, - 0, 0, 0, 0, 0, 548, 0, 0, 453, 0, - 0, 0, 596, 0, 529, 502, 789, 0, 0, 527, - 465, 563, 514, 569, 551, 577, 521, 515, 344, 552, - 390, 479, 362, 364, 776, 392, 395, 399, 400, 490, - 491, 508, 536, 555, 556, 557, 389, 376, 528, 377, - 409, 378, 345, 381, 380, 382, 538, 383, 347, 509, - 560, 0, 405, 524, 474, 348, 473, 510, 559, 558, - 363, 586, 593, 594, 685, 0, 599, 790, 791, 792, - 608, 0, 516, 359, 356, 0, 0, 0, 385, 511, - 372, 374, 375, 373, 505, 507, 613, 614, 615, 617, - 0, 618, 619, 0, 0, 0, 0, 620, 686, 704, - 670, 639, 601, 694, 636, 640, 641, 426, 427, 428, - 429, 707, 0, 0, 0, 592, 454, 455, 0, 397, - 396, 475, 349, 0, 0, 443, 425, 517, 355, 393, - 445, 431, 456, 457, 458, 459, 460, 0, 461, 462, - 403, 339, 340, 784, 386, 498, 709, 746, 747, 631, - 0, 695, 632, 642, 379, 667, 679, 678, 492, 591, - 0, 690, 693, 621, 783, 0, 687, 701, 788, 700, - 780, 504, 0, 535, 698, 645, 0, 691, 664, 665, - 0, 692, 660, 696, 0, 633, 0, 602, 605, 635, - 722, 723, 724, 346, 604, 726, 727, 728, 729, 730, - 731, 732, 725, 574, 668, 644, 671, 583, 647, 646, - 0, 0, 682, 600, 683, 684, 486, 487, 488, 489, - 407, 710, 370, 603, 519, 520, 0, 669, 0, 0, - 0, 0, 0, 0, 0, 0, 674, 675, 672, 793, - 0, 733, 734, 0, 0, 597, 598, 402, 0, 616, - 410, 369, 503, 404, 581, 434, 0, 609, 676, 610, - 522, 523, 737, 742, 738, 739, 741, 762, 493, 424, - 430, 539, 444, 466, 525, 580, 501, 530, 367, 570, - 541, 472, 661, 689, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, + 0, 0, 0, 722, 721, 720, 719, 718, 717, 716, + 715, 0, 0, 662, 385, 785, 779, 786, 767, 770, + 769, 744, 0, 341, 642, 466, 520, 402, 709, 710, + 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, + 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, + 305, 306, 307, 308, 309, 310, 712, 301, 302, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 0, 0, 0, 0, 333, 771, 772, + 773, 774, 775, 0, 0, 334, 335, 336, 0, 0, + 299, 300, 327, 552, 328, 329, 330, 331, 0, 0, + 591, 592, 593, 616, 0, 594, 575, 641, 412, 342, + 556, 583, 782, 783, 0, 0, 0, 0, 0, 0, + 0, 692, 703, 739, 740, 0, 753, 754, 756, 758, + 757, 760, 549, 550, 768, 0, 0, 437, 358, 359, + 496, 497, 535, 0, 438, 439, 440, 444, 441, 442, + 443, 762, 763, 764, 761, 470, 534, 557, 543, 781, + 483, 0, 789, 631, 632, 790, 749, 748, 343, 0, + 337, 338, 706, 707, 0, 0, 537, 482, 638, 502, + 0, 0, 647, 681, 670, 759, 634, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 395, 0, 0, + 465, 685, 666, 677, 667, 508, 652, 653, 654, 661, + 407, 655, 791, 657, 626, 658, 627, 659, 660, 0, + 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 268, 0, 0, + 2453, 0, 0, 0, 366, 269, 628, 755, 630, 629, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 369, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 546, 574, 0, 588, 0, 434, 435, 0, 0, 0, + 0, 0, 0, 0, 350, 553, 571, 367, 540, 586, + 372, 548, 564, 362, 501, 536, 0, 0, 352, 569, + 547, 479, 351, 0, 529, 392, 409, 389, 499, 0, + 0, 568, 599, 388, 589, 0, 579, 354, 0, 578, + 498, 471, 565, 570, 480, 473, 0, 353, 567, 478, + 472, 448, 399, 615, 449, 450, 451, 452, 453, 454, + 413, 514, 469, 515, 414, 486, 485, 487, 415, 416, + 417, 418, 419, 420, 421, 422, 423, 424, 0, 0, + 0, 0, 0, 610, 611, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 747, 0, 0, 752, 0, 582, 0, 0, 0, 0, + 0, 0, 551, 0, 0, 455, 0, 0, 0, 600, + 0, 532, 504, 793, 0, 0, 530, 467, 566, 516, + 572, 554, 580, 523, 517, 344, 555, 391, 481, 363, + 365, 780, 393, 396, 400, 401, 492, 493, 510, 539, + 558, 559, 560, 390, 377, 531, 378, 410, 379, 345, + 382, 381, 383, 541, 384, 347, 511, 563, 0, 406, + 527, 476, 348, 475, 512, 562, 561, 364, 590, 597, + 598, 689, 0, 603, 794, 795, 796, 612, 0, 518, + 360, 357, 0, 0, 0, 386, 513, 373, 375, 376, + 374, 507, 509, 617, 618, 619, 621, 0, 622, 623, + 0, 0, 0, 0, 624, 690, 708, 674, 643, 605, + 698, 640, 644, 645, 427, 428, 429, 430, 711, 0, + 0, 0, 596, 456, 457, 0, 398, 397, 477, 349, + 0, 0, 445, 426, 519, 355, 394, 447, 432, 458, + 459, 460, 461, 462, 0, 463, 464, 404, 339, 340, + 788, 387, 500, 713, 750, 751, 635, 0, 699, 636, + 646, 380, 671, 683, 682, 494, 595, 0, 694, 697, + 625, 787, 0, 691, 705, 792, 704, 784, 506, 0, + 538, 702, 649, 0, 695, 668, 669, 0, 696, 664, + 700, 356, 433, 524, 581, 0, 637, 0, 606, 609, + 639, 726, 727, 728, 346, 608, 730, 731, 732, 733, + 734, 735, 736, 729, 577, 672, 648, 675, 587, 651, + 650, 0, 0, 686, 604, 687, 688, 488, 489, 490, + 491, 408, 714, 371, 607, 521, 522, 0, 673, 0, + 0, 0, 0, 0, 0, 0, 0, 678, 679, 676, + 797, 0, 737, 738, 0, 0, 601, 602, 403, 0, + 620, 411, 370, 505, 405, 585, 436, 0, 613, 680, + 614, 525, 526, 741, 746, 742, 743, 745, 766, 495, + 425, 431, 542, 446, 468, 528, 584, 503, 533, 368, + 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 718, 717, 716, 715, 714, 713, 712, 711, 0, - 0, 658, 384, 781, 775, 782, 763, 766, 765, 740, - 0, 341, 638, 464, 518, 401, 705, 706, 0, 761, - 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, - 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, - 307, 308, 309, 310, 708, 301, 302, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 324, 0, 0, 0, 0, 333, 767, 768, 769, 770, - 771, 0, 0, 334, 335, 336, 0, 0, 299, 300, - 327, 549, 328, 329, 330, 331, 0, 0, 587, 588, - 589, 612, 0, 590, 572, 637, 411, 342, 553, 579, - 778, 779, 0, 0, 0, 0, 0, 0, 0, 688, - 699, 735, 736, 0, 749, 750, 752, 754, 753, 756, - 546, 547, 764, 0, 0, 435, 357, 358, 494, 495, - 532, 0, 436, 437, 438, 442, 439, 440, 441, 758, - 759, 760, 757, 468, 531, 554, 540, 777, 481, 0, - 785, 627, 628, 786, 745, 744, 343, 0, 337, 338, - 702, 703, 0, 0, 534, 480, 634, 500, 0, 0, - 643, 677, 666, 755, 630, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 394, 0, 0, 463, 681, - 662, 673, 663, 506, 648, 649, 650, 657, 406, 651, - 787, 653, 622, 654, 623, 655, 656, 0, 680, 629, - 542, 482, 0, 697, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 268, 0, 0, 1866, 0, - 0, 0, 365, 269, 624, 751, 626, 625, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 368, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 543, 571, - 0, 584, 0, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 350, 550, 568, 366, 537, 582, 371, 545, - 561, 361, 499, 533, 0, 0, 352, 566, 544, 477, - 351, 0, 526, 391, 408, 388, 497, 0, 0, 565, - 595, 387, 585, 0, 576, 354, 0, 575, 496, 469, - 562, 567, 478, 471, 0, 353, 564, 476, 470, 446, - 398, 611, 447, 448, 449, 450, 451, 452, 412, 512, - 467, 513, 413, 484, 483, 485, 414, 415, 416, 417, - 418, 419, 420, 421, 422, 423, 0, 0, 0, 0, - 0, 606, 607, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 743, 0, - 0, 748, 0, 578, 0, 0, 0, 0, 0, 0, - 548, 0, 0, 453, 0, 0, 0, 596, 0, 529, - 502, 789, 0, 0, 527, 465, 563, 514, 569, 551, - 577, 521, 515, 344, 552, 390, 479, 362, 364, 776, - 392, 395, 399, 400, 490, 491, 508, 536, 555, 556, - 557, 389, 376, 528, 377, 409, 378, 345, 381, 380, - 382, 538, 383, 347, 509, 560, 0, 405, 524, 474, - 348, 473, 510, 559, 558, 363, 586, 593, 594, 685, - 0, 599, 790, 791, 792, 608, 0, 516, 359, 356, - 0, 0, 0, 385, 511, 372, 374, 375, 373, 505, - 507, 613, 614, 615, 617, 0, 618, 619, 0, 0, - 0, 0, 620, 686, 704, 670, 639, 601, 694, 636, - 640, 641, 426, 427, 428, 429, 707, 0, 0, 0, - 592, 454, 455, 0, 397, 396, 475, 349, 0, 0, - 443, 425, 517, 355, 393, 445, 431, 456, 457, 458, - 459, 460, 0, 461, 462, 403, 339, 340, 784, 386, - 498, 709, 746, 747, 631, 0, 695, 632, 642, 379, - 667, 679, 678, 492, 591, 0, 690, 693, 621, 783, - 0, 687, 701, 788, 700, 780, 504, 0, 535, 698, - 645, 0, 691, 664, 665, 0, 692, 660, 696, 0, - 633, 0, 602, 605, 635, 722, 723, 724, 346, 604, - 726, 727, 728, 729, 730, 731, 732, 725, 574, 668, - 644, 671, 583, 647, 646, 0, 0, 682, 600, 683, - 684, 486, 487, 488, 489, 407, 710, 370, 603, 519, - 520, 0, 669, 0, 0, 0, 0, 0, 0, 0, - 0, 674, 675, 672, 793, 0, 733, 734, 0, 0, - 597, 598, 402, 0, 616, 410, 369, 503, 404, 581, - 434, 0, 609, 676, 610, 522, 523, 737, 742, 738, - 739, 741, 762, 493, 424, 430, 539, 444, 466, 525, - 580, 501, 530, 367, 570, 541, 472, 661, 689, 0, + 0, 0, 722, 721, 720, 719, 718, 717, 716, 715, + 0, 0, 662, 385, 785, 779, 786, 767, 770, 769, + 744, 0, 341, 642, 466, 520, 402, 709, 710, 0, + 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, + 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, + 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 0, 0, 0, 0, 333, 771, 772, 773, + 774, 775, 0, 0, 334, 335, 336, 0, 0, 299, + 300, 327, 552, 328, 329, 330, 331, 0, 0, 591, + 592, 593, 616, 0, 594, 575, 641, 412, 342, 556, + 583, 782, 783, 0, 0, 0, 0, 0, 0, 0, + 692, 703, 739, 740, 0, 753, 754, 756, 758, 757, + 760, 549, 550, 768, 0, 0, 437, 358, 359, 496, + 497, 535, 0, 438, 439, 440, 444, 441, 442, 443, + 762, 763, 764, 761, 470, 534, 557, 543, 781, 483, + 0, 789, 631, 632, 790, 749, 748, 343, 0, 337, + 338, 706, 707, 0, 0, 537, 482, 638, 502, 0, + 0, 647, 681, 670, 759, 634, 0, 0, 3671, 0, + 0, 0, 0, 0, 0, 0, 395, 0, 0, 465, + 685, 666, 677, 667, 508, 652, 653, 654, 661, 407, + 655, 791, 657, 626, 658, 627, 659, 660, 0, 684, + 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 718, 717, 716, 715, - 714, 713, 712, 711, 0, 0, 658, 384, 781, 775, - 782, 763, 766, 765, 740, 0, 341, 638, 464, 518, - 401, 705, 706, 0, 761, 284, 285, 286, 287, 288, - 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, - 298, 303, 304, 305, 306, 307, 308, 309, 310, 708, - 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, - 333, 767, 768, 769, 770, 771, 0, 0, 334, 335, - 336, 0, 0, 299, 300, 327, 549, 328, 329, 330, - 331, 0, 0, 587, 588, 589, 612, 0, 590, 572, - 637, 411, 342, 553, 579, 778, 779, 0, 0, 0, - 0, 0, 0, 0, 688, 699, 735, 736, 0, 749, - 750, 752, 754, 753, 756, 546, 547, 764, 0, 0, - 435, 357, 358, 494, 495, 532, 0, 436, 437, 438, - 442, 439, 440, 441, 758, 759, 760, 757, 468, 531, - 554, 540, 777, 481, 0, 785, 627, 628, 786, 745, - 744, 343, 0, 337, 338, 702, 703, 0, 0, 534, - 480, 634, 500, 0, 0, 643, 677, 666, 755, 630, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 394, 0, 0, 463, 681, 662, 673, 663, 506, 648, - 649, 650, 657, 406, 651, 787, 653, 622, 654, 623, - 655, 656, 0, 680, 629, 542, 482, 0, 697, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 268, 0, 0, 2449, 0, 0, 0, 365, 269, 624, - 751, 626, 625, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 368, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 543, 571, 0, 584, 0, 432, 433, - 0, 0, 0, 0, 0, 0, 0, 350, 550, 568, - 366, 537, 582, 371, 545, 561, 361, 499, 533, 0, - 0, 352, 566, 544, 477, 351, 0, 526, 391, 408, - 388, 497, 0, 0, 565, 595, 387, 585, 0, 576, - 354, 0, 575, 496, 469, 562, 567, 478, 471, 0, - 353, 564, 476, 470, 446, 398, 611, 447, 448, 449, - 450, 451, 452, 412, 512, 467, 513, 413, 484, 483, - 485, 414, 415, 416, 417, 418, 419, 420, 421, 422, - 423, 0, 0, 0, 0, 0, 606, 607, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 743, 0, 0, 748, 0, 578, 0, - 0, 0, 0, 0, 0, 548, 0, 0, 453, 0, - 0, 0, 596, 0, 529, 502, 789, 0, 0, 527, - 465, 563, 514, 569, 551, 577, 521, 515, 344, 552, - 390, 479, 362, 364, 776, 392, 395, 399, 400, 490, - 491, 508, 536, 555, 556, 557, 389, 376, 528, 377, - 409, 378, 345, 381, 380, 382, 538, 383, 347, 509, - 560, 0, 405, 524, 474, 348, 473, 510, 559, 558, - 363, 586, 593, 594, 685, 0, 599, 790, 791, 792, - 608, 0, 516, 359, 356, 0, 0, 0, 385, 511, - 372, 374, 375, 373, 505, 507, 613, 614, 615, 617, - 0, 618, 619, 0, 0, 0, 0, 620, 686, 704, - 670, 639, 601, 694, 636, 640, 641, 426, 427, 428, - 429, 707, 0, 0, 0, 592, 454, 455, 0, 397, - 396, 475, 349, 0, 0, 443, 425, 517, 355, 393, - 445, 431, 456, 457, 458, 459, 460, 0, 461, 462, - 403, 339, 340, 784, 386, 498, 709, 746, 747, 631, - 0, 695, 632, 642, 379, 667, 679, 678, 492, 591, - 0, 690, 693, 621, 783, 0, 687, 701, 788, 700, - 780, 504, 0, 535, 698, 645, 0, 691, 664, 665, - 0, 692, 660, 696, 0, 633, 0, 602, 605, 635, - 722, 723, 724, 346, 604, 726, 727, 728, 729, 730, - 731, 732, 725, 574, 668, 644, 671, 583, 647, 646, - 0, 0, 682, 600, 683, 684, 486, 487, 488, 489, - 407, 710, 370, 603, 519, 520, 0, 669, 0, 0, - 0, 0, 0, 0, 0, 0, 674, 675, 672, 793, - 0, 733, 734, 0, 0, 597, 598, 402, 0, 616, - 410, 369, 503, 404, 581, 434, 0, 609, 676, 610, - 522, 523, 737, 742, 738, 739, 741, 762, 493, 424, - 430, 539, 444, 466, 525, 580, 501, 530, 367, 570, - 541, 472, 661, 689, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 268, 0, 0, 0, + 0, 0, 0, 366, 269, 628, 755, 630, 629, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 369, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 546, + 574, 0, 588, 0, 434, 435, 0, 0, 0, 0, + 0, 0, 0, 350, 553, 571, 367, 540, 586, 372, + 548, 564, 362, 501, 536, 0, 0, 352, 569, 547, + 479, 351, 0, 529, 392, 409, 389, 499, 0, 0, + 568, 599, 388, 589, 0, 579, 354, 0, 578, 498, + 471, 565, 570, 480, 473, 0, 353, 567, 478, 472, + 448, 399, 615, 449, 450, 451, 452, 453, 454, 413, + 514, 469, 515, 414, 486, 485, 487, 415, 416, 417, + 418, 419, 420, 421, 422, 423, 424, 0, 0, 0, + 0, 0, 610, 611, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 747, + 0, 0, 752, 0, 582, 0, 0, 0, 0, 0, + 0, 551, 0, 0, 455, 0, 0, 0, 600, 0, + 532, 504, 793, 0, 0, 530, 467, 566, 516, 572, + 554, 580, 523, 517, 344, 555, 391, 481, 363, 365, + 780, 393, 396, 400, 401, 492, 493, 510, 539, 558, + 559, 560, 390, 377, 531, 378, 410, 379, 345, 382, + 381, 383, 541, 384, 347, 511, 563, 0, 406, 527, + 476, 348, 475, 512, 562, 561, 364, 590, 597, 598, + 689, 0, 603, 794, 795, 796, 612, 0, 518, 360, + 357, 0, 0, 0, 386, 513, 373, 375, 376, 374, + 507, 509, 617, 618, 619, 621, 0, 622, 623, 0, + 0, 0, 0, 624, 690, 708, 674, 643, 605, 698, + 640, 644, 645, 427, 428, 429, 430, 711, 0, 0, + 0, 596, 456, 457, 0, 398, 397, 477, 349, 0, + 0, 445, 426, 519, 355, 394, 447, 432, 458, 459, + 460, 461, 462, 0, 463, 464, 404, 339, 340, 788, + 387, 500, 713, 750, 751, 635, 0, 699, 636, 646, + 380, 671, 683, 682, 494, 595, 0, 694, 697, 625, + 787, 0, 691, 705, 792, 704, 784, 506, 0, 538, + 702, 649, 0, 695, 668, 669, 0, 696, 664, 700, + 356, 433, 524, 581, 0, 637, 0, 606, 609, 639, + 726, 727, 728, 346, 608, 730, 731, 732, 733, 734, + 735, 736, 729, 577, 672, 648, 675, 587, 651, 650, + 0, 0, 686, 604, 687, 688, 488, 489, 490, 491, + 408, 714, 371, 607, 521, 522, 0, 673, 0, 0, + 0, 0, 0, 0, 0, 0, 678, 679, 676, 797, + 0, 737, 738, 0, 0, 601, 602, 403, 0, 620, + 411, 370, 505, 405, 585, 436, 0, 613, 680, 614, + 525, 526, 741, 746, 742, 743, 745, 766, 495, 425, + 431, 542, 446, 468, 528, 584, 503, 533, 368, 573, + 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 718, 717, 716, 715, 714, 713, 712, 711, 0, - 0, 658, 384, 781, 775, 782, 763, 766, 765, 740, - 0, 341, 638, 464, 518, 401, 705, 706, 0, 761, + 0, 722, 721, 720, 719, 718, 717, 716, 715, 0, + 0, 662, 385, 785, 779, 786, 767, 770, 769, 744, + 0, 341, 642, 466, 520, 402, 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, - 307, 308, 309, 310, 708, 301, 302, 311, 312, 313, + 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 324, 0, 0, 0, 0, 333, 767, 768, 769, 770, - 771, 0, 0, 334, 335, 336, 0, 0, 299, 300, - 327, 549, 328, 329, 330, 331, 0, 0, 587, 588, - 589, 612, 0, 590, 572, 637, 411, 342, 553, 579, - 778, 779, 0, 0, 0, 0, 0, 0, 0, 688, - 699, 735, 736, 0, 749, 750, 752, 754, 753, 756, - 546, 547, 764, 0, 0, 435, 357, 358, 494, 495, - 532, 0, 436, 437, 438, 442, 439, 440, 441, 758, - 759, 760, 757, 468, 531, 554, 540, 777, 481, 0, - 785, 627, 628, 786, 745, 744, 343, 0, 337, 338, - 702, 703, 0, 0, 534, 480, 634, 500, 0, 0, - 643, 677, 666, 755, 630, 0, 0, 3667, 0, 0, - 0, 0, 0, 0, 0, 394, 0, 0, 463, 681, - 662, 673, 663, 506, 648, 649, 650, 657, 406, 651, - 787, 653, 622, 654, 623, 655, 656, 0, 680, 629, - 542, 482, 0, 697, 0, 0, 0, 0, 0, 0, + 324, 0, 0, 0, 0, 333, 771, 772, 773, 774, + 775, 0, 0, 334, 335, 336, 0, 0, 299, 300, + 327, 552, 328, 329, 330, 331, 0, 0, 591, 592, + 593, 616, 0, 594, 575, 641, 412, 342, 556, 583, + 782, 783, 0, 0, 0, 0, 0, 0, 0, 692, + 703, 739, 740, 0, 753, 754, 756, 758, 757, 760, + 549, 550, 768, 0, 0, 437, 358, 359, 496, 497, + 535, 0, 438, 439, 440, 444, 441, 442, 443, 762, + 763, 764, 761, 470, 534, 557, 543, 781, 483, 0, + 789, 631, 632, 790, 749, 748, 343, 0, 337, 338, + 706, 707, 0, 0, 537, 482, 638, 502, 0, 0, + 647, 681, 670, 759, 634, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 395, 0, 0, 465, 685, + 666, 677, 667, 508, 652, 653, 654, 661, 407, 655, + 791, 657, 626, 658, 627, 659, 660, 0, 684, 633, + 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1816, 0, 0, 268, 0, 0, 0, 0, + 0, 0, 366, 269, 628, 755, 630, 629, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 369, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 546, 574, + 0, 588, 0, 434, 435, 0, 0, 0, 0, 0, + 0, 0, 350, 553, 571, 367, 540, 586, 372, 548, + 564, 362, 501, 536, 0, 0, 352, 569, 547, 479, + 351, 0, 529, 392, 409, 389, 499, 0, 0, 568, + 599, 388, 589, 0, 579, 354, 0, 578, 498, 471, + 565, 570, 480, 473, 0, 353, 567, 478, 472, 448, + 399, 615, 449, 450, 451, 452, 453, 454, 413, 514, + 469, 515, 414, 486, 485, 487, 415, 416, 417, 418, + 419, 420, 421, 422, 423, 424, 0, 0, 0, 0, + 0, 610, 611, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 747, 0, + 0, 752, 0, 582, 0, 0, 0, 0, 0, 0, + 551, 0, 0, 455, 0, 0, 0, 600, 0, 532, + 504, 793, 0, 0, 530, 467, 566, 516, 572, 554, + 580, 523, 517, 344, 555, 391, 481, 363, 365, 780, + 393, 396, 400, 401, 492, 493, 510, 539, 558, 559, + 560, 390, 377, 531, 378, 410, 379, 345, 382, 381, + 383, 541, 384, 347, 511, 563, 0, 406, 527, 476, + 348, 475, 512, 562, 561, 364, 590, 597, 598, 689, + 0, 603, 794, 795, 796, 612, 0, 518, 360, 357, + 0, 0, 0, 386, 513, 373, 375, 376, 374, 507, + 509, 617, 618, 619, 621, 0, 622, 623, 0, 0, + 0, 0, 624, 690, 708, 674, 643, 605, 698, 640, + 644, 645, 427, 428, 429, 430, 711, 0, 0, 0, + 596, 456, 457, 0, 398, 397, 477, 349, 0, 0, + 445, 426, 519, 355, 394, 447, 432, 458, 459, 460, + 461, 462, 0, 463, 464, 404, 339, 340, 788, 387, + 500, 713, 750, 751, 635, 0, 699, 636, 646, 380, + 671, 683, 682, 494, 595, 0, 694, 697, 625, 787, + 0, 691, 705, 792, 704, 784, 506, 0, 538, 702, + 649, 0, 695, 668, 669, 0, 696, 664, 700, 356, + 433, 524, 581, 0, 637, 0, 606, 609, 639, 726, + 727, 728, 346, 608, 730, 731, 732, 733, 734, 735, + 736, 729, 577, 672, 648, 675, 587, 651, 650, 0, + 0, 686, 604, 687, 688, 488, 489, 490, 491, 408, + 714, 371, 607, 521, 522, 0, 673, 0, 0, 0, + 0, 0, 0, 0, 0, 678, 679, 676, 797, 0, + 737, 738, 0, 0, 601, 602, 403, 0, 620, 411, + 370, 505, 405, 585, 436, 0, 613, 680, 614, 525, + 526, 741, 746, 742, 743, 745, 766, 495, 425, 431, + 542, 446, 468, 528, 584, 503, 533, 368, 573, 544, + 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 268, 0, 0, 0, 0, - 0, 0, 365, 269, 624, 751, 626, 625, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 368, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 543, 571, - 0, 584, 0, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 350, 550, 568, 366, 537, 582, 371, 545, - 561, 361, 499, 533, 0, 0, 352, 566, 544, 477, - 351, 0, 526, 391, 408, 388, 497, 0, 0, 565, - 595, 387, 585, 0, 576, 354, 0, 575, 496, 469, - 562, 567, 478, 471, 0, 353, 564, 476, 470, 446, - 398, 611, 447, 448, 449, 450, 451, 452, 412, 512, - 467, 513, 413, 484, 483, 485, 414, 415, 416, 417, - 418, 419, 420, 421, 422, 423, 0, 0, 0, 0, - 0, 606, 607, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 743, 0, - 0, 748, 0, 578, 0, 0, 0, 0, 0, 0, - 548, 0, 0, 453, 0, 0, 0, 596, 0, 529, - 502, 789, 0, 0, 527, 465, 563, 514, 569, 551, - 577, 521, 515, 344, 552, 390, 479, 362, 364, 776, - 392, 395, 399, 400, 490, 491, 508, 536, 555, 556, - 557, 389, 376, 528, 377, 409, 378, 345, 381, 380, - 382, 538, 383, 347, 509, 560, 0, 405, 524, 474, - 348, 473, 510, 559, 558, 363, 586, 593, 594, 685, - 0, 599, 790, 791, 792, 608, 0, 516, 359, 356, - 0, 0, 0, 385, 511, 372, 374, 375, 373, 505, - 507, 613, 614, 615, 617, 0, 618, 619, 0, 0, - 0, 0, 620, 686, 704, 670, 639, 601, 694, 636, - 640, 641, 426, 427, 428, 429, 707, 0, 0, 0, - 592, 454, 455, 0, 397, 396, 475, 349, 0, 0, - 443, 425, 517, 355, 393, 445, 431, 456, 457, 458, - 459, 460, 0, 461, 462, 403, 339, 340, 784, 386, - 498, 709, 746, 747, 631, 0, 695, 632, 642, 379, - 667, 679, 678, 492, 591, 0, 690, 693, 621, 783, - 0, 687, 701, 788, 700, 780, 504, 0, 535, 698, - 645, 0, 691, 664, 665, 0, 692, 660, 696, 0, - 633, 0, 602, 605, 635, 722, 723, 724, 346, 604, - 726, 727, 728, 729, 730, 731, 732, 725, 574, 668, - 644, 671, 583, 647, 646, 0, 0, 682, 600, 683, - 684, 486, 487, 488, 489, 407, 710, 370, 603, 519, - 520, 0, 669, 0, 0, 0, 0, 0, 0, 0, - 0, 674, 675, 672, 793, 0, 733, 734, 0, 0, - 597, 598, 402, 0, 616, 410, 369, 503, 404, 581, - 434, 0, 609, 676, 610, 522, 523, 737, 742, 738, - 739, 741, 762, 493, 424, 430, 539, 444, 466, 525, - 580, 501, 530, 367, 570, 541, 472, 661, 689, 0, + 722, 721, 720, 719, 718, 717, 716, 715, 0, 0, + 662, 385, 785, 779, 786, 767, 770, 769, 744, 0, + 341, 642, 466, 520, 402, 709, 710, 0, 765, 284, + 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, + 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, + 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 0, 0, 0, 0, 333, 771, 772, 773, 774, 775, + 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, + 552, 328, 329, 330, 331, 0, 0, 591, 592, 593, + 616, 0, 594, 575, 641, 412, 342, 556, 583, 782, + 783, 0, 0, 0, 0, 0, 0, 0, 692, 703, + 739, 740, 0, 753, 754, 756, 758, 757, 760, 549, + 550, 768, 0, 0, 437, 358, 359, 496, 497, 535, + 0, 438, 439, 440, 444, 441, 442, 443, 762, 763, + 764, 761, 470, 534, 557, 543, 781, 483, 0, 789, + 631, 632, 790, 749, 748, 343, 0, 337, 338, 706, + 707, 0, 0, 537, 482, 638, 502, 0, 0, 647, + 681, 670, 759, 634, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 395, 0, 0, 465, 685, 666, + 677, 667, 508, 652, 653, 654, 661, 407, 655, 791, + 657, 626, 658, 627, 659, 660, 0, 684, 633, 545, + 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 268, 0, 0, 3542, 0, 0, + 0, 366, 269, 628, 755, 630, 629, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 369, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 546, 574, 0, + 588, 0, 434, 435, 0, 0, 0, 0, 0, 0, + 0, 350, 553, 571, 367, 540, 586, 372, 548, 564, + 362, 501, 536, 0, 0, 352, 569, 547, 479, 351, + 0, 529, 392, 409, 389, 499, 0, 0, 568, 599, + 388, 589, 0, 579, 354, 0, 578, 498, 471, 565, + 570, 480, 473, 0, 353, 567, 478, 472, 448, 399, + 615, 449, 450, 451, 452, 453, 454, 413, 514, 469, + 515, 414, 486, 485, 487, 415, 416, 417, 418, 419, + 420, 421, 422, 423, 424, 0, 0, 0, 0, 0, + 610, 611, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 747, 0, 0, + 752, 0, 582, 0, 0, 0, 0, 0, 0, 551, + 0, 0, 455, 0, 0, 0, 600, 0, 532, 504, + 793, 0, 0, 530, 467, 566, 516, 572, 554, 580, + 523, 517, 344, 555, 391, 481, 363, 365, 780, 393, + 396, 400, 401, 492, 493, 510, 539, 558, 559, 560, + 390, 377, 531, 378, 410, 379, 345, 382, 381, 383, + 541, 384, 347, 511, 563, 0, 406, 527, 476, 348, + 475, 512, 562, 561, 364, 590, 597, 598, 689, 0, + 603, 794, 795, 796, 612, 0, 518, 360, 357, 0, + 0, 0, 386, 513, 373, 375, 376, 374, 507, 509, + 617, 618, 619, 621, 0, 622, 623, 0, 0, 0, + 0, 624, 690, 708, 674, 643, 605, 698, 640, 644, + 645, 427, 428, 429, 430, 711, 0, 0, 0, 596, + 456, 457, 0, 398, 397, 477, 349, 0, 0, 445, + 426, 519, 355, 394, 447, 432, 458, 459, 460, 461, + 462, 0, 463, 464, 404, 339, 340, 788, 387, 500, + 713, 750, 751, 635, 0, 699, 636, 646, 380, 671, + 683, 682, 494, 595, 0, 694, 697, 625, 787, 0, + 691, 705, 792, 704, 784, 506, 0, 538, 702, 649, + 0, 695, 668, 669, 0, 696, 664, 700, 356, 433, + 524, 581, 0, 637, 0, 606, 609, 639, 726, 727, + 728, 346, 608, 730, 731, 732, 733, 734, 735, 736, + 729, 577, 672, 648, 675, 587, 651, 650, 0, 0, + 686, 604, 687, 688, 488, 489, 490, 491, 408, 714, + 371, 607, 521, 522, 0, 673, 0, 0, 0, 0, + 0, 0, 0, 0, 678, 679, 676, 797, 0, 737, + 738, 0, 0, 601, 602, 403, 0, 620, 411, 370, + 505, 405, 585, 436, 0, 613, 680, 614, 525, 526, + 741, 746, 742, 743, 745, 766, 495, 425, 431, 542, + 446, 468, 528, 584, 503, 533, 368, 573, 544, 474, + 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 722, + 721, 720, 719, 718, 717, 716, 715, 0, 0, 662, + 385, 785, 779, 786, 767, 770, 769, 744, 0, 341, + 642, 466, 520, 402, 709, 710, 0, 765, 284, 285, + 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, + 295, 296, 297, 298, 303, 304, 305, 306, 307, 308, + 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, + 0, 0, 0, 333, 771, 772, 773, 774, 775, 0, + 0, 334, 335, 336, 0, 0, 299, 300, 327, 552, + 328, 329, 330, 331, 0, 0, 591, 592, 593, 616, + 0, 594, 575, 641, 412, 342, 556, 583, 782, 783, + 0, 0, 0, 0, 0, 0, 0, 692, 703, 739, + 740, 0, 753, 754, 756, 758, 757, 760, 549, 550, + 768, 0, 0, 437, 358, 359, 496, 497, 535, 0, + 438, 439, 440, 444, 441, 442, 443, 762, 763, 764, + 761, 470, 534, 557, 543, 781, 483, 0, 789, 631, + 632, 790, 749, 748, 343, 0, 337, 338, 706, 707, + 0, 0, 537, 482, 638, 502, 0, 0, 647, 681, + 670, 759, 634, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 395, 0, 0, 465, 685, 666, 677, + 667, 508, 652, 653, 654, 661, 407, 655, 791, 657, + 626, 658, 627, 659, 660, 0, 684, 633, 545, 484, + 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 718, 717, 716, 715, - 714, 713, 712, 711, 0, 0, 658, 384, 781, 775, - 782, 763, 766, 765, 740, 0, 341, 638, 464, 518, - 401, 705, 706, 0, 761, 284, 285, 286, 287, 288, - 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, - 298, 303, 304, 305, 306, 307, 308, 309, 310, 708, - 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, - 333, 767, 768, 769, 770, 771, 0, 0, 334, 335, - 336, 0, 0, 299, 300, 327, 549, 328, 329, 330, - 331, 0, 0, 587, 588, 589, 612, 0, 590, 572, - 637, 411, 342, 553, 579, 778, 779, 0, 0, 0, - 0, 0, 0, 0, 688, 699, 735, 736, 0, 749, - 750, 752, 754, 753, 756, 546, 547, 764, 0, 0, - 435, 357, 358, 494, 495, 532, 0, 436, 437, 438, - 442, 439, 440, 441, 758, 759, 760, 757, 468, 531, - 554, 540, 777, 481, 0, 785, 627, 628, 786, 745, - 744, 343, 0, 337, 338, 702, 703, 0, 0, 534, - 480, 634, 500, 0, 0, 643, 677, 666, 755, 630, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 394, 0, 0, 463, 681, 662, 673, 663, 506, 648, - 649, 650, 657, 406, 651, 787, 653, 622, 654, 623, - 655, 656, 0, 680, 629, 542, 482, 0, 697, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1812, 0, 0, - 268, 0, 0, 0, 0, 0, 0, 365, 269, 624, - 751, 626, 625, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 368, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 543, 571, 0, 584, 0, 432, 433, - 0, 0, 0, 0, 0, 0, 0, 350, 550, 568, - 366, 537, 582, 371, 545, 561, 361, 499, 533, 0, - 0, 352, 566, 544, 477, 351, 0, 526, 391, 408, - 388, 497, 0, 0, 565, 595, 387, 585, 0, 576, - 354, 0, 575, 496, 469, 562, 567, 478, 471, 0, - 353, 564, 476, 470, 446, 398, 611, 447, 448, 449, - 450, 451, 452, 412, 512, 467, 513, 413, 484, 483, - 485, 414, 415, 416, 417, 418, 419, 420, 421, 422, - 423, 0, 0, 0, 0, 0, 606, 607, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 743, 0, 0, 748, 0, 578, 0, - 0, 0, 0, 0, 0, 548, 0, 0, 453, 0, - 0, 0, 596, 0, 529, 502, 789, 0, 0, 527, - 465, 563, 514, 569, 551, 577, 521, 515, 344, 552, - 390, 479, 362, 364, 776, 392, 395, 399, 400, 490, - 491, 508, 536, 555, 556, 557, 389, 376, 528, 377, - 409, 378, 345, 381, 380, 382, 538, 383, 347, 509, - 560, 0, 405, 524, 474, 348, 473, 510, 559, 558, - 363, 586, 593, 594, 685, 0, 599, 790, 791, 792, - 608, 0, 516, 359, 356, 0, 0, 0, 385, 511, - 372, 374, 375, 373, 505, 507, 613, 614, 615, 617, - 0, 618, 619, 0, 0, 0, 0, 620, 686, 704, - 670, 639, 601, 694, 636, 640, 641, 426, 427, 428, - 429, 707, 0, 0, 0, 592, 454, 455, 0, 397, - 396, 475, 349, 0, 0, 443, 425, 517, 355, 393, - 445, 431, 456, 457, 458, 459, 460, 0, 461, 462, - 403, 339, 340, 784, 386, 498, 709, 746, 747, 631, - 0, 695, 632, 642, 379, 667, 679, 678, 492, 591, - 0, 690, 693, 621, 783, 0, 687, 701, 788, 700, - 780, 504, 0, 535, 698, 645, 0, 691, 664, 665, - 0, 692, 660, 696, 0, 633, 0, 602, 605, 635, - 722, 723, 724, 346, 604, 726, 727, 728, 729, 730, - 731, 732, 725, 574, 668, 644, 671, 583, 647, 646, - 0, 0, 682, 600, 683, 684, 486, 487, 488, 489, - 407, 710, 370, 603, 519, 520, 0, 669, 0, 0, - 0, 0, 0, 0, 0, 0, 674, 675, 672, 793, - 0, 733, 734, 0, 0, 597, 598, 402, 0, 616, - 410, 369, 503, 404, 581, 434, 0, 609, 676, 610, - 522, 523, 737, 742, 738, 739, 741, 762, 493, 424, - 430, 539, 444, 466, 525, 580, 501, 530, 367, 570, - 541, 472, 661, 689, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, + 0, 0, 0, 268, 0, 0, 0, 0, 0, 0, + 366, 269, 628, 755, 630, 629, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 369, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3523, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 546, 574, 0, 588, + 0, 434, 435, 0, 0, 0, 0, 0, 0, 0, + 350, 553, 571, 367, 540, 586, 372, 548, 564, 362, + 501, 536, 0, 0, 352, 569, 547, 479, 351, 0, + 529, 392, 409, 389, 499, 0, 0, 568, 599, 388, + 589, 0, 579, 354, 0, 578, 498, 471, 565, 570, + 480, 473, 0, 353, 567, 478, 472, 448, 399, 615, + 449, 450, 451, 452, 453, 454, 413, 514, 469, 515, + 414, 486, 485, 487, 415, 416, 417, 418, 419, 420, + 421, 422, 423, 424, 0, 0, 0, 0, 0, 610, + 611, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 747, 0, 0, 752, + 0, 582, 0, 0, 0, 0, 0, 0, 551, 0, + 0, 455, 0, 0, 0, 600, 0, 532, 504, 793, + 0, 0, 530, 467, 566, 516, 572, 554, 580, 523, + 517, 344, 555, 391, 481, 363, 365, 780, 393, 396, + 400, 401, 492, 493, 510, 539, 558, 559, 560, 390, + 377, 531, 378, 410, 379, 345, 382, 381, 383, 541, + 384, 347, 511, 563, 0, 406, 527, 476, 348, 475, + 512, 562, 561, 364, 590, 597, 598, 689, 0, 603, + 794, 795, 796, 612, 0, 518, 360, 357, 0, 0, + 0, 386, 513, 373, 375, 376, 374, 507, 509, 617, + 618, 619, 621, 0, 622, 623, 0, 0, 0, 0, + 624, 690, 708, 674, 643, 605, 698, 640, 644, 645, + 427, 428, 429, 430, 711, 0, 0, 0, 596, 456, + 457, 0, 398, 397, 477, 349, 0, 0, 445, 426, + 519, 355, 394, 447, 432, 458, 459, 460, 461, 462, + 0, 463, 464, 404, 339, 340, 788, 387, 500, 713, + 750, 751, 635, 0, 699, 636, 646, 380, 671, 683, + 682, 494, 595, 0, 694, 697, 625, 787, 0, 691, + 705, 792, 704, 784, 506, 0, 538, 702, 649, 0, + 695, 668, 669, 0, 696, 664, 700, 356, 433, 524, + 581, 0, 637, 0, 606, 609, 639, 726, 727, 728, + 346, 608, 730, 731, 732, 733, 734, 735, 736, 729, + 577, 672, 648, 675, 587, 651, 650, 0, 0, 686, + 604, 687, 688, 488, 489, 490, 491, 408, 714, 371, + 607, 521, 522, 0, 673, 0, 0, 0, 0, 0, + 0, 0, 0, 678, 679, 676, 797, 0, 737, 738, + 0, 0, 601, 602, 403, 0, 620, 411, 370, 505, + 405, 585, 436, 0, 613, 680, 614, 525, 526, 741, + 746, 742, 743, 745, 766, 495, 425, 431, 542, 446, + 468, 528, 584, 503, 533, 368, 573, 544, 474, 665, + 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 722, 721, + 720, 719, 718, 717, 716, 715, 0, 0, 662, 385, + 785, 779, 786, 767, 770, 769, 744, 0, 341, 642, + 466, 520, 402, 709, 710, 0, 765, 284, 285, 286, + 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, + 296, 297, 298, 303, 304, 305, 306, 307, 308, 309, + 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 0, 0, + 0, 0, 333, 771, 772, 773, 774, 775, 0, 0, + 334, 335, 336, 0, 0, 299, 300, 327, 552, 328, + 329, 330, 331, 0, 0, 591, 592, 593, 616, 0, + 594, 575, 641, 412, 342, 556, 583, 782, 783, 0, + 0, 0, 0, 0, 0, 0, 692, 703, 739, 740, + 0, 753, 754, 756, 758, 757, 760, 549, 550, 768, + 0, 0, 437, 358, 359, 496, 497, 535, 0, 438, + 439, 440, 444, 441, 442, 443, 762, 763, 764, 761, + 470, 534, 557, 543, 781, 483, 0, 789, 631, 632, + 790, 749, 748, 343, 0, 337, 338, 706, 707, 0, + 0, 537, 482, 638, 502, 0, 0, 647, 681, 670, + 759, 634, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 395, 0, 0, 465, 685, 666, 677, 667, + 508, 652, 653, 654, 661, 407, 655, 791, 657, 626, + 658, 627, 659, 660, 0, 684, 633, 545, 484, 0, + 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 268, 0, 0, 3401, 0, 0, 0, 366, + 269, 628, 755, 630, 629, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 369, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 546, 574, 0, 588, 0, + 434, 435, 0, 0, 0, 0, 0, 0, 0, 350, + 553, 571, 367, 540, 586, 372, 548, 564, 362, 501, + 536, 0, 0, 352, 569, 547, 479, 351, 0, 529, + 392, 409, 389, 499, 0, 0, 568, 599, 388, 589, + 0, 579, 354, 0, 578, 498, 471, 565, 570, 480, + 473, 0, 353, 567, 478, 472, 448, 399, 615, 449, + 450, 451, 452, 453, 454, 413, 514, 469, 515, 414, + 486, 485, 487, 415, 416, 417, 418, 419, 420, 421, + 422, 423, 424, 0, 0, 0, 0, 0, 610, 611, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 747, 0, 0, 752, 0, + 582, 0, 0, 0, 0, 0, 0, 551, 0, 0, + 455, 0, 0, 0, 600, 0, 532, 504, 793, 0, + 0, 530, 467, 566, 516, 572, 554, 580, 523, 517, + 344, 555, 391, 481, 363, 365, 780, 393, 396, 400, + 401, 492, 493, 510, 539, 558, 559, 560, 390, 377, + 531, 378, 410, 379, 345, 382, 381, 383, 541, 384, + 347, 511, 563, 0, 406, 527, 476, 348, 475, 512, + 562, 561, 364, 590, 597, 598, 689, 0, 603, 794, + 795, 796, 612, 0, 518, 360, 357, 0, 0, 0, + 386, 513, 373, 375, 376, 374, 507, 509, 617, 618, + 619, 621, 0, 622, 623, 0, 0, 0, 0, 624, + 690, 708, 674, 643, 605, 698, 640, 644, 645, 427, + 428, 429, 430, 711, 0, 0, 0, 596, 456, 457, + 0, 398, 397, 477, 349, 0, 0, 445, 426, 519, + 355, 394, 447, 432, 458, 459, 460, 461, 462, 0, + 463, 464, 404, 339, 340, 788, 387, 500, 713, 750, + 751, 635, 0, 699, 636, 646, 380, 671, 683, 682, + 494, 595, 0, 694, 697, 625, 787, 0, 691, 705, + 792, 704, 784, 506, 0, 538, 702, 649, 0, 695, + 668, 669, 0, 696, 664, 700, 356, 433, 524, 581, + 0, 637, 0, 606, 609, 639, 726, 727, 728, 346, + 608, 730, 731, 732, 733, 734, 735, 736, 729, 577, + 672, 648, 675, 587, 651, 650, 0, 0, 686, 604, + 687, 688, 488, 489, 490, 491, 408, 714, 371, 607, + 521, 522, 0, 673, 0, 0, 0, 0, 0, 0, + 0, 0, 678, 679, 676, 797, 0, 737, 738, 0, + 0, 601, 602, 403, 0, 620, 411, 370, 505, 405, + 585, 436, 0, 613, 680, 614, 525, 526, 741, 746, + 742, 743, 745, 766, 495, 425, 431, 542, 446, 468, + 528, 584, 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 718, 717, 716, 715, 714, 713, 712, 711, 0, - 0, 658, 384, 781, 775, 782, 763, 766, 765, 740, - 0, 341, 638, 464, 518, 401, 705, 706, 0, 761, - 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, - 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, - 307, 308, 309, 310, 708, 301, 302, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 324, 0, 0, 0, 0, 333, 767, 768, 769, 770, - 771, 0, 0, 334, 335, 336, 0, 0, 299, 300, - 327, 549, 328, 329, 330, 331, 0, 0, 587, 588, - 589, 612, 0, 590, 572, 637, 411, 342, 553, 579, - 778, 779, 0, 0, 0, 0, 0, 0, 0, 688, - 699, 735, 736, 0, 749, 750, 752, 754, 753, 756, - 546, 547, 764, 0, 0, 435, 357, 358, 494, 495, - 532, 0, 436, 437, 438, 442, 439, 440, 441, 758, - 759, 760, 757, 468, 531, 554, 540, 777, 481, 0, - 785, 627, 628, 786, 745, 744, 343, 0, 337, 338, - 702, 703, 0, 0, 534, 480, 634, 500, 0, 0, - 643, 677, 666, 755, 630, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 394, 0, 0, 463, 681, - 662, 673, 663, 506, 648, 649, 650, 657, 406, 651, - 787, 653, 622, 654, 623, 655, 656, 0, 680, 629, - 542, 482, 0, 697, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 268, 0, 0, 3538, 0, - 0, 0, 365, 269, 624, 751, 626, 625, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 368, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 543, 571, - 0, 584, 0, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 350, 550, 568, 366, 537, 582, 371, 545, - 561, 361, 499, 533, 0, 0, 352, 566, 544, 477, - 351, 0, 526, 391, 408, 388, 497, 0, 0, 565, - 595, 387, 585, 0, 576, 354, 0, 575, 496, 469, - 562, 567, 478, 471, 0, 353, 564, 476, 470, 446, - 398, 611, 447, 448, 449, 450, 451, 452, 412, 512, - 467, 513, 413, 484, 483, 485, 414, 415, 416, 417, - 418, 419, 420, 421, 422, 423, 0, 0, 0, 0, - 0, 606, 607, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 743, 0, - 0, 748, 0, 578, 0, 0, 0, 0, 0, 0, - 548, 0, 0, 453, 0, 0, 0, 596, 0, 529, - 502, 789, 0, 0, 527, 465, 563, 514, 569, 551, - 577, 521, 515, 344, 552, 390, 479, 362, 364, 776, - 392, 395, 399, 400, 490, 491, 508, 536, 555, 556, - 557, 389, 376, 528, 377, 409, 378, 345, 381, 380, - 382, 538, 383, 347, 509, 560, 0, 405, 524, 474, - 348, 473, 510, 559, 558, 363, 586, 593, 594, 685, - 0, 599, 790, 791, 792, 608, 0, 516, 359, 356, - 0, 0, 0, 385, 511, 372, 374, 375, 373, 505, - 507, 613, 614, 615, 617, 0, 618, 619, 0, 0, - 0, 0, 620, 686, 704, 670, 639, 601, 694, 636, - 640, 641, 426, 427, 428, 429, 707, 0, 0, 0, - 592, 454, 455, 0, 397, 396, 475, 349, 0, 0, - 443, 425, 517, 355, 393, 445, 431, 456, 457, 458, - 459, 460, 0, 461, 462, 403, 339, 340, 784, 386, - 498, 709, 746, 747, 631, 0, 695, 632, 642, 379, - 667, 679, 678, 492, 591, 0, 690, 693, 621, 783, - 0, 687, 701, 788, 700, 780, 504, 0, 535, 698, - 645, 0, 691, 664, 665, 0, 692, 660, 696, 0, - 633, 0, 602, 605, 635, 722, 723, 724, 346, 604, - 726, 727, 728, 729, 730, 731, 732, 725, 574, 668, - 644, 671, 583, 647, 646, 0, 0, 682, 600, 683, - 684, 486, 487, 488, 489, 407, 710, 370, 603, 519, - 520, 0, 669, 0, 0, 0, 0, 0, 0, 0, - 0, 674, 675, 672, 793, 0, 733, 734, 0, 0, - 597, 598, 402, 0, 616, 410, 369, 503, 404, 581, - 434, 0, 609, 676, 610, 522, 523, 737, 742, 738, - 739, 741, 762, 493, 424, 430, 539, 444, 466, 525, - 580, 501, 530, 367, 570, 541, 472, 661, 689, 0, + 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 722, 721, 720, + 719, 718, 717, 716, 715, 0, 0, 662, 385, 785, + 779, 786, 767, 770, 769, 744, 0, 341, 642, 466, + 520, 402, 709, 710, 0, 765, 284, 285, 286, 287, + 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, + 297, 298, 303, 304, 305, 306, 307, 308, 309, 310, + 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 0, 0, 0, + 0, 333, 771, 772, 773, 774, 775, 0, 0, 334, + 335, 336, 0, 0, 299, 300, 327, 552, 328, 329, + 330, 331, 0, 0, 591, 592, 593, 616, 0, 594, + 575, 641, 412, 342, 556, 583, 782, 783, 0, 0, + 0, 0, 0, 0, 0, 692, 703, 739, 740, 0, + 753, 754, 756, 758, 757, 760, 549, 550, 768, 0, + 0, 437, 358, 359, 496, 497, 535, 0, 438, 439, + 440, 444, 441, 442, 443, 762, 763, 764, 761, 470, + 534, 557, 543, 781, 483, 0, 789, 631, 632, 790, + 749, 748, 343, 0, 337, 338, 706, 707, 0, 0, + 537, 482, 638, 502, 0, 0, 647, 681, 670, 759, + 634, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 395, 0, 0, 465, 685, 666, 677, 667, 508, + 652, 653, 654, 661, 407, 655, 791, 657, 626, 658, + 627, 659, 660, 0, 684, 633, 545, 484, 0, 701, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3367, 0, + 0, 268, 0, 0, 0, 0, 0, 0, 366, 269, + 628, 755, 630, 629, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 369, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 546, 574, 0, 588, 0, 434, + 435, 0, 0, 0, 0, 0, 0, 0, 350, 553, + 571, 367, 540, 586, 372, 548, 564, 362, 501, 536, + 0, 0, 352, 569, 547, 479, 351, 0, 529, 392, + 409, 389, 499, 0, 0, 568, 599, 388, 589, 0, + 579, 354, 0, 578, 498, 471, 565, 570, 480, 473, + 0, 353, 567, 478, 472, 448, 399, 615, 449, 450, + 451, 452, 453, 454, 413, 514, 469, 515, 414, 486, + 485, 487, 415, 416, 417, 418, 419, 420, 421, 422, + 423, 424, 0, 0, 0, 0, 0, 610, 611, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 747, 0, 0, 752, 0, 582, + 0, 0, 0, 0, 0, 0, 551, 0, 0, 455, + 0, 0, 0, 600, 0, 532, 504, 793, 0, 0, + 530, 467, 566, 516, 572, 554, 580, 523, 517, 344, + 555, 391, 481, 363, 365, 780, 393, 396, 400, 401, + 492, 493, 510, 539, 558, 559, 560, 390, 377, 531, + 378, 410, 379, 345, 382, 381, 383, 541, 384, 347, + 511, 563, 0, 406, 527, 476, 348, 475, 512, 562, + 561, 364, 590, 597, 598, 689, 0, 603, 794, 795, + 796, 612, 0, 518, 360, 357, 0, 0, 0, 386, + 513, 373, 375, 376, 374, 507, 509, 617, 618, 619, + 621, 0, 622, 623, 0, 0, 0, 0, 624, 690, + 708, 674, 643, 605, 698, 640, 644, 645, 427, 428, + 429, 430, 711, 0, 0, 0, 596, 456, 457, 0, + 398, 397, 477, 349, 0, 0, 445, 426, 519, 355, + 394, 447, 432, 458, 459, 460, 461, 462, 0, 463, + 464, 404, 339, 340, 788, 387, 500, 713, 750, 751, + 635, 0, 699, 636, 646, 380, 671, 683, 682, 494, + 595, 0, 694, 697, 625, 787, 0, 691, 705, 792, + 704, 784, 506, 0, 538, 702, 649, 0, 695, 668, + 669, 0, 696, 664, 700, 356, 433, 524, 581, 0, + 637, 0, 606, 609, 639, 726, 727, 728, 346, 608, + 730, 731, 732, 733, 734, 735, 736, 729, 577, 672, + 648, 675, 587, 651, 650, 0, 0, 686, 604, 687, + 688, 488, 489, 490, 491, 408, 714, 371, 607, 521, + 522, 0, 673, 0, 0, 0, 0, 0, 0, 0, + 0, 678, 679, 676, 797, 0, 737, 738, 0, 0, + 601, 602, 403, 0, 620, 411, 370, 505, 405, 585, + 436, 0, 613, 680, 614, 525, 526, 741, 746, 742, + 743, 745, 766, 495, 425, 431, 542, 446, 468, 528, + 584, 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 718, 717, 716, 715, - 714, 713, 712, 711, 0, 0, 658, 384, 781, 775, - 782, 763, 766, 765, 740, 0, 341, 638, 464, 518, - 401, 705, 706, 0, 761, 284, 285, 286, 287, 288, + 0, 0, 0, 0, 0, 0, 722, 721, 720, 719, + 718, 717, 716, 715, 0, 0, 662, 385, 785, 779, + 786, 767, 770, 769, 744, 0, 341, 642, 466, 520, + 402, 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, - 298, 303, 304, 305, 306, 307, 308, 309, 310, 708, + 298, 303, 304, 305, 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, - 333, 767, 768, 769, 770, 771, 0, 0, 334, 335, - 336, 0, 0, 299, 300, 327, 549, 328, 329, 330, - 331, 0, 0, 587, 588, 589, 612, 0, 590, 572, - 637, 411, 342, 553, 579, 778, 779, 0, 0, 0, - 0, 0, 0, 0, 688, 699, 735, 736, 0, 749, - 750, 752, 754, 753, 756, 546, 547, 764, 0, 0, - 435, 357, 358, 494, 495, 532, 0, 436, 437, 438, - 442, 439, 440, 441, 758, 759, 760, 757, 468, 531, - 554, 540, 777, 481, 0, 785, 627, 628, 786, 745, - 744, 343, 0, 337, 338, 702, 703, 0, 0, 534, - 480, 634, 500, 0, 0, 643, 677, 666, 755, 630, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 394, 0, 0, 463, 681, 662, 673, 663, 506, 648, - 649, 650, 657, 406, 651, 787, 653, 622, 654, 623, - 655, 656, 0, 680, 629, 542, 482, 0, 697, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 268, 0, 0, 0, 0, 0, 0, 365, 269, 624, - 751, 626, 625, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 368, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3519, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 543, 571, 0, 584, 0, 432, 433, - 0, 0, 0, 0, 0, 0, 0, 350, 550, 568, - 366, 537, 582, 371, 545, 561, 361, 499, 533, 0, - 0, 352, 566, 544, 477, 351, 0, 526, 391, 408, - 388, 497, 0, 0, 565, 595, 387, 585, 0, 576, - 354, 0, 575, 496, 469, 562, 567, 478, 471, 0, - 353, 564, 476, 470, 446, 398, 611, 447, 448, 449, - 450, 451, 452, 412, 512, 467, 513, 413, 484, 483, - 485, 414, 415, 416, 417, 418, 419, 420, 421, 422, - 423, 0, 0, 0, 0, 0, 606, 607, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 743, 0, 0, 748, 0, 578, 0, - 0, 0, 0, 0, 0, 548, 0, 0, 453, 0, - 0, 0, 596, 0, 529, 502, 789, 0, 0, 527, - 465, 563, 514, 569, 551, 577, 521, 515, 344, 552, - 390, 479, 362, 364, 776, 392, 395, 399, 400, 490, - 491, 508, 536, 555, 556, 557, 389, 376, 528, 377, - 409, 378, 345, 381, 380, 382, 538, 383, 347, 509, - 560, 0, 405, 524, 474, 348, 473, 510, 559, 558, - 363, 586, 593, 594, 685, 0, 599, 790, 791, 792, - 608, 0, 516, 359, 356, 0, 0, 0, 385, 511, - 372, 374, 375, 373, 505, 507, 613, 614, 615, 617, - 0, 618, 619, 0, 0, 0, 0, 620, 686, 704, - 670, 639, 601, 694, 636, 640, 641, 426, 427, 428, - 429, 707, 0, 0, 0, 592, 454, 455, 0, 397, - 396, 475, 349, 0, 0, 443, 425, 517, 355, 393, - 445, 431, 456, 457, 458, 459, 460, 0, 461, 462, - 403, 339, 340, 784, 386, 498, 709, 746, 747, 631, - 0, 695, 632, 642, 379, 667, 679, 678, 492, 591, - 0, 690, 693, 621, 783, 0, 687, 701, 788, 700, - 780, 504, 0, 535, 698, 645, 0, 691, 664, 665, - 0, 692, 660, 696, 0, 633, 0, 602, 605, 635, - 722, 723, 724, 346, 604, 726, 727, 728, 729, 730, - 731, 732, 725, 574, 668, 644, 671, 583, 647, 646, - 0, 0, 682, 600, 683, 684, 486, 487, 488, 489, - 407, 710, 370, 603, 519, 520, 0, 669, 0, 0, - 0, 0, 0, 0, 0, 0, 674, 675, 672, 793, - 0, 733, 734, 0, 0, 597, 598, 402, 0, 616, - 410, 369, 503, 404, 581, 434, 0, 609, 676, 610, - 522, 523, 737, 742, 738, 739, 741, 762, 493, 424, - 430, 539, 444, 466, 525, 580, 501, 530, 367, 570, - 541, 472, 661, 689, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 718, 717, 716, 715, 714, 713, 712, 711, 0, - 0, 658, 384, 781, 775, 782, 763, 766, 765, 740, - 0, 341, 638, 464, 518, 401, 705, 706, 0, 761, - 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, - 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, - 307, 308, 309, 310, 708, 301, 302, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 324, 0, 0, 0, 0, 333, 767, 768, 769, 770, - 771, 0, 0, 334, 335, 336, 0, 0, 299, 300, - 327, 549, 328, 329, 330, 331, 0, 0, 587, 588, - 589, 612, 0, 590, 572, 637, 411, 342, 553, 579, - 778, 779, 0, 0, 0, 0, 0, 0, 0, 688, - 699, 735, 736, 0, 749, 750, 752, 754, 753, 756, - 546, 547, 764, 0, 0, 435, 357, 358, 494, 495, - 532, 0, 436, 437, 438, 442, 439, 440, 441, 758, - 759, 760, 757, 468, 531, 554, 540, 777, 481, 0, - 785, 627, 628, 786, 745, 744, 343, 0, 337, 338, - 702, 703, 0, 0, 534, 480, 634, 500, 0, 0, - 643, 677, 666, 755, 630, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 394, 0, 0, 463, 681, - 662, 673, 663, 506, 648, 649, 650, 657, 406, 651, - 787, 653, 622, 654, 623, 655, 656, 0, 680, 629, - 542, 482, 0, 697, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 268, 0, 0, 3397, 0, - 0, 0, 365, 269, 624, 751, 626, 625, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 368, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 543, 571, - 0, 584, 0, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 350, 550, 568, 366, 537, 582, 371, 545, - 561, 361, 499, 533, 0, 0, 352, 566, 544, 477, - 351, 0, 526, 391, 408, 388, 497, 0, 0, 565, - 595, 387, 585, 0, 576, 354, 0, 575, 496, 469, - 562, 567, 478, 471, 0, 353, 564, 476, 470, 446, - 398, 611, 447, 448, 449, 450, 451, 452, 412, 512, - 467, 513, 413, 484, 483, 485, 414, 415, 416, 417, - 418, 419, 420, 421, 422, 423, 0, 0, 0, 0, - 0, 606, 607, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 743, 0, - 0, 748, 0, 578, 0, 0, 0, 0, 0, 0, - 548, 0, 0, 453, 0, 0, 0, 596, 0, 529, - 502, 789, 0, 0, 527, 465, 563, 514, 569, 551, - 577, 521, 515, 344, 552, 390, 479, 362, 364, 776, - 392, 395, 399, 400, 490, 491, 508, 536, 555, 556, - 557, 389, 376, 528, 377, 409, 378, 345, 381, 380, - 382, 538, 383, 347, 509, 560, 0, 405, 524, 474, - 348, 473, 510, 559, 558, 363, 586, 593, 594, 685, - 0, 599, 790, 791, 792, 608, 0, 516, 359, 356, - 0, 0, 0, 385, 511, 372, 374, 375, 373, 505, - 507, 613, 614, 615, 617, 0, 618, 619, 0, 0, - 0, 0, 620, 686, 704, 670, 639, 601, 694, 636, - 640, 641, 426, 427, 428, 429, 707, 0, 0, 0, - 592, 454, 455, 0, 397, 396, 475, 349, 0, 0, - 443, 425, 517, 355, 393, 445, 431, 456, 457, 458, - 459, 460, 0, 461, 462, 403, 339, 340, 784, 386, - 498, 709, 746, 747, 631, 0, 695, 632, 642, 379, - 667, 679, 678, 492, 591, 0, 690, 693, 621, 783, - 0, 687, 701, 788, 700, 780, 504, 0, 535, 698, - 645, 0, 691, 664, 665, 0, 692, 660, 696, 0, - 633, 0, 602, 605, 635, 722, 723, 724, 346, 604, - 726, 727, 728, 729, 730, 731, 732, 725, 574, 668, - 644, 671, 583, 647, 646, 0, 0, 682, 600, 683, - 684, 486, 487, 488, 489, 407, 710, 370, 603, 519, - 520, 0, 669, 0, 0, 0, 0, 0, 0, 0, - 0, 674, 675, 672, 793, 0, 733, 734, 0, 0, - 597, 598, 402, 0, 616, 410, 369, 503, 404, 581, - 434, 0, 609, 676, 610, 522, 523, 737, 742, 738, - 739, 741, 762, 493, 424, 430, 539, 444, 466, 525, - 580, 501, 530, 367, 570, 541, 472, 661, 689, 0, + 333, 771, 772, 773, 774, 775, 0, 0, 334, 335, + 336, 0, 0, 299, 300, 327, 552, 328, 329, 330, + 331, 0, 0, 591, 592, 593, 616, 0, 594, 575, + 641, 412, 342, 556, 583, 782, 783, 0, 0, 0, + 0, 0, 0, 0, 692, 703, 739, 740, 0, 753, + 754, 756, 758, 757, 760, 549, 550, 768, 0, 0, + 437, 358, 359, 496, 497, 535, 0, 438, 439, 440, + 444, 441, 442, 443, 762, 763, 764, 761, 470, 534, + 557, 543, 781, 483, 0, 789, 631, 632, 790, 749, + 748, 343, 0, 337, 338, 706, 707, 0, 0, 537, + 482, 638, 502, 0, 0, 647, 681, 670, 759, 634, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 395, 0, 0, 465, 685, 666, 677, 667, 508, 652, + 653, 654, 661, 407, 655, 791, 657, 626, 658, 627, + 659, 660, 0, 684, 633, 545, 484, 0, 701, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 268, 0, 0, 0, 0, 0, 0, 366, 269, 628, + 755, 630, 629, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 369, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2735, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 546, 574, 0, 588, 0, 434, 435, + 0, 0, 0, 0, 0, 0, 0, 350, 553, 571, + 367, 540, 586, 372, 548, 564, 362, 501, 536, 0, + 0, 352, 569, 547, 479, 351, 0, 529, 392, 409, + 389, 499, 0, 0, 568, 599, 388, 589, 0, 579, + 354, 0, 578, 498, 471, 565, 570, 480, 473, 0, + 353, 567, 478, 472, 448, 399, 615, 449, 450, 451, + 452, 453, 454, 413, 514, 469, 515, 414, 486, 485, + 487, 415, 416, 417, 418, 419, 420, 421, 422, 423, + 424, 0, 0, 0, 0, 0, 610, 611, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 747, 0, 0, 752, 0, 582, 0, + 0, 0, 0, 0, 0, 551, 0, 0, 455, 0, + 0, 0, 600, 0, 532, 504, 793, 0, 0, 530, + 467, 566, 516, 572, 554, 580, 523, 517, 344, 555, + 391, 481, 363, 365, 780, 393, 396, 400, 401, 492, + 493, 510, 539, 558, 559, 560, 390, 377, 531, 378, + 410, 379, 345, 382, 381, 383, 541, 384, 347, 511, + 563, 0, 406, 527, 476, 348, 475, 512, 562, 561, + 364, 590, 597, 598, 689, 0, 603, 794, 795, 796, + 612, 0, 518, 360, 357, 0, 0, 0, 386, 513, + 373, 375, 376, 374, 507, 509, 617, 618, 619, 621, + 0, 622, 623, 0, 0, 0, 0, 624, 690, 708, + 674, 643, 605, 698, 640, 644, 645, 427, 428, 429, + 430, 711, 0, 0, 0, 596, 456, 457, 0, 398, + 397, 477, 349, 0, 0, 445, 426, 519, 355, 394, + 447, 432, 458, 459, 460, 461, 462, 0, 463, 464, + 404, 339, 340, 788, 387, 500, 713, 750, 751, 635, + 0, 699, 636, 646, 380, 671, 683, 682, 494, 595, + 0, 694, 697, 625, 787, 0, 691, 705, 792, 704, + 784, 506, 0, 538, 702, 649, 0, 695, 668, 669, + 0, 696, 664, 700, 356, 433, 524, 581, 0, 637, + 0, 606, 609, 639, 726, 727, 728, 346, 608, 730, + 731, 732, 733, 734, 735, 736, 729, 577, 672, 648, + 675, 587, 651, 650, 0, 0, 686, 604, 687, 688, + 488, 489, 490, 491, 408, 714, 371, 607, 521, 522, + 0, 673, 0, 0, 0, 0, 0, 0, 0, 0, + 678, 679, 676, 797, 0, 737, 738, 0, 0, 601, + 602, 403, 0, 620, 411, 370, 505, 405, 585, 436, + 0, 613, 680, 614, 525, 526, 741, 746, 742, 743, + 745, 766, 495, 425, 431, 542, 446, 468, 528, 584, + 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, + 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 722, 721, 720, 719, 718, + 717, 716, 715, 0, 0, 662, 385, 785, 779, 786, + 767, 770, 769, 744, 0, 341, 642, 466, 520, 402, + 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, + 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, + 303, 304, 305, 306, 307, 308, 309, 310, 712, 301, + 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, + 771, 772, 773, 774, 775, 0, 0, 334, 335, 336, + 0, 0, 299, 300, 327, 552, 328, 329, 330, 331, + 0, 0, 591, 592, 593, 616, 0, 594, 575, 641, + 412, 342, 556, 583, 782, 783, 0, 0, 0, 0, + 0, 0, 0, 692, 703, 739, 740, 0, 753, 754, + 756, 758, 757, 760, 549, 550, 768, 0, 0, 437, + 358, 359, 496, 497, 535, 0, 438, 439, 440, 444, + 441, 442, 443, 762, 763, 764, 761, 470, 534, 557, + 543, 781, 483, 0, 789, 631, 632, 790, 749, 748, + 343, 0, 337, 338, 706, 707, 0, 0, 537, 482, + 638, 502, 0, 0, 647, 681, 670, 759, 634, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 395, + 0, 0, 465, 685, 666, 677, 667, 508, 652, 653, + 654, 661, 407, 655, 791, 657, 626, 658, 627, 659, + 660, 0, 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 718, 717, 716, 715, - 714, 713, 712, 711, 0, 0, 658, 384, 781, 775, - 782, 763, 766, 765, 740, 0, 341, 638, 464, 518, - 401, 705, 706, 0, 761, 284, 285, 286, 287, 288, - 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, - 298, 303, 304, 305, 306, 307, 308, 309, 310, 708, - 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, - 333, 767, 768, 769, 770, 771, 0, 0, 334, 335, - 336, 0, 0, 299, 300, 327, 549, 328, 329, 330, - 331, 0, 0, 587, 588, 589, 612, 0, 590, 572, - 637, 411, 342, 553, 579, 778, 779, 0, 0, 0, - 0, 0, 0, 0, 688, 699, 735, 736, 0, 749, - 750, 752, 754, 753, 756, 546, 547, 764, 0, 0, - 435, 357, 358, 494, 495, 532, 0, 436, 437, 438, - 442, 439, 440, 441, 758, 759, 760, 757, 468, 531, - 554, 540, 777, 481, 0, 785, 627, 628, 786, 745, - 744, 343, 0, 337, 338, 702, 703, 0, 0, 534, - 480, 634, 500, 0, 0, 643, 677, 666, 755, 630, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 394, 0, 0, 463, 681, 662, 673, 663, 506, 648, - 649, 650, 657, 406, 651, 787, 653, 622, 654, 623, - 655, 656, 0, 680, 629, 542, 482, 0, 697, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3363, 0, 0, - 268, 0, 0, 0, 0, 0, 0, 365, 269, 624, - 751, 626, 625, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 368, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 543, 571, 0, 584, 0, 432, 433, - 0, 0, 0, 0, 0, 0, 0, 350, 550, 568, - 366, 537, 582, 371, 545, 561, 361, 499, 533, 0, - 0, 352, 566, 544, 477, 351, 0, 526, 391, 408, - 388, 497, 0, 0, 565, 595, 387, 585, 0, 576, - 354, 0, 575, 496, 469, 562, 567, 478, 471, 0, - 353, 564, 476, 470, 446, 398, 611, 447, 448, 449, - 450, 451, 452, 412, 512, 467, 513, 413, 484, 483, - 485, 414, 415, 416, 417, 418, 419, 420, 421, 422, - 423, 0, 0, 0, 0, 0, 606, 607, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 743, 0, 0, 748, 0, 578, 0, - 0, 0, 0, 0, 0, 548, 0, 0, 453, 0, - 0, 0, 596, 0, 529, 502, 789, 0, 0, 527, - 465, 563, 514, 569, 551, 577, 521, 515, 344, 552, - 390, 479, 362, 364, 776, 392, 395, 399, 400, 490, - 491, 508, 536, 555, 556, 557, 389, 376, 528, 377, - 409, 378, 345, 381, 380, 382, 538, 383, 347, 509, - 560, 0, 405, 524, 474, 348, 473, 510, 559, 558, - 363, 586, 593, 594, 685, 0, 599, 790, 791, 792, - 608, 0, 516, 359, 356, 0, 0, 0, 385, 511, - 372, 374, 375, 373, 505, 507, 613, 614, 615, 617, - 0, 618, 619, 0, 0, 0, 0, 620, 686, 704, - 670, 639, 601, 694, 636, 640, 641, 426, 427, 428, - 429, 707, 0, 0, 0, 592, 454, 455, 0, 397, - 396, 475, 349, 0, 0, 443, 425, 517, 355, 393, - 445, 431, 456, 457, 458, 459, 460, 0, 461, 462, - 403, 339, 340, 784, 386, 498, 709, 746, 747, 631, - 0, 695, 632, 642, 379, 667, 679, 678, 492, 591, - 0, 690, 693, 621, 783, 0, 687, 701, 788, 700, - 780, 504, 0, 535, 698, 645, 0, 691, 664, 665, - 0, 692, 660, 696, 0, 633, 0, 602, 605, 635, - 722, 723, 724, 346, 604, 726, 727, 728, 729, 730, - 731, 732, 725, 574, 668, 644, 671, 583, 647, 646, - 0, 0, 682, 600, 683, 684, 486, 487, 488, 489, - 407, 710, 370, 603, 519, 520, 0, 669, 0, 0, - 0, 0, 0, 0, 0, 0, 674, 675, 672, 793, - 0, 733, 734, 0, 0, 597, 598, 402, 0, 616, - 410, 369, 503, 404, 581, 434, 0, 609, 676, 610, - 522, 523, 737, 742, 738, 739, 741, 762, 493, 424, - 430, 539, 444, 466, 525, 580, 501, 530, 367, 570, - 541, 472, 661, 689, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, + 0, 0, 3239, 0, 0, 0, 366, 269, 628, 755, + 630, 629, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 369, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 546, 574, 0, 588, 0, 434, 435, 0, + 0, 0, 0, 0, 0, 0, 350, 553, 571, 367, + 540, 586, 372, 548, 564, 362, 501, 536, 0, 0, + 352, 569, 547, 479, 351, 0, 529, 392, 409, 389, + 499, 0, 0, 568, 599, 388, 589, 0, 579, 354, + 0, 578, 498, 471, 565, 570, 480, 473, 0, 353, + 567, 478, 472, 448, 399, 615, 449, 450, 451, 452, + 453, 454, 413, 514, 469, 515, 414, 486, 485, 487, + 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, + 0, 0, 0, 0, 0, 610, 611, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 747, 0, 0, 752, 0, 582, 0, 0, + 0, 0, 0, 0, 551, 0, 0, 455, 0, 0, + 0, 600, 0, 532, 504, 793, 0, 0, 530, 467, + 566, 516, 572, 554, 580, 523, 517, 344, 555, 391, + 481, 363, 365, 780, 393, 396, 400, 401, 492, 493, + 510, 539, 558, 559, 560, 390, 377, 531, 378, 410, + 379, 345, 382, 381, 383, 541, 384, 347, 511, 563, + 0, 406, 527, 476, 348, 475, 512, 562, 561, 364, + 590, 597, 598, 689, 0, 603, 794, 795, 796, 612, + 0, 518, 360, 357, 0, 0, 0, 386, 513, 373, + 375, 376, 374, 507, 509, 617, 618, 619, 621, 0, + 622, 623, 0, 0, 0, 0, 624, 690, 708, 674, + 643, 605, 698, 640, 644, 645, 427, 428, 429, 430, + 711, 0, 0, 0, 596, 456, 457, 0, 398, 397, + 477, 349, 0, 0, 445, 426, 519, 355, 394, 447, + 432, 458, 459, 460, 461, 462, 0, 463, 464, 404, + 339, 340, 788, 387, 500, 713, 750, 751, 635, 0, + 699, 636, 646, 380, 671, 683, 682, 494, 595, 0, + 694, 697, 625, 787, 0, 691, 705, 792, 704, 784, + 506, 0, 538, 702, 649, 0, 695, 668, 669, 0, + 696, 664, 700, 356, 433, 524, 581, 0, 637, 0, + 606, 609, 639, 726, 727, 728, 346, 608, 730, 731, + 732, 733, 734, 735, 736, 729, 577, 672, 648, 675, + 587, 651, 650, 0, 0, 686, 604, 687, 688, 488, + 489, 490, 491, 408, 714, 371, 607, 521, 522, 0, + 673, 0, 0, 0, 0, 0, 0, 0, 0, 678, + 679, 676, 797, 0, 737, 738, 0, 0, 601, 602, + 403, 0, 620, 411, 370, 505, 405, 585, 436, 0, + 613, 680, 614, 525, 526, 741, 746, 742, 743, 745, + 766, 495, 425, 431, 542, 446, 468, 528, 584, 503, + 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 718, 717, 716, 715, 714, 713, 712, 711, 0, - 0, 658, 384, 781, 775, 782, 763, 766, 765, 740, - 0, 341, 638, 464, 518, 401, 705, 706, 0, 761, - 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, - 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, - 307, 308, 309, 310, 708, 301, 302, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 324, 0, 0, 0, 0, 333, 767, 768, 769, 770, - 771, 0, 0, 334, 335, 336, 0, 0, 299, 300, - 327, 549, 328, 329, 330, 331, 0, 0, 587, 588, - 589, 612, 0, 590, 572, 637, 411, 342, 553, 579, - 778, 779, 0, 0, 0, 0, 0, 0, 0, 688, - 699, 735, 736, 0, 749, 750, 752, 754, 753, 756, - 546, 547, 764, 0, 0, 435, 357, 358, 494, 495, - 532, 0, 436, 437, 438, 442, 439, 440, 441, 758, - 759, 760, 757, 468, 531, 554, 540, 777, 481, 0, - 785, 627, 628, 786, 745, 744, 343, 0, 337, 338, - 702, 703, 0, 0, 534, 480, 634, 500, 0, 0, - 643, 677, 666, 755, 630, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 394, 0, 0, 463, 681, - 662, 673, 663, 506, 648, 649, 650, 657, 406, 651, - 787, 653, 622, 654, 623, 655, 656, 0, 680, 629, - 542, 482, 0, 697, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 722, 721, 720, 719, 718, 717, + 716, 715, 0, 0, 662, 385, 785, 779, 786, 767, + 770, 769, 744, 0, 341, 642, 466, 520, 402, 709, + 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, + 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, + 304, 305, 306, 307, 308, 309, 310, 712, 301, 302, + 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 0, 0, 0, 0, 333, 771, + 772, 773, 774, 775, 0, 0, 334, 335, 336, 0, + 0, 299, 300, 327, 552, 328, 329, 330, 331, 0, + 0, 591, 592, 593, 616, 0, 594, 575, 641, 412, + 342, 556, 583, 782, 783, 0, 0, 0, 0, 0, + 0, 0, 692, 703, 739, 740, 0, 753, 754, 756, + 758, 757, 760, 549, 550, 768, 0, 0, 437, 358, + 359, 496, 497, 535, 0, 438, 439, 440, 444, 441, + 442, 443, 762, 763, 764, 761, 470, 534, 557, 543, + 781, 483, 0, 789, 631, 632, 790, 749, 748, 343, + 0, 337, 338, 706, 707, 0, 0, 537, 482, 638, + 502, 0, 0, 647, 681, 670, 759, 634, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 395, 0, + 0, 465, 685, 666, 677, 667, 508, 652, 653, 654, + 661, 407, 655, 791, 657, 626, 658, 627, 659, 660, + 0, 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 268, 0, 0, 0, 0, - 0, 0, 365, 269, 624, 751, 626, 625, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 368, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2731, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 543, 571, - 0, 584, 0, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 350, 550, 568, 366, 537, 582, 371, 545, - 561, 361, 499, 533, 0, 0, 352, 566, 544, 477, - 351, 0, 526, 391, 408, 388, 497, 0, 0, 565, - 595, 387, 585, 0, 576, 354, 0, 575, 496, 469, - 562, 567, 478, 471, 0, 353, 564, 476, 470, 446, - 398, 611, 447, 448, 449, 450, 451, 452, 412, 512, - 467, 513, 413, 484, 483, 485, 414, 415, 416, 417, - 418, 419, 420, 421, 422, 423, 0, 0, 0, 0, - 0, 606, 607, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 743, 0, - 0, 748, 0, 578, 0, 0, 0, 0, 0, 0, - 548, 0, 0, 453, 0, 0, 0, 596, 0, 529, - 502, 789, 0, 0, 527, 465, 563, 514, 569, 551, - 577, 521, 515, 344, 552, 390, 479, 362, 364, 776, - 392, 395, 399, 400, 490, 491, 508, 536, 555, 556, - 557, 389, 376, 528, 377, 409, 378, 345, 381, 380, - 382, 538, 383, 347, 509, 560, 0, 405, 524, 474, - 348, 473, 510, 559, 558, 363, 586, 593, 594, 685, - 0, 599, 790, 791, 792, 608, 0, 516, 359, 356, - 0, 0, 0, 385, 511, 372, 374, 375, 373, 505, - 507, 613, 614, 615, 617, 0, 618, 619, 0, 0, - 0, 0, 620, 686, 704, 670, 639, 601, 694, 636, - 640, 641, 426, 427, 428, 429, 707, 0, 0, 0, - 592, 454, 455, 0, 397, 396, 475, 349, 0, 0, - 443, 425, 517, 355, 393, 445, 431, 456, 457, 458, - 459, 460, 0, 461, 462, 403, 339, 340, 784, 386, - 498, 709, 746, 747, 631, 0, 695, 632, 642, 379, - 667, 679, 678, 492, 591, 0, 690, 693, 621, 783, - 0, 687, 701, 788, 700, 780, 504, 0, 535, 698, - 645, 0, 691, 664, 665, 0, 692, 660, 696, 0, - 633, 0, 602, 605, 635, 722, 723, 724, 346, 604, - 726, 727, 728, 729, 730, 731, 732, 725, 574, 668, - 644, 671, 583, 647, 646, 0, 0, 682, 600, 683, - 684, 486, 487, 488, 489, 407, 710, 370, 603, 519, - 520, 0, 669, 0, 0, 0, 0, 0, 0, 0, - 0, 674, 675, 672, 793, 0, 733, 734, 0, 0, - 597, 598, 402, 0, 616, 410, 369, 503, 404, 581, - 434, 0, 609, 676, 610, 522, 523, 737, 742, 738, - 739, 741, 762, 493, 424, 430, 539, 444, 466, 525, - 580, 501, 530, 367, 570, 541, 472, 661, 689, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 268, 0, + 0, 0, 0, 0, 0, 366, 269, 628, 755, 630, + 629, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 369, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3187, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 546, 574, 0, 588, 0, 434, 435, 0, 0, + 0, 0, 0, 0, 0, 350, 553, 571, 367, 540, + 586, 372, 548, 564, 362, 501, 536, 0, 0, 352, + 569, 547, 479, 351, 0, 529, 392, 409, 389, 499, + 0, 0, 568, 599, 388, 589, 0, 579, 354, 0, + 578, 498, 471, 565, 570, 480, 473, 0, 353, 567, + 478, 472, 448, 399, 615, 449, 450, 451, 452, 453, + 454, 413, 514, 469, 515, 414, 486, 485, 487, 415, + 416, 417, 418, 419, 420, 421, 422, 423, 424, 0, + 0, 0, 0, 0, 610, 611, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 747, 0, 0, 752, 0, 582, 0, 0, 0, + 0, 0, 0, 551, 0, 0, 455, 0, 0, 0, + 600, 0, 532, 504, 793, 0, 0, 530, 467, 566, + 516, 572, 554, 580, 523, 517, 344, 555, 391, 481, + 363, 365, 780, 393, 396, 400, 401, 492, 493, 510, + 539, 558, 559, 560, 390, 377, 531, 378, 410, 379, + 345, 382, 381, 383, 541, 384, 347, 511, 563, 0, + 406, 527, 476, 348, 475, 512, 562, 561, 364, 590, + 597, 598, 689, 0, 603, 794, 795, 796, 612, 0, + 518, 360, 357, 0, 0, 0, 386, 513, 373, 375, + 376, 374, 507, 509, 617, 618, 619, 621, 0, 622, + 623, 0, 0, 0, 0, 624, 690, 708, 674, 643, + 605, 698, 640, 644, 645, 427, 428, 429, 430, 711, + 0, 0, 0, 596, 456, 457, 0, 398, 397, 477, + 349, 0, 0, 445, 426, 519, 355, 394, 447, 432, + 458, 459, 460, 461, 462, 0, 463, 464, 404, 339, + 340, 788, 387, 500, 713, 750, 751, 635, 0, 699, + 636, 646, 380, 671, 683, 682, 494, 595, 0, 694, + 697, 625, 787, 0, 691, 705, 792, 704, 784, 506, + 0, 538, 702, 649, 0, 695, 668, 669, 0, 696, + 664, 700, 356, 433, 524, 581, 0, 637, 0, 606, + 609, 639, 726, 727, 728, 346, 608, 730, 731, 732, + 733, 734, 735, 736, 729, 577, 672, 648, 675, 587, + 651, 650, 0, 0, 686, 604, 687, 688, 488, 489, + 490, 491, 408, 714, 371, 607, 521, 522, 0, 673, + 0, 0, 0, 0, 0, 0, 0, 0, 678, 679, + 676, 797, 0, 737, 738, 0, 0, 601, 602, 403, + 0, 620, 411, 370, 505, 405, 585, 436, 0, 613, + 680, 614, 525, 526, 741, 746, 742, 743, 745, 766, + 495, 425, 431, 542, 446, 468, 528, 584, 503, 533, + 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 718, 717, 716, 715, - 714, 713, 712, 711, 0, 0, 658, 384, 781, 775, - 782, 763, 766, 765, 740, 0, 341, 638, 464, 518, - 401, 705, 706, 0, 761, 284, 285, 286, 287, 288, - 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, - 298, 303, 304, 305, 306, 307, 308, 309, 310, 708, - 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, - 333, 767, 768, 769, 770, 771, 0, 0, 334, 335, - 336, 0, 0, 299, 300, 327, 549, 328, 329, 330, - 331, 0, 0, 587, 588, 589, 612, 0, 590, 572, - 637, 411, 342, 553, 579, 778, 779, 0, 0, 0, - 0, 0, 0, 0, 688, 699, 735, 736, 0, 749, - 750, 752, 754, 753, 756, 546, 547, 764, 0, 0, - 435, 357, 358, 494, 495, 532, 0, 436, 437, 438, - 442, 439, 440, 441, 758, 759, 760, 757, 468, 531, - 554, 540, 777, 481, 0, 785, 627, 628, 786, 745, - 744, 343, 0, 337, 338, 702, 703, 0, 0, 534, - 480, 634, 500, 0, 0, 643, 677, 666, 755, 630, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 394, 0, 0, 463, 681, 662, 673, 663, 506, 648, - 649, 650, 657, 406, 651, 787, 653, 622, 654, 623, - 655, 656, 0, 680, 629, 542, 482, 0, 697, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 268, 0, 0, 3235, 0, 0, 0, 365, 269, 624, - 751, 626, 625, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 368, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 543, 571, 0, 584, 0, 432, 433, - 0, 0, 0, 0, 0, 0, 0, 350, 550, 568, - 366, 537, 582, 371, 545, 561, 361, 499, 533, 0, - 0, 352, 566, 544, 477, 351, 0, 526, 391, 408, - 388, 497, 0, 0, 565, 595, 387, 585, 0, 576, - 354, 0, 575, 496, 469, 562, 567, 478, 471, 0, - 353, 564, 476, 470, 446, 398, 611, 447, 448, 449, - 450, 451, 452, 412, 512, 467, 513, 413, 484, 483, - 485, 414, 415, 416, 417, 418, 419, 420, 421, 422, - 423, 0, 0, 0, 0, 0, 606, 607, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 743, 0, 0, 748, 0, 578, 0, - 0, 0, 0, 0, 0, 548, 0, 0, 453, 0, - 0, 0, 596, 0, 529, 502, 789, 0, 0, 527, - 465, 563, 514, 569, 551, 577, 521, 515, 344, 552, - 390, 479, 362, 364, 776, 392, 395, 399, 400, 490, - 491, 508, 536, 555, 556, 557, 389, 376, 528, 377, - 409, 378, 345, 381, 380, 382, 538, 383, 347, 509, - 560, 0, 405, 524, 474, 348, 473, 510, 559, 558, - 363, 586, 593, 594, 685, 0, 599, 790, 791, 792, - 608, 0, 516, 359, 356, 0, 0, 0, 385, 511, - 372, 374, 375, 373, 505, 507, 613, 614, 615, 617, - 0, 618, 619, 0, 0, 0, 0, 620, 686, 704, - 670, 639, 601, 694, 636, 640, 641, 426, 427, 428, - 429, 707, 0, 0, 0, 592, 454, 455, 0, 397, - 396, 475, 349, 0, 0, 443, 425, 517, 355, 393, - 445, 431, 456, 457, 458, 459, 460, 0, 461, 462, - 403, 339, 340, 784, 386, 498, 709, 746, 747, 631, - 0, 695, 632, 642, 379, 667, 679, 678, 492, 591, - 0, 690, 693, 621, 783, 0, 687, 701, 788, 700, - 780, 504, 0, 535, 698, 645, 0, 691, 664, 665, - 0, 692, 660, 696, 0, 633, 0, 602, 605, 635, - 722, 723, 724, 346, 604, 726, 727, 728, 729, 730, - 731, 732, 725, 574, 668, 644, 671, 583, 647, 646, - 0, 0, 682, 600, 683, 684, 486, 487, 488, 489, - 407, 710, 370, 603, 519, 520, 0, 669, 0, 0, - 0, 0, 0, 0, 0, 0, 674, 675, 672, 793, - 0, 733, 734, 0, 0, 597, 598, 402, 0, 616, - 410, 369, 503, 404, 581, 434, 0, 609, 676, 610, - 522, 523, 737, 742, 738, 739, 741, 762, 493, 424, - 430, 539, 444, 466, 525, 580, 501, 530, 367, 570, - 541, 472, 661, 689, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, + 0, 0, 0, 722, 721, 720, 719, 718, 717, 716, + 715, 0, 0, 662, 385, 785, 779, 786, 767, 770, + 769, 744, 0, 341, 642, 466, 520, 402, 709, 710, + 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, + 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, + 305, 306, 307, 308, 309, 310, 712, 301, 302, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 0, 0, 0, 0, 333, 771, 772, + 773, 774, 775, 0, 0, 334, 335, 336, 0, 0, + 299, 300, 327, 552, 328, 329, 330, 331, 0, 0, + 591, 592, 593, 616, 0, 594, 575, 641, 412, 342, + 556, 583, 782, 783, 0, 0, 0, 0, 0, 0, + 0, 692, 703, 739, 740, 0, 753, 754, 756, 758, + 757, 760, 549, 550, 768, 0, 0, 437, 358, 359, + 496, 497, 535, 0, 438, 439, 440, 444, 441, 442, + 443, 762, 763, 764, 761, 470, 534, 557, 543, 781, + 483, 0, 789, 631, 632, 790, 749, 748, 343, 0, + 337, 338, 706, 707, 0, 0, 537, 482, 638, 502, + 0, 0, 647, 681, 670, 759, 634, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 395, 0, 0, + 465, 685, 666, 677, 667, 508, 652, 653, 654, 661, + 407, 655, 791, 657, 626, 658, 627, 659, 660, 0, + 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 268, 0, 0, + 3185, 0, 0, 0, 366, 269, 628, 755, 630, 629, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 369, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 546, 574, 0, 588, 0, 434, 435, 0, 0, 0, + 0, 0, 0, 0, 350, 553, 571, 367, 540, 586, + 372, 548, 564, 362, 501, 536, 0, 0, 352, 569, + 547, 479, 351, 0, 529, 392, 409, 389, 499, 0, + 0, 568, 599, 388, 589, 0, 579, 354, 0, 578, + 498, 471, 565, 570, 480, 473, 0, 353, 567, 478, + 472, 448, 399, 615, 449, 450, 451, 452, 453, 454, + 413, 514, 469, 515, 414, 486, 485, 487, 415, 416, + 417, 418, 419, 420, 421, 422, 423, 424, 0, 0, + 0, 0, 0, 610, 611, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 747, 0, 0, 752, 0, 582, 0, 0, 0, 0, + 0, 0, 551, 0, 0, 455, 0, 0, 0, 600, + 0, 532, 504, 793, 0, 0, 530, 467, 566, 516, + 572, 554, 580, 523, 517, 344, 555, 391, 481, 363, + 365, 780, 393, 396, 400, 401, 492, 493, 510, 539, + 558, 559, 560, 390, 377, 531, 378, 410, 379, 345, + 382, 381, 383, 541, 384, 347, 511, 563, 0, 406, + 527, 476, 348, 475, 512, 562, 561, 364, 590, 597, + 598, 689, 0, 603, 794, 795, 796, 612, 0, 518, + 360, 357, 0, 0, 0, 386, 513, 373, 375, 376, + 374, 507, 509, 617, 618, 619, 621, 0, 622, 623, + 0, 0, 0, 0, 624, 690, 708, 674, 643, 605, + 698, 640, 644, 645, 427, 428, 429, 430, 711, 0, + 0, 0, 596, 456, 457, 0, 398, 397, 477, 349, + 0, 0, 445, 426, 519, 355, 394, 447, 432, 458, + 459, 460, 461, 462, 0, 463, 464, 404, 339, 340, + 788, 387, 500, 713, 750, 751, 635, 0, 699, 636, + 646, 380, 671, 683, 682, 494, 595, 0, 694, 697, + 625, 787, 0, 691, 705, 792, 704, 784, 506, 0, + 538, 702, 649, 0, 695, 668, 669, 0, 696, 664, + 700, 356, 433, 524, 581, 0, 637, 0, 606, 609, + 639, 726, 727, 728, 346, 608, 730, 731, 732, 733, + 734, 735, 736, 729, 577, 672, 648, 675, 587, 651, + 650, 0, 0, 686, 604, 687, 688, 488, 489, 490, + 491, 408, 714, 371, 607, 521, 522, 0, 673, 0, + 0, 0, 0, 0, 0, 0, 0, 678, 679, 676, + 797, 0, 737, 738, 0, 0, 601, 602, 403, 0, + 620, 411, 370, 505, 405, 585, 436, 0, 613, 680, + 614, 525, 526, 741, 746, 742, 743, 745, 766, 495, + 425, 431, 542, 446, 468, 528, 584, 503, 533, 368, + 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 718, 717, 716, 715, 714, 713, 712, 711, 0, - 0, 658, 384, 781, 775, 782, 763, 766, 765, 740, - 0, 341, 638, 464, 518, 401, 705, 706, 0, 761, - 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, - 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, - 307, 308, 309, 310, 708, 301, 302, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 324, 0, 0, 0, 0, 333, 767, 768, 769, 770, - 771, 0, 0, 334, 335, 336, 0, 0, 299, 300, - 327, 549, 328, 329, 330, 331, 0, 0, 587, 588, - 589, 612, 0, 590, 572, 637, 411, 342, 553, 579, - 778, 779, 0, 0, 0, 0, 0, 0, 0, 688, - 699, 735, 736, 0, 749, 750, 752, 754, 753, 756, - 546, 547, 764, 0, 0, 435, 357, 358, 494, 495, - 532, 0, 436, 437, 438, 442, 439, 440, 441, 758, - 759, 760, 757, 468, 531, 554, 540, 777, 481, 0, - 785, 627, 628, 786, 745, 744, 343, 0, 337, 338, - 702, 703, 0, 0, 534, 480, 634, 500, 0, 0, - 643, 677, 666, 755, 630, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 394, 0, 0, 463, 681, - 662, 673, 663, 506, 648, 649, 650, 657, 406, 651, - 787, 653, 622, 654, 623, 655, 656, 0, 680, 629, - 542, 482, 0, 697, 0, 0, 0, 0, 0, 0, + 0, 0, 722, 721, 720, 719, 718, 717, 716, 715, + 0, 0, 662, 385, 785, 779, 786, 767, 770, 769, + 744, 0, 341, 642, 466, 520, 402, 709, 710, 0, + 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, + 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, + 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 0, 0, 0, 0, 333, 771, 772, 773, + 774, 775, 0, 0, 334, 335, 336, 0, 0, 299, + 300, 327, 552, 328, 329, 330, 331, 0, 0, 591, + 592, 593, 616, 0, 594, 575, 641, 412, 342, 556, + 583, 782, 783, 0, 0, 0, 0, 0, 0, 0, + 692, 703, 739, 740, 0, 753, 754, 756, 758, 757, + 760, 549, 550, 768, 0, 0, 437, 358, 359, 496, + 497, 535, 0, 438, 439, 440, 444, 441, 442, 443, + 762, 763, 764, 761, 470, 534, 557, 543, 781, 483, + 0, 789, 631, 632, 790, 749, 748, 343, 0, 337, + 338, 706, 707, 2982, 0, 537, 482, 638, 0, 502, + 0, 0, 647, 681, 670, 759, 634, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 395, 0, 0, + 465, 685, 666, 677, 667, 508, 652, 653, 654, 661, + 407, 655, 791, 657, 626, 658, 627, 659, 660, 0, + 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 268, 0, 0, + 0, 0, 0, 0, 366, 269, 628, 755, 630, 629, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 369, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 546, 574, 0, 588, 0, 434, 435, 0, 0, 0, + 0, 0, 0, 0, 350, 553, 571, 367, 540, 586, + 372, 548, 564, 362, 501, 536, 0, 0, 352, 569, + 547, 479, 351, 0, 529, 392, 409, 389, 499, 0, + 0, 568, 599, 388, 589, 0, 579, 354, 0, 578, + 498, 471, 565, 570, 480, 473, 0, 353, 567, 478, + 472, 448, 399, 615, 449, 450, 451, 452, 453, 454, + 413, 514, 469, 515, 414, 486, 485, 487, 415, 416, + 417, 418, 419, 420, 421, 422, 423, 424, 0, 0, + 0, 0, 0, 610, 611, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 747, 0, 0, 752, 0, 582, 0, 0, 0, 0, + 0, 0, 551, 0, 0, 455, 0, 0, 0, 600, + 0, 532, 504, 793, 0, 0, 530, 467, 566, 516, + 572, 554, 580, 523, 517, 344, 555, 391, 481, 363, + 365, 780, 393, 396, 400, 401, 492, 493, 510, 539, + 558, 559, 560, 390, 377, 531, 378, 410, 379, 345, + 382, 381, 383, 541, 384, 347, 511, 563, 0, 406, + 527, 476, 348, 475, 512, 562, 561, 364, 590, 597, + 598, 689, 0, 603, 794, 795, 796, 612, 0, 518, + 360, 357, 0, 0, 0, 386, 513, 373, 375, 376, + 374, 507, 509, 617, 618, 619, 621, 0, 622, 623, + 0, 0, 0, 0, 624, 690, 708, 674, 643, 605, + 698, 640, 644, 645, 427, 428, 429, 430, 711, 0, + 0, 0, 596, 456, 457, 0, 398, 397, 477, 349, + 0, 0, 445, 426, 519, 355, 394, 447, 432, 458, + 459, 460, 461, 462, 0, 463, 464, 404, 339, 340, + 788, 387, 500, 713, 750, 751, 635, 0, 699, 636, + 646, 380, 671, 683, 682, 494, 595, 0, 694, 697, + 625, 787, 0, 691, 705, 792, 704, 784, 506, 0, + 538, 702, 649, 0, 695, 668, 669, 0, 696, 664, + 700, 356, 433, 524, 581, 0, 637, 0, 606, 609, + 639, 726, 727, 728, 346, 608, 730, 731, 732, 733, + 734, 735, 736, 729, 577, 672, 648, 675, 587, 651, + 650, 0, 0, 686, 604, 687, 688, 488, 489, 490, + 491, 408, 714, 371, 607, 521, 522, 0, 673, 0, + 0, 0, 0, 0, 0, 0, 0, 678, 679, 676, + 797, 0, 737, 738, 0, 0, 601, 602, 403, 0, + 620, 411, 370, 505, 405, 585, 436, 0, 613, 680, + 614, 525, 526, 741, 746, 742, 743, 745, 766, 495, + 425, 431, 542, 446, 468, 528, 584, 503, 533, 368, + 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 268, 0, 0, 0, 0, - 0, 0, 365, 269, 624, 751, 626, 625, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 368, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3183, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 543, 571, - 0, 584, 0, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 350, 550, 568, 366, 537, 582, 371, 545, - 561, 361, 499, 533, 0, 0, 352, 566, 544, 477, - 351, 0, 526, 391, 408, 388, 497, 0, 0, 565, - 595, 387, 585, 0, 576, 354, 0, 575, 496, 469, - 562, 567, 478, 471, 0, 353, 564, 476, 470, 446, - 398, 611, 447, 448, 449, 450, 451, 452, 412, 512, - 467, 513, 413, 484, 483, 485, 414, 415, 416, 417, - 418, 419, 420, 421, 422, 423, 0, 0, 0, 0, - 0, 606, 607, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 743, 0, - 0, 748, 0, 578, 0, 0, 0, 0, 0, 0, - 548, 0, 0, 453, 0, 0, 0, 596, 0, 529, - 502, 789, 0, 0, 527, 465, 563, 514, 569, 551, - 577, 521, 515, 344, 552, 390, 479, 362, 364, 776, - 392, 395, 399, 400, 490, 491, 508, 536, 555, 556, - 557, 389, 376, 528, 377, 409, 378, 345, 381, 380, - 382, 538, 383, 347, 509, 560, 0, 405, 524, 474, - 348, 473, 510, 559, 558, 363, 586, 593, 594, 685, - 0, 599, 790, 791, 792, 608, 0, 516, 359, 356, - 0, 0, 0, 385, 511, 372, 374, 375, 373, 505, - 507, 613, 614, 615, 617, 0, 618, 619, 0, 0, - 0, 0, 620, 686, 704, 670, 639, 601, 694, 636, - 640, 641, 426, 427, 428, 429, 707, 0, 0, 0, - 592, 454, 455, 0, 397, 396, 475, 349, 0, 0, - 443, 425, 517, 355, 393, 445, 431, 456, 457, 458, - 459, 460, 0, 461, 462, 403, 339, 340, 784, 386, - 498, 709, 746, 747, 631, 0, 695, 632, 642, 379, - 667, 679, 678, 492, 591, 0, 690, 693, 621, 783, - 0, 687, 701, 788, 700, 780, 504, 0, 535, 698, - 645, 0, 691, 664, 665, 0, 692, 660, 696, 0, - 633, 0, 602, 605, 635, 722, 723, 724, 346, 604, - 726, 727, 728, 729, 730, 731, 732, 725, 574, 668, - 644, 671, 583, 647, 646, 0, 0, 682, 600, 683, - 684, 486, 487, 488, 489, 407, 710, 370, 603, 519, - 520, 0, 669, 0, 0, 0, 0, 0, 0, 0, - 0, 674, 675, 672, 793, 0, 733, 734, 0, 0, - 597, 598, 402, 0, 616, 410, 369, 503, 404, 581, - 434, 0, 609, 676, 610, 522, 523, 737, 742, 738, - 739, 741, 762, 493, 424, 430, 539, 444, 466, 525, - 580, 501, 530, 367, 570, 541, 472, 661, 689, 0, + 0, 0, 722, 721, 720, 719, 718, 717, 716, 715, + 0, 0, 662, 385, 785, 779, 786, 767, 770, 769, + 744, 0, 341, 642, 466, 520, 402, 709, 710, 0, + 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, + 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, + 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 0, 0, 0, 0, 333, 771, 772, 773, + 774, 775, 0, 0, 334, 335, 336, 0, 0, 299, + 300, 327, 552, 328, 329, 330, 331, 0, 0, 591, + 592, 593, 616, 0, 594, 575, 641, 412, 342, 556, + 583, 782, 783, 0, 0, 0, 0, 0, 0, 0, + 692, 703, 739, 740, 0, 753, 754, 756, 758, 757, + 760, 549, 550, 768, 0, 0, 437, 358, 359, 496, + 497, 535, 0, 438, 439, 440, 444, 441, 442, 443, + 762, 763, 764, 761, 470, 534, 557, 543, 781, 483, + 0, 789, 631, 632, 790, 749, 748, 343, 0, 337, + 338, 706, 707, 0, 0, 537, 482, 638, 502, 0, + 0, 647, 681, 670, 759, 634, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 395, 0, 0, 465, + 685, 666, 677, 667, 508, 652, 653, 654, 661, 407, + 655, 791, 657, 626, 658, 627, 659, 660, 0, 684, + 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 718, 717, 716, 715, - 714, 713, 712, 711, 0, 0, 658, 384, 781, 775, - 782, 763, 766, 765, 740, 0, 341, 638, 464, 518, - 401, 705, 706, 0, 761, 284, 285, 286, 287, 288, - 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, - 298, 303, 304, 305, 306, 307, 308, 309, 310, 708, - 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, - 333, 767, 768, 769, 770, 771, 0, 0, 334, 335, - 336, 0, 0, 299, 300, 327, 549, 328, 329, 330, - 331, 0, 0, 587, 588, 589, 612, 0, 590, 572, - 637, 411, 342, 553, 579, 778, 779, 0, 0, 0, - 0, 0, 0, 0, 688, 699, 735, 736, 0, 749, - 750, 752, 754, 753, 756, 546, 547, 764, 0, 0, - 435, 357, 358, 494, 495, 532, 0, 436, 437, 438, - 442, 439, 440, 441, 758, 759, 760, 757, 468, 531, - 554, 540, 777, 481, 0, 785, 627, 628, 786, 745, - 744, 343, 0, 337, 338, 702, 703, 0, 0, 534, - 480, 634, 500, 0, 0, 643, 677, 666, 755, 630, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 394, 0, 0, 463, 681, 662, 673, 663, 506, 648, - 649, 650, 657, 406, 651, 787, 653, 622, 654, 623, - 655, 656, 0, 680, 629, 542, 482, 0, 697, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 268, 0, 0, 3181, 0, 0, 0, 365, 269, 624, - 751, 626, 625, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 368, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 543, 571, 0, 584, 0, 432, 433, - 0, 0, 0, 0, 0, 0, 0, 350, 550, 568, - 366, 537, 582, 371, 545, 561, 361, 499, 533, 0, - 0, 352, 566, 544, 477, 351, 0, 526, 391, 408, - 388, 497, 0, 0, 565, 595, 387, 585, 0, 576, - 354, 0, 575, 496, 469, 562, 567, 478, 471, 0, - 353, 564, 476, 470, 446, 398, 611, 447, 448, 449, - 450, 451, 452, 412, 512, 467, 513, 413, 484, 483, - 485, 414, 415, 416, 417, 418, 419, 420, 421, 422, - 423, 0, 0, 0, 0, 0, 606, 607, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 743, 0, 0, 748, 0, 578, 0, - 0, 0, 0, 0, 0, 548, 0, 0, 453, 0, - 0, 0, 596, 0, 529, 502, 789, 0, 0, 527, - 465, 563, 514, 569, 551, 577, 521, 515, 344, 552, - 390, 479, 362, 364, 776, 392, 395, 399, 400, 490, - 491, 508, 536, 555, 556, 557, 389, 376, 528, 377, - 409, 378, 345, 381, 380, 382, 538, 383, 347, 509, - 560, 0, 405, 524, 474, 348, 473, 510, 559, 558, - 363, 586, 593, 594, 685, 0, 599, 790, 791, 792, - 608, 0, 516, 359, 356, 0, 0, 0, 385, 511, - 372, 374, 375, 373, 505, 507, 613, 614, 615, 617, - 0, 618, 619, 0, 0, 0, 0, 620, 686, 704, - 670, 639, 601, 694, 636, 640, 641, 426, 427, 428, - 429, 707, 0, 0, 0, 592, 454, 455, 0, 397, - 396, 475, 349, 0, 0, 443, 425, 517, 355, 393, - 445, 431, 456, 457, 458, 459, 460, 0, 461, 462, - 403, 339, 340, 784, 386, 498, 709, 746, 747, 631, - 0, 695, 632, 642, 379, 667, 679, 678, 492, 591, - 0, 690, 693, 621, 783, 0, 687, 701, 788, 700, - 780, 504, 0, 535, 698, 645, 0, 691, 664, 665, - 0, 692, 660, 696, 0, 633, 0, 602, 605, 635, - 722, 723, 724, 346, 604, 726, 727, 728, 729, 730, - 731, 732, 725, 574, 668, 644, 671, 583, 647, 646, - 0, 0, 682, 600, 683, 684, 486, 487, 488, 489, - 407, 710, 370, 603, 519, 520, 0, 669, 0, 0, - 0, 0, 0, 0, 0, 0, 674, 675, 672, 793, - 0, 733, 734, 0, 0, 597, 598, 402, 0, 616, - 410, 369, 503, 404, 581, 434, 0, 609, 676, 610, - 522, 523, 737, 742, 738, 739, 741, 762, 493, 424, - 430, 539, 444, 466, 525, 580, 501, 530, 367, 570, - 541, 472, 661, 689, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 268, 0, 0, 0, + 2386, 0, 0, 366, 269, 628, 755, 630, 629, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 369, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 546, + 574, 0, 588, 0, 434, 435, 0, 0, 0, 0, + 0, 0, 0, 350, 553, 571, 367, 540, 586, 372, + 548, 564, 362, 501, 536, 0, 0, 352, 569, 547, + 479, 351, 0, 529, 392, 409, 389, 499, 0, 0, + 568, 599, 388, 589, 0, 579, 354, 0, 578, 498, + 471, 565, 570, 480, 473, 0, 353, 567, 478, 472, + 448, 399, 615, 449, 450, 451, 452, 453, 454, 413, + 514, 469, 515, 414, 486, 485, 487, 415, 416, 417, + 418, 419, 420, 421, 422, 423, 424, 0, 0, 0, + 0, 0, 610, 611, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 747, + 0, 0, 752, 0, 582, 0, 0, 0, 0, 0, + 0, 551, 0, 0, 455, 0, 0, 0, 600, 0, + 532, 504, 793, 0, 0, 530, 467, 566, 516, 572, + 554, 580, 523, 517, 344, 555, 391, 481, 363, 365, + 780, 393, 396, 400, 401, 492, 493, 510, 539, 558, + 559, 560, 390, 377, 531, 378, 410, 379, 345, 382, + 381, 383, 541, 384, 347, 511, 563, 0, 406, 527, + 476, 348, 475, 512, 562, 561, 364, 590, 597, 598, + 689, 0, 603, 794, 795, 796, 612, 0, 518, 360, + 357, 0, 0, 0, 386, 513, 373, 375, 376, 374, + 507, 509, 617, 618, 619, 621, 0, 622, 623, 0, + 0, 0, 0, 624, 690, 708, 674, 643, 605, 698, + 640, 644, 645, 427, 428, 429, 430, 711, 0, 0, + 0, 596, 456, 457, 0, 398, 397, 477, 349, 0, + 0, 445, 426, 519, 355, 394, 447, 432, 458, 459, + 460, 461, 462, 0, 463, 464, 404, 339, 340, 788, + 387, 500, 713, 750, 751, 635, 0, 699, 636, 646, + 380, 671, 683, 682, 494, 595, 0, 694, 697, 625, + 787, 0, 691, 705, 792, 704, 784, 506, 0, 538, + 702, 649, 0, 695, 668, 669, 0, 696, 664, 700, + 356, 433, 524, 581, 0, 637, 0, 606, 609, 639, + 726, 727, 728, 346, 608, 730, 731, 732, 733, 734, + 735, 736, 729, 577, 672, 648, 675, 587, 651, 650, + 0, 0, 686, 604, 687, 688, 488, 489, 490, 491, + 408, 714, 371, 607, 521, 522, 0, 673, 0, 0, + 0, 0, 0, 0, 0, 0, 678, 679, 676, 797, + 0, 737, 738, 0, 0, 601, 602, 403, 0, 620, + 411, 370, 505, 405, 585, 436, 0, 613, 680, 614, + 525, 526, 741, 746, 742, 743, 745, 766, 495, 425, + 431, 542, 446, 468, 528, 584, 503, 533, 368, 573, + 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 718, 717, 716, 715, 714, 713, 712, 711, 0, - 0, 658, 384, 781, 775, 782, 763, 766, 765, 740, - 0, 341, 638, 464, 518, 401, 705, 706, 0, 761, + 0, 722, 721, 720, 719, 718, 717, 716, 715, 0, + 0, 662, 385, 785, 779, 786, 767, 770, 769, 744, + 0, 341, 642, 466, 520, 402, 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, - 307, 308, 309, 310, 708, 301, 302, 311, 312, 313, + 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 324, 0, 0, 0, 0, 333, 767, 768, 769, 770, - 771, 0, 0, 334, 335, 336, 0, 0, 299, 300, - 327, 549, 328, 329, 330, 331, 0, 0, 587, 588, - 589, 612, 0, 590, 572, 637, 411, 342, 553, 579, - 778, 779, 0, 0, 0, 0, 0, 0, 0, 688, - 699, 735, 736, 0, 749, 750, 752, 754, 753, 756, - 546, 547, 764, 0, 0, 435, 357, 358, 494, 495, - 532, 0, 436, 437, 438, 442, 439, 440, 441, 758, - 759, 760, 757, 468, 531, 554, 540, 777, 481, 0, - 785, 627, 628, 786, 745, 744, 343, 0, 337, 338, - 702, 703, 2978, 0, 534, 480, 634, 0, 500, 0, - 0, 643, 677, 666, 755, 630, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 394, 0, 0, 463, - 681, 662, 673, 663, 506, 648, 649, 650, 657, 406, - 651, 787, 653, 622, 654, 623, 655, 656, 0, 680, - 629, 542, 482, 0, 697, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 268, 0, 0, 0, - 0, 0, 0, 365, 269, 624, 751, 626, 625, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 368, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 543, - 571, 0, 584, 0, 432, 433, 0, 0, 0, 0, - 0, 0, 0, 350, 550, 568, 366, 537, 582, 371, - 545, 561, 361, 499, 533, 0, 0, 352, 566, 544, - 477, 351, 0, 526, 391, 408, 388, 497, 0, 0, - 565, 595, 387, 585, 0, 576, 354, 0, 575, 496, - 469, 562, 567, 478, 471, 0, 353, 564, 476, 470, - 446, 398, 611, 447, 448, 449, 450, 451, 452, 412, - 512, 467, 513, 413, 484, 483, 485, 414, 415, 416, - 417, 418, 419, 420, 421, 422, 423, 0, 0, 0, - 0, 0, 606, 607, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 743, - 0, 0, 748, 0, 578, 0, 0, 0, 0, 0, - 0, 548, 0, 0, 453, 0, 0, 0, 596, 0, - 529, 502, 789, 0, 0, 527, 465, 563, 514, 569, - 551, 577, 521, 515, 344, 552, 390, 479, 362, 364, - 776, 392, 395, 399, 400, 490, 491, 508, 536, 555, - 556, 557, 389, 376, 528, 377, 409, 378, 345, 381, - 380, 382, 538, 383, 347, 509, 560, 0, 405, 524, - 474, 348, 473, 510, 559, 558, 363, 586, 593, 594, - 685, 0, 599, 790, 791, 792, 608, 0, 516, 359, - 356, 0, 0, 0, 385, 511, 372, 374, 375, 373, - 505, 507, 613, 614, 615, 617, 0, 618, 619, 0, - 0, 0, 0, 620, 686, 704, 670, 639, 601, 694, - 636, 640, 641, 426, 427, 428, 429, 707, 0, 0, - 0, 592, 454, 455, 0, 397, 396, 475, 349, 0, - 0, 443, 425, 517, 355, 393, 445, 431, 456, 457, - 458, 459, 460, 0, 461, 462, 403, 339, 340, 784, - 386, 498, 709, 746, 747, 631, 0, 695, 632, 642, - 379, 667, 679, 678, 492, 591, 0, 690, 693, 621, - 783, 0, 687, 701, 788, 700, 780, 504, 0, 535, - 698, 645, 0, 691, 664, 665, 0, 692, 660, 696, - 0, 633, 0, 602, 605, 635, 722, 723, 724, 346, - 604, 726, 727, 728, 729, 730, 731, 732, 725, 574, - 668, 644, 671, 583, 647, 646, 0, 0, 682, 600, - 683, 684, 486, 487, 488, 489, 407, 710, 370, 603, - 519, 520, 0, 669, 0, 0, 0, 0, 0, 0, - 0, 0, 674, 675, 672, 793, 0, 733, 734, 0, - 0, 597, 598, 402, 0, 616, 410, 369, 503, 404, - 581, 434, 0, 609, 676, 610, 522, 523, 737, 742, - 738, 739, 741, 762, 493, 424, 430, 539, 444, 466, - 525, 580, 501, 530, 367, 570, 541, 472, 661, 689, + 324, 0, 0, 0, 0, 333, 771, 772, 773, 774, + 775, 0, 0, 334, 335, 336, 0, 0, 299, 300, + 327, 552, 328, 329, 330, 331, 0, 0, 591, 592, + 593, 616, 0, 594, 575, 641, 412, 342, 556, 583, + 782, 783, 0, 0, 0, 0, 0, 0, 0, 692, + 703, 739, 740, 0, 753, 754, 756, 758, 757, 760, + 549, 550, 768, 0, 0, 437, 358, 359, 496, 497, + 535, 0, 438, 439, 440, 444, 441, 442, 443, 762, + 763, 764, 761, 470, 534, 557, 543, 781, 483, 0, + 789, 631, 632, 790, 749, 748, 343, 0, 337, 338, + 706, 707, 0, 0, 537, 482, 638, 502, 0, 0, + 647, 681, 670, 759, 634, 0, 0, 1448, 0, 0, + 0, 0, 0, 0, 0, 395, 0, 0, 465, 685, + 666, 677, 667, 508, 652, 653, 654, 661, 407, 655, + 791, 657, 626, 658, 627, 659, 660, 0, 684, 633, + 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 718, 717, 716, - 715, 714, 713, 712, 711, 0, 0, 658, 384, 781, - 775, 782, 763, 766, 765, 740, 0, 341, 638, 464, - 518, 401, 705, 706, 0, 761, 284, 285, 286, 287, - 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, - 297, 298, 303, 304, 305, 306, 307, 308, 309, 310, - 708, 301, 302, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 324, 0, 0, 0, - 0, 333, 767, 768, 769, 770, 771, 0, 0, 334, - 335, 336, 0, 0, 299, 300, 327, 549, 328, 329, - 330, 331, 0, 0, 587, 588, 589, 612, 0, 590, - 572, 637, 411, 342, 553, 579, 778, 779, 0, 0, - 0, 0, 0, 0, 0, 688, 699, 735, 736, 0, - 749, 750, 752, 754, 753, 756, 546, 547, 764, 0, - 0, 435, 357, 358, 494, 495, 532, 0, 436, 437, - 438, 442, 439, 440, 441, 758, 759, 760, 757, 468, - 531, 554, 540, 777, 481, 0, 785, 627, 628, 786, - 745, 744, 343, 0, 337, 338, 702, 703, 0, 0, - 534, 480, 634, 500, 0, 0, 643, 677, 666, 755, - 630, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 394, 0, 0, 463, 681, 662, 673, 663, 506, - 648, 649, 650, 657, 406, 651, 787, 653, 622, 654, - 623, 655, 656, 0, 680, 629, 542, 482, 0, 697, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 268, 0, 0, 0, 2382, 0, 0, 365, 269, - 624, 751, 626, 625, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 368, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 543, 571, 0, 584, 0, 432, - 433, 0, 0, 0, 0, 0, 0, 0, 350, 550, - 568, 366, 537, 582, 371, 545, 561, 361, 499, 533, - 0, 0, 352, 566, 544, 477, 351, 0, 526, 391, - 408, 388, 497, 0, 0, 565, 595, 387, 585, 0, - 576, 354, 0, 575, 496, 469, 562, 567, 478, 471, - 0, 353, 564, 476, 470, 446, 398, 611, 447, 448, - 449, 450, 451, 452, 412, 512, 467, 513, 413, 484, - 483, 485, 414, 415, 416, 417, 418, 419, 420, 421, - 422, 423, 0, 0, 0, 0, 0, 606, 607, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 743, 0, 0, 748, 0, 578, - 0, 0, 0, 0, 0, 0, 548, 0, 0, 453, - 0, 0, 0, 596, 0, 529, 502, 789, 0, 0, - 527, 465, 563, 514, 569, 551, 577, 521, 515, 344, - 552, 390, 479, 362, 364, 776, 392, 395, 399, 400, - 490, 491, 508, 536, 555, 556, 557, 389, 376, 528, - 377, 409, 378, 345, 381, 380, 382, 538, 383, 347, - 509, 560, 0, 405, 524, 474, 348, 473, 510, 559, - 558, 363, 586, 593, 594, 685, 0, 599, 790, 791, - 792, 608, 0, 516, 359, 356, 0, 0, 0, 385, - 511, 372, 374, 375, 373, 505, 507, 613, 614, 615, - 617, 0, 618, 619, 0, 0, 0, 0, 620, 686, - 704, 670, 639, 601, 694, 636, 640, 641, 426, 427, - 428, 429, 707, 0, 0, 0, 592, 454, 455, 0, - 397, 396, 475, 349, 0, 0, 443, 425, 517, 355, - 393, 445, 431, 456, 457, 458, 459, 460, 0, 461, - 462, 403, 339, 340, 784, 386, 498, 709, 746, 747, - 631, 0, 695, 632, 642, 379, 667, 679, 678, 492, - 591, 0, 690, 693, 621, 783, 0, 687, 701, 788, - 700, 780, 504, 0, 535, 698, 645, 0, 691, 664, - 665, 0, 692, 660, 696, 0, 633, 0, 602, 605, - 635, 722, 723, 724, 346, 604, 726, 727, 728, 729, - 730, 731, 732, 725, 574, 668, 644, 671, 583, 647, - 646, 0, 0, 682, 600, 683, 684, 486, 487, 488, - 489, 407, 710, 370, 603, 519, 520, 0, 669, 0, - 0, 0, 0, 0, 0, 0, 0, 674, 675, 672, - 793, 0, 733, 734, 0, 0, 597, 598, 402, 0, - 616, 410, 369, 503, 404, 581, 434, 0, 609, 676, - 610, 522, 523, 737, 742, 738, 739, 741, 762, 493, - 424, 430, 539, 444, 466, 525, 580, 501, 530, 367, - 570, 541, 472, 661, 689, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, + 0, 0, 0, 0, 0, 268, 0, 0, 0, 0, + 0, 0, 366, 269, 628, 755, 630, 629, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 369, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 546, 574, + 0, 588, 0, 434, 435, 0, 0, 0, 0, 0, + 0, 0, 350, 553, 571, 367, 540, 586, 372, 548, + 564, 362, 501, 536, 0, 0, 352, 569, 547, 479, + 351, 0, 529, 392, 409, 389, 499, 0, 0, 568, + 599, 388, 589, 0, 579, 354, 0, 578, 498, 471, + 565, 570, 480, 473, 0, 353, 567, 478, 472, 448, + 399, 615, 449, 450, 451, 452, 453, 454, 413, 514, + 469, 515, 414, 486, 485, 487, 415, 416, 417, 418, + 419, 420, 421, 422, 423, 424, 0, 0, 0, 0, + 0, 610, 611, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 747, 0, + 0, 752, 0, 582, 0, 0, 0, 0, 0, 0, + 551, 0, 0, 455, 0, 0, 0, 600, 0, 532, + 504, 793, 0, 0, 530, 467, 566, 516, 572, 554, + 580, 523, 517, 344, 555, 391, 481, 363, 365, 780, + 393, 396, 400, 401, 492, 493, 510, 539, 558, 559, + 560, 390, 377, 531, 378, 410, 379, 345, 382, 381, + 383, 541, 384, 347, 511, 563, 0, 406, 527, 476, + 348, 475, 512, 562, 561, 364, 590, 597, 598, 689, + 0, 603, 794, 795, 796, 612, 0, 518, 360, 357, + 0, 0, 0, 386, 513, 373, 375, 376, 374, 507, + 509, 617, 618, 619, 621, 0, 622, 623, 0, 0, + 0, 0, 624, 690, 708, 674, 643, 605, 698, 640, + 644, 645, 427, 428, 429, 430, 711, 0, 0, 0, + 596, 456, 457, 0, 398, 397, 477, 349, 0, 0, + 445, 426, 519, 355, 394, 447, 432, 458, 459, 460, + 461, 462, 0, 463, 464, 404, 339, 340, 788, 387, + 500, 713, 750, 751, 635, 0, 699, 636, 646, 380, + 671, 683, 682, 494, 595, 0, 694, 697, 625, 787, + 0, 691, 705, 792, 704, 784, 506, 0, 538, 702, + 649, 0, 695, 668, 669, 0, 696, 664, 700, 356, + 433, 524, 581, 0, 637, 0, 606, 609, 639, 726, + 727, 728, 346, 608, 730, 731, 732, 733, 734, 735, + 736, 729, 577, 672, 648, 675, 587, 651, 650, 0, + 0, 686, 604, 687, 688, 488, 489, 490, 491, 408, + 714, 371, 607, 521, 522, 0, 673, 0, 0, 0, + 0, 0, 0, 0, 0, 678, 679, 676, 797, 0, + 737, 738, 0, 0, 601, 602, 403, 0, 620, 411, + 370, 505, 405, 585, 436, 0, 613, 680, 614, 525, + 526, 741, 746, 742, 743, 745, 766, 495, 425, 431, + 542, 446, 468, 528, 584, 503, 533, 368, 573, 544, + 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 718, 717, 716, 715, 714, 713, 712, 711, - 0, 0, 658, 384, 781, 775, 782, 763, 766, 765, - 740, 0, 341, 638, 464, 518, 401, 705, 706, 0, - 761, 284, 285, 286, 287, 288, 289, 290, 291, 332, - 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, - 306, 307, 308, 309, 310, 708, 301, 302, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 324, 0, 0, 0, 0, 333, 767, 768, 769, - 770, 771, 0, 0, 334, 335, 336, 0, 0, 299, - 300, 327, 549, 328, 329, 330, 331, 0, 0, 587, - 588, 589, 612, 0, 590, 572, 637, 411, 342, 553, - 579, 778, 779, 0, 0, 0, 0, 0, 0, 0, - 688, 699, 735, 736, 0, 749, 750, 752, 754, 753, - 756, 546, 547, 764, 0, 0, 435, 357, 358, 494, - 495, 532, 0, 436, 437, 438, 442, 439, 440, 441, - 758, 759, 760, 757, 468, 531, 554, 540, 777, 481, - 0, 785, 627, 628, 786, 745, 744, 343, 0, 337, - 338, 702, 703, 0, 0, 534, 480, 634, 500, 0, - 0, 643, 677, 666, 755, 630, 0, 0, 1444, 0, - 0, 0, 0, 0, 0, 0, 394, 0, 0, 463, - 681, 662, 673, 663, 506, 648, 649, 650, 657, 406, - 651, 787, 653, 622, 654, 623, 655, 656, 0, 680, - 629, 542, 482, 0, 697, 0, 0, 0, 0, 0, + 722, 721, 720, 719, 718, 717, 716, 715, 0, 0, + 662, 385, 785, 779, 786, 767, 770, 769, 2601, 0, + 341, 642, 466, 520, 402, 709, 710, 0, 765, 284, + 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, + 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, + 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 0, 0, 0, 0, 333, 771, 772, 773, 774, 775, + 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, + 552, 328, 329, 330, 331, 0, 0, 591, 592, 593, + 616, 0, 594, 575, 641, 412, 342, 556, 583, 782, + 783, 0, 0, 0, 0, 0, 0, 0, 692, 703, + 739, 740, 0, 753, 754, 756, 758, 757, 760, 549, + 550, 768, 0, 0, 437, 358, 359, 496, 497, 535, + 0, 438, 439, 440, 444, 441, 442, 443, 762, 763, + 764, 761, 470, 534, 557, 543, 781, 483, 0, 789, + 631, 632, 790, 749, 748, 343, 0, 337, 338, 706, + 707, 0, 0, 537, 482, 638, 502, 0, 0, 647, + 681, 670, 759, 634, 0, 2537, 0, 0, 0, 0, + 0, 0, 0, 0, 395, 0, 0, 465, 685, 666, + 677, 667, 508, 652, 653, 654, 661, 407, 655, 791, + 657, 626, 658, 627, 659, 660, 0, 684, 633, 545, + 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 268, 0, 0, 0, - 0, 0, 0, 365, 269, 624, 751, 626, 625, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 368, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 543, - 571, 0, 584, 0, 432, 433, 0, 0, 0, 0, - 0, 0, 0, 350, 550, 568, 366, 537, 582, 371, - 545, 561, 361, 499, 533, 0, 0, 352, 566, 544, - 477, 351, 0, 526, 391, 408, 388, 497, 0, 0, - 565, 595, 387, 585, 0, 576, 354, 0, 575, 496, - 469, 562, 567, 478, 471, 0, 353, 564, 476, 470, - 446, 398, 611, 447, 448, 449, 450, 451, 452, 412, - 512, 467, 513, 413, 484, 483, 485, 414, 415, 416, - 417, 418, 419, 420, 421, 422, 423, 0, 0, 0, - 0, 0, 606, 607, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 743, - 0, 0, 748, 0, 578, 0, 0, 0, 0, 0, - 0, 548, 0, 0, 453, 0, 0, 0, 596, 0, - 529, 502, 789, 0, 0, 527, 465, 563, 514, 569, - 551, 577, 521, 515, 344, 552, 390, 479, 362, 364, - 776, 392, 395, 399, 400, 490, 491, 508, 536, 555, - 556, 557, 389, 376, 528, 377, 409, 378, 345, 381, - 380, 382, 538, 383, 347, 509, 560, 0, 405, 524, - 474, 348, 473, 510, 559, 558, 363, 586, 593, 594, - 685, 0, 599, 790, 791, 792, 608, 0, 516, 359, - 356, 0, 0, 0, 385, 511, 372, 374, 375, 373, - 505, 507, 613, 614, 615, 617, 0, 618, 619, 0, - 0, 0, 0, 620, 686, 704, 670, 639, 601, 694, - 636, 640, 641, 426, 427, 428, 429, 707, 0, 0, - 0, 592, 454, 455, 0, 397, 396, 475, 349, 0, - 0, 443, 425, 517, 355, 393, 445, 431, 456, 457, - 458, 459, 460, 0, 461, 462, 403, 339, 340, 784, - 386, 498, 709, 746, 747, 631, 0, 695, 632, 642, - 379, 667, 679, 678, 492, 591, 0, 690, 693, 621, - 783, 0, 687, 701, 788, 700, 780, 504, 0, 535, - 698, 645, 0, 691, 664, 665, 0, 692, 660, 696, - 0, 633, 0, 602, 605, 635, 722, 723, 724, 346, - 604, 726, 727, 728, 729, 730, 731, 732, 725, 574, - 668, 644, 671, 583, 647, 646, 0, 0, 682, 600, - 683, 684, 486, 487, 488, 489, 407, 710, 370, 603, - 519, 520, 0, 669, 0, 0, 0, 0, 0, 0, - 0, 0, 674, 675, 672, 793, 0, 733, 734, 0, - 0, 597, 598, 402, 0, 616, 410, 369, 503, 404, - 581, 434, 0, 609, 676, 610, 522, 523, 737, 742, - 738, 739, 741, 762, 493, 424, 430, 539, 444, 466, - 525, 580, 501, 530, 367, 570, 541, 472, 661, 689, + 0, 0, 0, 0, 268, 0, 0, 0, 0, 0, + 0, 366, 269, 628, 755, 630, 629, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 369, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 546, 574, 0, + 588, 0, 434, 435, 0, 0, 0, 0, 0, 0, + 0, 350, 553, 571, 367, 540, 586, 372, 548, 564, + 362, 501, 536, 0, 0, 352, 569, 547, 479, 351, + 0, 529, 392, 409, 389, 499, 0, 0, 568, 599, + 388, 589, 0, 579, 354, 0, 578, 498, 471, 565, + 570, 480, 473, 0, 353, 567, 478, 472, 448, 399, + 615, 449, 450, 451, 452, 453, 454, 413, 514, 469, + 515, 414, 486, 485, 487, 415, 416, 417, 418, 419, + 420, 421, 422, 423, 424, 0, 0, 0, 0, 0, + 610, 611, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 747, 0, 0, + 752, 0, 582, 0, 0, 0, 0, 0, 0, 551, + 0, 0, 455, 0, 0, 0, 600, 0, 532, 504, + 793, 0, 0, 530, 467, 566, 516, 572, 554, 580, + 523, 517, 344, 555, 391, 481, 363, 365, 780, 393, + 396, 400, 401, 492, 493, 510, 539, 558, 559, 560, + 390, 377, 531, 378, 410, 379, 345, 382, 381, 383, + 541, 384, 347, 511, 563, 0, 406, 527, 476, 348, + 475, 512, 562, 561, 364, 590, 597, 598, 689, 0, + 603, 794, 795, 796, 612, 0, 518, 360, 357, 0, + 0, 0, 386, 513, 373, 375, 376, 374, 507, 509, + 617, 618, 619, 621, 0, 622, 623, 0, 0, 0, + 0, 624, 690, 708, 674, 643, 605, 698, 640, 644, + 645, 427, 428, 429, 430, 711, 0, 0, 0, 596, + 456, 457, 0, 398, 397, 477, 349, 0, 0, 445, + 426, 519, 355, 394, 447, 432, 458, 459, 460, 461, + 462, 0, 463, 464, 404, 339, 340, 788, 387, 500, + 713, 750, 751, 635, 0, 699, 636, 646, 380, 671, + 683, 682, 494, 595, 0, 694, 697, 625, 787, 0, + 691, 705, 792, 704, 784, 506, 0, 538, 702, 649, + 0, 695, 668, 669, 0, 696, 664, 700, 356, 433, + 524, 581, 0, 637, 0, 606, 609, 639, 726, 727, + 728, 346, 608, 730, 731, 732, 733, 734, 735, 736, + 729, 577, 672, 648, 675, 587, 651, 650, 0, 0, + 686, 604, 687, 688, 488, 489, 490, 491, 408, 714, + 371, 607, 521, 522, 0, 673, 0, 0, 0, 0, + 0, 0, 0, 0, 678, 679, 676, 797, 0, 737, + 738, 0, 0, 601, 602, 403, 0, 620, 411, 370, + 505, 405, 585, 436, 0, 613, 680, 614, 525, 526, + 741, 746, 742, 743, 745, 766, 495, 425, 431, 542, + 446, 468, 528, 584, 503, 533, 368, 573, 544, 474, + 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 722, + 721, 720, 719, 718, 717, 716, 715, 0, 0, 662, + 385, 785, 779, 786, 767, 770, 769, 744, 0, 341, + 642, 466, 520, 402, 709, 710, 0, 765, 284, 285, + 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, + 295, 296, 297, 298, 303, 304, 305, 306, 307, 308, + 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, + 0, 0, 0, 333, 771, 772, 773, 774, 775, 0, + 0, 334, 335, 336, 0, 0, 299, 300, 327, 552, + 328, 329, 330, 331, 0, 0, 591, 592, 593, 616, + 0, 594, 575, 641, 412, 342, 556, 583, 782, 783, + 0, 0, 0, 0, 0, 0, 0, 692, 703, 739, + 740, 0, 753, 754, 756, 758, 757, 760, 549, 550, + 768, 0, 0, 437, 358, 359, 496, 497, 535, 0, + 438, 439, 440, 444, 441, 442, 443, 762, 763, 764, + 761, 470, 534, 557, 543, 781, 483, 0, 789, 631, + 632, 790, 749, 748, 343, 0, 337, 338, 706, 707, + 0, 0, 537, 482, 638, 502, 0, 0, 647, 681, + 670, 759, 634, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 395, 0, 0, 465, 685, 666, 677, + 667, 508, 652, 653, 654, 661, 407, 655, 791, 657, + 626, 658, 627, 659, 660, 0, 684, 633, 545, 484, + 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 268, 0, 0, 1870, 0, 0, 0, + 366, 269, 628, 755, 630, 629, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 369, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 546, 574, 0, 588, + 0, 434, 435, 0, 0, 0, 0, 0, 0, 0, + 350, 553, 571, 367, 540, 586, 372, 548, 564, 362, + 501, 536, 0, 0, 352, 569, 547, 479, 351, 0, + 529, 392, 409, 389, 499, 0, 0, 568, 599, 388, + 589, 0, 579, 354, 0, 578, 498, 471, 565, 570, + 480, 473, 0, 353, 567, 478, 472, 448, 399, 615, + 449, 450, 451, 452, 453, 454, 413, 514, 469, 515, + 414, 486, 485, 487, 415, 416, 417, 418, 419, 420, + 421, 422, 423, 424, 0, 0, 0, 0, 0, 610, + 611, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 747, 0, 0, 752, + 0, 582, 0, 0, 0, 0, 0, 0, 551, 0, + 0, 455, 0, 0, 0, 600, 0, 532, 504, 793, + 0, 0, 530, 467, 566, 516, 572, 554, 580, 2071, + 517, 344, 555, 391, 481, 363, 365, 780, 393, 396, + 400, 401, 492, 493, 510, 539, 558, 559, 560, 390, + 377, 531, 378, 410, 379, 345, 382, 381, 383, 541, + 384, 347, 511, 563, 0, 406, 527, 476, 348, 475, + 512, 562, 561, 364, 590, 597, 598, 689, 0, 603, + 794, 795, 796, 612, 0, 518, 360, 357, 0, 0, + 0, 386, 513, 373, 375, 376, 374, 507, 509, 617, + 618, 619, 621, 0, 622, 623, 0, 0, 0, 0, + 624, 690, 708, 674, 643, 605, 698, 640, 644, 645, + 427, 428, 429, 430, 711, 0, 0, 0, 596, 456, + 457, 0, 398, 397, 477, 349, 0, 0, 445, 426, + 519, 355, 394, 447, 432, 458, 459, 460, 461, 462, + 0, 463, 464, 404, 339, 340, 788, 387, 500, 713, + 750, 751, 635, 0, 699, 636, 646, 380, 671, 683, + 682, 494, 595, 0, 694, 697, 625, 787, 0, 691, + 705, 792, 704, 784, 506, 0, 538, 702, 649, 0, + 695, 668, 669, 0, 696, 664, 700, 356, 433, 524, + 581, 0, 637, 0, 606, 609, 639, 726, 727, 728, + 346, 608, 730, 731, 732, 733, 734, 735, 736, 729, + 577, 672, 648, 675, 587, 651, 650, 0, 0, 686, + 604, 687, 688, 488, 489, 490, 491, 408, 714, 371, + 607, 521, 522, 0, 673, 0, 0, 0, 0, 0, + 0, 0, 0, 678, 679, 676, 797, 0, 737, 738, + 0, 0, 601, 602, 403, 0, 620, 411, 370, 505, + 405, 585, 436, 0, 613, 680, 614, 525, 526, 741, + 746, 742, 743, 745, 766, 495, 425, 431, 542, 446, + 468, 528, 584, 503, 533, 368, 573, 544, 474, 665, + 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 722, 721, + 720, 719, 718, 717, 716, 715, 0, 0, 662, 385, + 785, 779, 786, 767, 770, 769, 744, 0, 341, 642, + 466, 520, 402, 709, 710, 0, 765, 284, 285, 286, + 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, + 296, 297, 298, 303, 304, 305, 306, 307, 308, 309, + 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 0, 0, + 0, 0, 333, 771, 772, 773, 774, 775, 0, 0, + 334, 335, 336, 0, 0, 299, 300, 327, 552, 328, + 329, 330, 331, 0, 0, 591, 592, 593, 616, 0, + 594, 575, 641, 412, 342, 556, 583, 782, 783, 0, + 0, 0, 0, 0, 0, 0, 692, 703, 739, 740, + 0, 753, 754, 756, 758, 757, 760, 549, 550, 768, + 0, 0, 437, 358, 359, 496, 497, 535, 0, 438, + 439, 440, 444, 441, 442, 443, 762, 763, 764, 761, + 470, 534, 557, 543, 781, 483, 0, 789, 631, 632, + 790, 749, 748, 343, 0, 337, 338, 706, 707, 0, + 0, 537, 482, 638, 502, 0, 0, 647, 681, 670, + 759, 634, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 395, 0, 0, 465, 685, 666, 677, 667, + 508, 652, 653, 654, 661, 407, 655, 791, 657, 626, + 658, 627, 659, 660, 0, 684, 633, 545, 484, 0, + 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 268, 0, 0, 0, 0, 0, 0, 366, + 269, 628, 755, 630, 629, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 369, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 546, 574, 0, 588, 0, + 434, 435, 0, 0, 0, 0, 0, 0, 0, 350, + 553, 571, 367, 540, 586, 372, 548, 564, 362, 501, + 536, 0, 0, 352, 569, 547, 479, 351, 0, 529, + 392, 409, 389, 499, 0, 0, 568, 599, 388, 589, + 0, 579, 354, 0, 578, 498, 471, 565, 570, 480, + 473, 0, 353, 567, 478, 472, 448, 399, 615, 449, + 450, 451, 452, 453, 454, 413, 514, 469, 515, 414, + 486, 485, 487, 415, 416, 417, 418, 419, 420, 421, + 422, 423, 424, 0, 0, 0, 0, 0, 610, 611, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 747, 0, 0, 752, 0, + 582, 0, 0, 1913, 0, 0, 0, 551, 0, 0, + 455, 0, 0, 0, 600, 0, 532, 504, 793, 0, + 0, 530, 467, 566, 516, 572, 554, 580, 523, 517, + 344, 555, 391, 481, 363, 365, 780, 393, 396, 400, + 401, 492, 493, 510, 539, 558, 559, 560, 390, 377, + 531, 378, 410, 379, 345, 382, 381, 383, 541, 384, + 347, 511, 563, 0, 406, 527, 476, 348, 475, 512, + 562, 561, 364, 590, 597, 598, 689, 0, 603, 794, + 795, 796, 612, 0, 518, 360, 357, 0, 0, 0, + 386, 513, 373, 375, 376, 374, 507, 509, 617, 618, + 619, 621, 0, 622, 623, 0, 0, 0, 0, 624, + 690, 708, 674, 643, 605, 698, 640, 644, 645, 427, + 428, 429, 430, 711, 0, 0, 0, 596, 456, 457, + 0, 398, 397, 477, 349, 0, 0, 445, 426, 519, + 355, 394, 447, 432, 458, 459, 460, 461, 462, 0, + 463, 464, 404, 339, 340, 788, 387, 500, 713, 750, + 751, 635, 0, 699, 636, 646, 380, 671, 683, 682, + 494, 595, 0, 694, 697, 625, 787, 0, 691, 705, + 792, 704, 784, 506, 0, 538, 702, 649, 0, 695, + 668, 669, 0, 696, 664, 700, 356, 433, 524, 581, + 0, 637, 0, 606, 609, 639, 726, 727, 728, 346, + 608, 730, 731, 732, 733, 734, 735, 736, 729, 577, + 672, 648, 675, 587, 651, 650, 0, 0, 686, 604, + 687, 688, 488, 489, 490, 491, 408, 714, 371, 607, + 521, 522, 0, 673, 0, 0, 0, 0, 0, 0, + 0, 0, 678, 679, 676, 797, 0, 737, 738, 0, + 0, 601, 602, 403, 0, 620, 411, 370, 505, 405, + 585, 436, 0, 613, 680, 614, 525, 526, 741, 746, + 742, 743, 745, 766, 495, 425, 431, 542, 446, 468, + 528, 584, 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 718, 717, 716, - 715, 714, 713, 712, 711, 0, 0, 658, 384, 781, - 775, 782, 763, 766, 765, 2597, 0, 341, 638, 464, - 518, 401, 705, 706, 0, 761, 284, 285, 286, 287, + 0, 0, 0, 0, 0, 0, 0, 722, 721, 720, + 719, 718, 717, 716, 715, 0, 0, 662, 385, 785, + 779, 786, 767, 770, 769, 744, 0, 341, 642, 466, + 520, 402, 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, 308, 309, 310, - 708, 301, 302, 311, 312, 313, 314, 315, 316, 317, + 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, 0, 0, - 0, 333, 767, 768, 769, 770, 771, 0, 0, 334, - 335, 336, 0, 0, 299, 300, 327, 549, 328, 329, - 330, 331, 0, 0, 587, 588, 589, 612, 0, 590, - 572, 637, 411, 342, 553, 579, 778, 779, 0, 0, - 0, 0, 0, 0, 0, 688, 699, 735, 736, 0, - 749, 750, 752, 754, 753, 756, 546, 547, 764, 0, - 0, 435, 357, 358, 494, 495, 532, 0, 436, 437, - 438, 442, 439, 440, 441, 758, 759, 760, 757, 468, - 531, 554, 540, 777, 481, 0, 785, 627, 628, 786, - 745, 744, 343, 0, 337, 338, 702, 703, 0, 0, - 534, 480, 634, 500, 0, 0, 643, 677, 666, 755, - 630, 0, 2533, 0, 0, 0, 0, 0, 0, 0, - 0, 394, 0, 0, 463, 681, 662, 673, 663, 506, - 648, 649, 650, 657, 406, 651, 787, 653, 622, 654, - 623, 655, 656, 0, 680, 629, 542, 482, 0, 697, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 268, 0, 0, 0, 0, 0, 0, 365, 269, - 624, 751, 626, 625, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 368, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 543, 571, 0, 584, 0, 432, - 433, 0, 0, 0, 0, 0, 0, 0, 350, 550, - 568, 366, 537, 582, 371, 545, 561, 361, 499, 533, - 0, 0, 352, 566, 544, 477, 351, 0, 526, 391, - 408, 388, 497, 0, 0, 565, 595, 387, 585, 0, - 576, 354, 0, 575, 496, 469, 562, 567, 478, 471, - 0, 353, 564, 476, 470, 446, 398, 611, 447, 448, - 449, 450, 451, 452, 412, 512, 467, 513, 413, 484, - 483, 485, 414, 415, 416, 417, 418, 419, 420, 421, - 422, 423, 0, 0, 0, 0, 0, 606, 607, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 743, 0, 0, 748, 0, 578, - 0, 0, 0, 0, 0, 0, 548, 0, 0, 453, - 0, 0, 0, 596, 0, 529, 502, 789, 0, 0, - 527, 465, 563, 514, 569, 551, 577, 521, 515, 344, - 552, 390, 479, 362, 364, 776, 392, 395, 399, 400, - 490, 491, 508, 536, 555, 556, 557, 389, 376, 528, - 377, 409, 378, 345, 381, 380, 382, 538, 383, 347, - 509, 560, 0, 405, 524, 474, 348, 473, 510, 559, - 558, 363, 586, 593, 594, 685, 0, 599, 790, 791, - 792, 608, 0, 516, 359, 356, 0, 0, 0, 385, - 511, 372, 374, 375, 373, 505, 507, 613, 614, 615, - 617, 0, 618, 619, 0, 0, 0, 0, 620, 686, - 704, 670, 639, 601, 694, 636, 640, 641, 426, 427, - 428, 429, 707, 0, 0, 0, 592, 454, 455, 0, - 397, 396, 475, 349, 0, 0, 443, 425, 517, 355, - 393, 445, 431, 456, 457, 458, 459, 460, 0, 461, - 462, 403, 339, 340, 784, 386, 498, 709, 746, 747, - 631, 0, 695, 632, 642, 379, 667, 679, 678, 492, - 591, 0, 690, 693, 621, 783, 0, 687, 701, 788, - 700, 780, 504, 0, 535, 698, 645, 0, 691, 664, - 665, 0, 692, 660, 696, 0, 633, 0, 602, 605, - 635, 722, 723, 724, 346, 604, 726, 727, 728, 729, - 730, 731, 732, 725, 574, 668, 644, 671, 583, 647, - 646, 0, 0, 682, 600, 683, 684, 486, 487, 488, - 489, 407, 710, 370, 603, 519, 520, 0, 669, 0, - 0, 0, 0, 0, 0, 0, 0, 674, 675, 672, - 793, 0, 733, 734, 0, 0, 597, 598, 402, 0, - 616, 410, 369, 503, 404, 581, 434, 0, 609, 676, - 610, 522, 523, 737, 742, 738, 739, 741, 762, 493, - 424, 430, 539, 444, 466, 525, 580, 501, 530, 367, - 570, 541, 472, 661, 689, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, + 0, 333, 771, 772, 773, 774, 775, 0, 0, 334, + 335, 336, 0, 0, 299, 300, 327, 552, 328, 329, + 330, 331, 0, 0, 591, 592, 593, 616, 0, 594, + 575, 641, 412, 342, 556, 583, 782, 783, 0, 0, + 0, 0, 0, 0, 0, 692, 703, 739, 740, 0, + 753, 754, 756, 758, 757, 760, 549, 550, 768, 0, + 0, 437, 358, 359, 496, 497, 535, 0, 438, 439, + 440, 444, 441, 442, 443, 762, 763, 764, 761, 470, + 534, 557, 543, 781, 483, 0, 789, 631, 632, 790, + 749, 748, 343, 0, 337, 338, 706, 707, 0, 0, + 537, 482, 638, 502, 0, 0, 647, 681, 670, 759, + 634, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1209, 395, 0, 0, 465, 685, 666, 677, 667, 508, + 652, 653, 654, 661, 407, 655, 791, 657, 626, 658, + 627, 659, 660, 0, 684, 633, 545, 484, 0, 701, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 268, 0, 0, 0, 0, 0, 0, 366, 269, + 628, 755, 630, 629, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 369, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 546, 574, 0, 588, 0, 434, + 435, 0, 0, 0, 0, 0, 0, 0, 350, 553, + 571, 367, 540, 586, 372, 548, 564, 362, 501, 536, + 0, 0, 352, 569, 547, 479, 351, 0, 529, 392, + 409, 389, 499, 0, 0, 568, 599, 388, 589, 0, + 579, 354, 0, 578, 498, 471, 565, 570, 480, 473, + 0, 353, 567, 478, 472, 448, 399, 615, 449, 450, + 451, 452, 453, 454, 413, 514, 469, 515, 414, 486, + 485, 487, 415, 416, 417, 418, 419, 420, 421, 422, + 423, 424, 0, 0, 0, 0, 0, 610, 611, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 747, 0, 0, 752, 0, 582, + 0, 0, 0, 0, 0, 0, 551, 0, 0, 455, + 0, 0, 0, 600, 0, 532, 504, 793, 0, 0, + 530, 467, 566, 516, 572, 554, 580, 523, 517, 344, + 555, 391, 481, 363, 365, 780, 393, 396, 400, 401, + 492, 493, 510, 539, 558, 559, 560, 390, 377, 531, + 378, 410, 379, 345, 382, 381, 383, 541, 384, 347, + 511, 563, 0, 406, 527, 476, 348, 475, 512, 562, + 561, 364, 590, 597, 598, 689, 0, 603, 794, 795, + 796, 612, 0, 518, 360, 357, 0, 0, 0, 386, + 513, 373, 375, 376, 374, 507, 509, 617, 618, 619, + 621, 0, 622, 623, 0, 0, 0, 0, 624, 690, + 708, 674, 643, 605, 698, 640, 644, 645, 427, 428, + 429, 430, 711, 0, 0, 0, 596, 456, 457, 0, + 398, 397, 477, 349, 0, 0, 445, 426, 519, 355, + 394, 447, 432, 458, 459, 460, 461, 462, 0, 463, + 464, 404, 339, 340, 788, 387, 500, 713, 750, 751, + 635, 0, 699, 636, 646, 380, 671, 683, 682, 494, + 595, 0, 694, 697, 625, 787, 0, 691, 705, 792, + 704, 784, 506, 0, 538, 702, 649, 0, 695, 668, + 669, 0, 696, 664, 700, 356, 433, 524, 581, 0, + 637, 0, 606, 609, 639, 726, 727, 728, 346, 608, + 730, 731, 732, 733, 734, 735, 736, 729, 577, 672, + 648, 675, 587, 651, 650, 0, 0, 686, 604, 687, + 688, 488, 489, 490, 491, 408, 714, 371, 607, 521, + 522, 0, 673, 0, 0, 0, 0, 0, 0, 0, + 0, 678, 679, 676, 797, 0, 737, 738, 0, 0, + 601, 602, 403, 0, 620, 411, 370, 505, 405, 585, + 436, 0, 613, 680, 614, 525, 526, 741, 746, 742, + 743, 745, 766, 495, 425, 431, 542, 446, 468, 528, + 584, 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 718, 717, 716, 715, 714, 713, 712, 711, - 0, 0, 658, 384, 781, 775, 782, 763, 766, 765, - 740, 0, 341, 638, 464, 518, 401, 705, 706, 0, - 761, 284, 285, 286, 287, 288, 289, 290, 291, 332, - 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, - 306, 307, 308, 309, 310, 708, 301, 302, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 324, 0, 0, 0, 0, 333, 767, 768, 769, - 770, 771, 0, 0, 334, 335, 336, 0, 0, 299, - 300, 327, 549, 328, 329, 330, 331, 0, 0, 587, - 588, 589, 612, 0, 590, 572, 637, 411, 342, 553, - 579, 778, 779, 0, 0, 0, 0, 0, 0, 0, - 688, 699, 735, 736, 0, 749, 750, 752, 754, 753, - 756, 546, 547, 764, 0, 0, 435, 357, 358, 494, - 495, 532, 0, 436, 437, 438, 442, 439, 440, 441, - 758, 759, 760, 757, 468, 531, 554, 540, 777, 481, - 0, 785, 627, 628, 786, 745, 744, 343, 0, 337, - 338, 702, 703, 0, 0, 534, 480, 634, 500, 0, - 0, 643, 677, 666, 755, 630, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 394, 0, 0, 463, - 681, 662, 673, 663, 506, 648, 649, 650, 657, 406, - 651, 787, 653, 622, 654, 623, 655, 656, 0, 680, - 629, 542, 482, 0, 697, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 268, 0, 0, 1866, - 0, 0, 0, 365, 269, 624, 751, 626, 625, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 368, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 543, - 571, 0, 584, 0, 432, 433, 0, 0, 0, 0, - 0, 0, 0, 350, 550, 568, 366, 537, 582, 371, - 545, 561, 361, 499, 533, 0, 0, 352, 566, 544, - 477, 351, 0, 526, 391, 408, 388, 497, 0, 0, - 565, 595, 387, 585, 0, 576, 354, 0, 575, 496, - 469, 562, 567, 478, 471, 0, 353, 564, 476, 470, - 446, 398, 611, 447, 448, 449, 450, 451, 452, 412, - 512, 467, 513, 413, 484, 483, 485, 414, 415, 416, - 417, 418, 419, 420, 421, 422, 423, 0, 0, 0, - 0, 0, 606, 607, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 743, - 0, 0, 748, 0, 578, 0, 0, 0, 0, 0, - 0, 548, 0, 0, 453, 0, 0, 0, 596, 0, - 529, 502, 789, 0, 0, 527, 465, 563, 514, 569, - 551, 577, 2067, 515, 344, 552, 390, 479, 362, 364, - 776, 392, 395, 399, 400, 490, 491, 508, 536, 555, - 556, 557, 389, 376, 528, 377, 409, 378, 345, 381, - 380, 382, 538, 383, 347, 509, 560, 0, 405, 524, - 474, 348, 473, 510, 559, 558, 363, 586, 593, 594, - 685, 0, 599, 790, 791, 792, 608, 0, 516, 359, - 356, 0, 0, 0, 385, 511, 372, 374, 375, 373, - 505, 507, 613, 614, 615, 617, 0, 618, 619, 0, - 0, 0, 0, 620, 686, 704, 670, 639, 601, 694, - 636, 640, 641, 426, 427, 428, 429, 707, 0, 0, - 0, 592, 454, 455, 0, 397, 396, 475, 349, 0, - 0, 443, 425, 517, 355, 393, 445, 431, 456, 457, - 458, 459, 460, 0, 461, 462, 403, 339, 340, 784, - 386, 498, 709, 746, 747, 631, 0, 695, 632, 642, - 379, 667, 679, 678, 492, 591, 0, 690, 693, 621, - 783, 0, 687, 701, 788, 700, 780, 504, 0, 535, - 698, 645, 0, 691, 664, 665, 0, 692, 660, 696, - 0, 633, 0, 602, 605, 635, 722, 723, 724, 346, - 604, 726, 727, 728, 729, 730, 731, 732, 725, 574, - 668, 644, 671, 583, 647, 646, 0, 0, 682, 600, - 683, 684, 486, 487, 488, 489, 407, 710, 370, 603, - 519, 520, 0, 669, 0, 0, 0, 0, 0, 0, - 0, 0, 674, 675, 672, 793, 0, 733, 734, 0, - 0, 597, 598, 402, 0, 616, 410, 369, 503, 404, - 581, 434, 0, 609, 676, 610, 522, 523, 737, 742, - 738, 739, 741, 762, 493, 424, 430, 539, 444, 466, - 525, 580, 501, 530, 367, 570, 541, 472, 661, 689, + 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 722, 721, 720, 719, + 718, 717, 716, 715, 0, 0, 662, 385, 785, 779, + 786, 767, 770, 769, 744, 0, 341, 642, 466, 520, + 402, 709, 710, 0, 765, 284, 285, 286, 287, 288, + 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, + 298, 303, 304, 305, 306, 307, 308, 309, 310, 712, + 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, + 333, 771, 772, 773, 774, 775, 0, 0, 334, 335, + 336, 0, 0, 299, 300, 327, 552, 328, 329, 330, + 331, 0, 0, 591, 592, 593, 616, 0, 594, 575, + 641, 412, 342, 556, 583, 782, 783, 0, 0, 0, + 0, 0, 0, 0, 692, 703, 739, 740, 0, 753, + 754, 756, 758, 757, 760, 549, 550, 768, 0, 0, + 437, 358, 359, 496, 497, 535, 0, 438, 439, 440, + 444, 441, 442, 443, 762, 763, 764, 761, 470, 534, + 557, 543, 781, 483, 0, 789, 631, 632, 790, 749, + 748, 343, 0, 337, 338, 706, 707, 0, 0, 537, + 482, 638, 502, 0, 0, 647, 681, 670, 759, 634, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 395, 0, 0, 465, 685, 666, 677, 667, 508, 652, + 653, 654, 661, 407, 655, 791, 657, 626, 658, 627, + 659, 660, 0, 684, 633, 545, 484, 0, 701, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 268, 0, 0, 0, 0, 0, 0, 366, 269, 628, + 755, 630, 629, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 369, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 546, 574, 0, 588, 0, 434, 435, + 0, 0, 0, 0, 0, 0, 0, 350, 553, 571, + 367, 540, 586, 372, 548, 564, 362, 501, 536, 0, + 0, 352, 569, 547, 479, 351, 0, 529, 392, 409, + 389, 499, 0, 0, 568, 599, 388, 589, 0, 579, + 354, 0, 578, 498, 471, 565, 570, 480, 473, 0, + 353, 567, 478, 472, 448, 399, 615, 449, 450, 451, + 452, 453, 454, 413, 514, 469, 515, 414, 486, 485, + 487, 415, 416, 417, 418, 419, 420, 421, 422, 423, + 424, 0, 0, 0, 0, 0, 610, 611, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 747, 0, 816, 752, 0, 582, 0, + 0, 0, 0, 0, 0, 551, 0, 0, 455, 0, + 0, 0, 600, 0, 532, 504, 793, 0, 0, 530, + 467, 566, 516, 572, 554, 580, 523, 517, 344, 555, + 391, 481, 363, 365, 780, 393, 396, 400, 401, 492, + 493, 510, 539, 558, 559, 560, 390, 377, 531, 378, + 410, 379, 345, 382, 381, 383, 541, 384, 347, 511, + 563, 0, 406, 527, 476, 348, 475, 512, 562, 561, + 364, 590, 597, 598, 689, 0, 603, 794, 795, 796, + 612, 0, 518, 360, 357, 0, 0, 0, 386, 513, + 373, 375, 376, 374, 507, 509, 617, 618, 619, 621, + 0, 622, 623, 0, 0, 0, 0, 624, 690, 708, + 674, 643, 605, 698, 640, 644, 645, 427, 428, 429, + 430, 711, 0, 0, 0, 596, 456, 457, 0, 398, + 397, 477, 349, 0, 0, 445, 426, 519, 355, 394, + 447, 432, 458, 459, 460, 461, 462, 0, 463, 464, + 404, 339, 340, 788, 387, 500, 713, 750, 751, 635, + 0, 699, 636, 646, 380, 671, 683, 682, 494, 595, + 0, 694, 697, 625, 787, 0, 691, 705, 792, 704, + 784, 506, 0, 538, 702, 649, 0, 695, 668, 669, + 0, 696, 664, 700, 356, 433, 524, 581, 0, 637, + 0, 606, 609, 639, 726, 727, 728, 346, 608, 730, + 731, 732, 733, 734, 735, 736, 729, 577, 672, 648, + 675, 587, 651, 650, 0, 0, 686, 604, 687, 688, + 488, 489, 490, 491, 408, 714, 371, 607, 521, 522, + 0, 673, 0, 0, 0, 0, 0, 0, 0, 0, + 678, 679, 676, 797, 0, 737, 738, 0, 0, 601, + 602, 403, 0, 620, 411, 370, 505, 405, 585, 436, + 0, 613, 680, 614, 525, 526, 741, 746, 742, 743, + 745, 766, 495, 425, 431, 542, 446, 468, 528, 584, + 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, + 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 722, 721, 720, 719, 718, + 717, 716, 715, 0, 0, 662, 385, 785, 779, 786, + 767, 770, 769, 744, 0, 341, 642, 466, 520, 402, + 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, + 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, + 303, 304, 305, 306, 307, 308, 309, 310, 712, 301, + 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, + 771, 772, 773, 774, 775, 0, 0, 334, 335, 336, + 0, 0, 299, 300, 327, 552, 328, 329, 330, 331, + 0, 0, 591, 592, 593, 616, 0, 594, 575, 641, + 412, 342, 556, 583, 782, 783, 0, 0, 0, 0, + 0, 0, 0, 692, 703, 739, 740, 0, 753, 754, + 756, 758, 757, 760, 549, 550, 768, 0, 0, 437, + 358, 359, 496, 497, 535, 0, 438, 439, 440, 444, + 441, 442, 443, 762, 763, 764, 761, 470, 534, 557, + 543, 781, 483, 0, 789, 631, 632, 790, 749, 748, + 343, 0, 337, 338, 706, 707, 0, 0, 537, 482, + 638, 502, 0, 0, 647, 681, 670, 759, 634, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 395, + 0, 0, 465, 685, 666, 677, 667, 508, 652, 653, + 654, 661, 407, 655, 791, 657, 626, 658, 627, 659, + 660, 0, 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 718, 717, 716, - 715, 714, 713, 712, 711, 0, 0, 658, 384, 781, - 775, 782, 763, 766, 765, 740, 0, 341, 638, 464, - 518, 401, 705, 706, 0, 761, 284, 285, 286, 287, - 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, - 297, 298, 303, 304, 305, 306, 307, 308, 309, 310, - 708, 301, 302, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 324, 0, 0, 0, - 0, 333, 767, 768, 769, 770, 771, 0, 0, 334, - 335, 336, 0, 0, 299, 300, 327, 549, 328, 329, - 330, 331, 0, 0, 587, 588, 589, 612, 0, 590, - 572, 637, 411, 342, 553, 579, 778, 779, 0, 0, - 0, 0, 0, 0, 0, 688, 699, 735, 736, 0, - 749, 750, 752, 754, 753, 756, 546, 547, 764, 0, - 0, 435, 357, 358, 494, 495, 532, 0, 436, 437, - 438, 442, 439, 440, 441, 758, 759, 760, 757, 468, - 531, 554, 540, 777, 481, 0, 785, 627, 628, 786, - 745, 744, 343, 0, 337, 338, 702, 703, 0, 0, - 534, 480, 634, 500, 0, 0, 643, 677, 666, 755, - 630, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 394, 0, 0, 463, 681, 662, 673, 663, 506, - 648, 649, 650, 657, 406, 651, 787, 653, 622, 654, - 623, 655, 656, 0, 680, 629, 542, 482, 0, 697, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 268, 0, 0, 0, 0, 0, 0, 365, 269, - 624, 751, 626, 625, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 368, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 543, 571, 0, 584, 0, 432, - 433, 0, 0, 0, 0, 0, 0, 0, 350, 550, - 568, 366, 537, 582, 371, 545, 561, 361, 499, 533, - 0, 0, 352, 566, 544, 477, 351, 0, 526, 391, - 408, 388, 497, 0, 0, 565, 595, 387, 585, 0, - 576, 354, 0, 575, 496, 469, 562, 567, 478, 471, - 0, 353, 564, 476, 470, 446, 398, 611, 447, 448, - 449, 450, 451, 452, 412, 512, 467, 513, 413, 484, - 483, 485, 414, 415, 416, 417, 418, 419, 420, 421, - 422, 423, 0, 0, 0, 0, 0, 606, 607, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 743, 0, 0, 748, 0, 578, - 0, 0, 1909, 0, 0, 0, 548, 0, 0, 453, - 0, 0, 0, 596, 0, 529, 502, 789, 0, 0, - 527, 465, 563, 514, 569, 551, 577, 521, 515, 344, - 552, 390, 479, 362, 364, 776, 392, 395, 399, 400, - 490, 491, 508, 536, 555, 556, 557, 389, 376, 528, - 377, 409, 378, 345, 381, 380, 382, 538, 383, 347, - 509, 560, 0, 405, 524, 474, 348, 473, 510, 559, - 558, 363, 586, 593, 594, 685, 0, 599, 790, 791, - 792, 608, 0, 516, 359, 356, 0, 0, 0, 385, - 511, 372, 374, 375, 373, 505, 507, 613, 614, 615, - 617, 0, 618, 619, 0, 0, 0, 0, 620, 686, - 704, 670, 639, 601, 694, 636, 640, 641, 426, 427, - 428, 429, 707, 0, 0, 0, 592, 454, 455, 0, - 397, 396, 475, 349, 0, 0, 443, 425, 517, 355, - 393, 445, 431, 456, 457, 458, 459, 460, 0, 461, - 462, 403, 339, 340, 784, 386, 498, 709, 746, 747, - 631, 0, 695, 632, 642, 379, 667, 679, 678, 492, - 591, 0, 690, 693, 621, 783, 0, 687, 701, 788, - 700, 780, 504, 0, 535, 698, 645, 0, 691, 664, - 665, 0, 692, 660, 696, 0, 633, 0, 602, 605, - 635, 722, 723, 724, 346, 604, 726, 727, 728, 729, - 730, 731, 732, 725, 574, 668, 644, 671, 583, 647, - 646, 0, 0, 682, 600, 683, 684, 486, 487, 488, - 489, 407, 710, 370, 603, 519, 520, 0, 669, 0, - 0, 0, 0, 0, 0, 0, 0, 674, 675, 672, - 793, 0, 733, 734, 0, 0, 597, 598, 402, 0, - 616, 410, 369, 503, 404, 581, 434, 0, 609, 676, - 610, 522, 523, 737, 742, 738, 739, 741, 762, 493, - 424, 430, 539, 444, 466, 525, 580, 501, 530, 367, - 570, 541, 472, 661, 689, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, + 0, 0, 0, 0, 0, 0, 366, 269, 628, 755, + 630, 629, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 369, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 546, 574, 0, 588, 0, 434, 435, 0, + 0, 0, 0, 0, 0, 0, 350, 553, 571, 367, + 540, 586, 372, 548, 564, 362, 501, 536, 0, 0, + 352, 569, 547, 479, 351, 0, 529, 392, 409, 389, + 499, 0, 0, 568, 599, 388, 589, 0, 579, 354, + 0, 578, 498, 471, 565, 570, 480, 473, 0, 353, + 567, 478, 472, 448, 399, 615, 449, 450, 451, 452, + 453, 454, 413, 514, 469, 515, 414, 486, 485, 487, + 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, + 0, 0, 0, 0, 0, 610, 611, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 747, 0, 0, 752, 0, 582, 0, 0, + 0, 0, 0, 0, 551, 0, 0, 455, 0, 0, + 0, 600, 0, 532, 504, 793, 0, 0, 530, 467, + 566, 516, 572, 554, 580, 523, 517, 344, 555, 391, + 481, 363, 365, 780, 393, 396, 400, 401, 492, 493, + 510, 539, 558, 559, 560, 390, 377, 531, 378, 410, + 379, 345, 382, 381, 383, 541, 384, 347, 511, 563, + 0, 406, 527, 476, 348, 475, 512, 562, 561, 364, + 590, 597, 598, 689, 0, 603, 794, 795, 796, 612, + 0, 518, 360, 357, 0, 0, 0, 386, 513, 373, + 375, 376, 374, 507, 509, 617, 618, 619, 621, 0, + 622, 623, 0, 0, 0, 0, 624, 690, 708, 674, + 643, 605, 698, 640, 644, 645, 427, 428, 429, 430, + 711, 0, 0, 0, 596, 456, 457, 0, 398, 397, + 477, 349, 0, 0, 445, 426, 519, 355, 394, 447, + 432, 458, 459, 460, 461, 462, 0, 463, 464, 404, + 339, 340, 788, 387, 500, 713, 750, 751, 635, 0, + 699, 636, 646, 380, 671, 683, 682, 494, 595, 0, + 694, 697, 625, 787, 0, 691, 705, 792, 704, 784, + 506, 0, 538, 702, 649, 0, 695, 668, 669, 0, + 696, 664, 700, 356, 433, 524, 581, 0, 637, 0, + 606, 609, 639, 726, 727, 728, 346, 608, 730, 731, + 732, 733, 734, 735, 736, 729, 577, 672, 648, 675, + 587, 651, 650, 0, 0, 686, 604, 687, 688, 488, + 489, 490, 491, 408, 714, 371, 607, 521, 522, 0, + 673, 0, 0, 0, 0, 0, 0, 0, 0, 678, + 679, 676, 797, 0, 737, 738, 0, 0, 601, 602, + 403, 0, 620, 411, 370, 505, 405, 585, 436, 0, + 613, 680, 614, 525, 526, 741, 746, 742, 743, 745, + 766, 495, 425, 431, 542, 446, 468, 528, 584, 503, + 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 718, 717, 716, 715, 714, 713, 712, 711, - 0, 0, 658, 384, 781, 775, 782, 763, 766, 765, - 740, 0, 341, 638, 464, 518, 401, 705, 706, 0, - 761, 284, 285, 286, 287, 288, 289, 290, 291, 332, - 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, - 306, 307, 308, 309, 310, 708, 301, 302, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 324, 0, 0, 0, 0, 333, 767, 768, 769, - 770, 771, 0, 0, 334, 335, 336, 0, 0, 299, - 300, 327, 549, 328, 329, 330, 331, 0, 0, 587, - 588, 589, 612, 0, 590, 572, 637, 411, 342, 553, - 579, 778, 779, 0, 0, 0, 0, 0, 0, 0, - 688, 699, 735, 736, 0, 749, 750, 752, 754, 753, - 756, 546, 547, 764, 0, 0, 435, 357, 358, 494, - 495, 532, 0, 436, 437, 438, 442, 439, 440, 441, - 758, 759, 760, 757, 468, 531, 554, 540, 777, 481, - 0, 785, 627, 628, 786, 745, 744, 343, 0, 337, - 338, 702, 703, 0, 0, 534, 480, 634, 500, 0, - 0, 643, 677, 666, 755, 630, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1205, 394, 0, 0, 463, - 681, 662, 673, 663, 506, 648, 649, 650, 657, 406, - 651, 787, 653, 622, 654, 623, 655, 656, 0, 680, - 629, 542, 482, 0, 697, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 722, 721, 720, 719, 718, 717, + 716, 715, 1212, 0, 662, 385, 785, 779, 786, 767, + 770, 769, 744, 0, 341, 642, 466, 520, 402, 709, + 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, + 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, + 304, 305, 306, 307, 308, 309, 310, 712, 301, 302, + 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 0, 0, 0, 0, 333, 771, + 772, 773, 774, 775, 0, 0, 334, 335, 336, 0, + 0, 299, 300, 327, 552, 328, 329, 330, 331, 0, + 0, 591, 592, 593, 616, 0, 594, 575, 641, 412, + 342, 556, 583, 782, 783, 0, 0, 0, 0, 0, + 0, 0, 692, 703, 739, 740, 0, 753, 754, 756, + 758, 757, 760, 549, 550, 768, 0, 0, 437, 358, + 359, 496, 497, 535, 0, 438, 439, 440, 444, 441, + 442, 443, 762, 763, 764, 761, 470, 534, 557, 543, + 781, 483, 0, 789, 631, 632, 790, 749, 748, 343, + 0, 337, 338, 706, 707, 0, 0, 537, 482, 638, + 502, 0, 0, 647, 681, 670, 759, 634, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 395, 0, + 0, 465, 685, 666, 677, 667, 508, 652, 653, 654, + 661, 407, 655, 791, 657, 626, 658, 627, 659, 660, + 0, 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 268, 0, 0, 0, - 0, 0, 0, 365, 269, 624, 751, 626, 625, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 368, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 543, - 571, 0, 584, 0, 432, 433, 0, 0, 0, 0, - 0, 0, 0, 350, 550, 568, 366, 537, 582, 371, - 545, 561, 361, 499, 533, 0, 0, 352, 566, 544, - 477, 351, 0, 526, 391, 408, 388, 497, 0, 0, - 565, 595, 387, 585, 0, 576, 354, 0, 575, 496, - 469, 562, 567, 478, 471, 0, 353, 564, 476, 470, - 446, 398, 611, 447, 448, 449, 450, 451, 452, 412, - 512, 467, 513, 413, 484, 483, 485, 414, 415, 416, - 417, 418, 419, 420, 421, 422, 423, 0, 0, 0, - 0, 0, 606, 607, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 743, - 0, 0, 748, 0, 578, 0, 0, 0, 0, 0, - 0, 548, 0, 0, 453, 0, 0, 0, 596, 0, - 529, 502, 789, 0, 0, 527, 465, 563, 514, 569, - 551, 577, 521, 515, 344, 552, 390, 479, 362, 364, - 776, 392, 395, 399, 400, 490, 491, 508, 536, 555, - 556, 557, 389, 376, 528, 377, 409, 378, 345, 381, - 380, 382, 538, 383, 347, 509, 560, 0, 405, 524, - 474, 348, 473, 510, 559, 558, 363, 586, 593, 594, - 685, 0, 599, 790, 791, 792, 608, 0, 516, 359, - 356, 0, 0, 0, 385, 511, 372, 374, 375, 373, - 505, 507, 613, 614, 615, 617, 0, 618, 619, 0, - 0, 0, 0, 620, 686, 704, 670, 639, 601, 694, - 636, 640, 641, 426, 427, 428, 429, 707, 0, 0, - 0, 592, 454, 455, 0, 397, 396, 475, 349, 0, - 0, 443, 425, 517, 355, 393, 445, 431, 456, 457, - 458, 459, 460, 0, 461, 462, 403, 339, 340, 784, - 386, 498, 709, 746, 747, 631, 0, 695, 632, 642, - 379, 667, 679, 678, 492, 591, 0, 690, 693, 621, - 783, 0, 687, 701, 788, 700, 780, 504, 0, 535, - 698, 645, 0, 691, 664, 665, 0, 692, 660, 696, - 0, 633, 0, 602, 605, 635, 722, 723, 724, 346, - 604, 726, 727, 728, 729, 730, 731, 732, 725, 574, - 668, 644, 671, 583, 647, 646, 0, 0, 682, 600, - 683, 684, 486, 487, 488, 489, 407, 710, 370, 603, - 519, 520, 0, 669, 0, 0, 0, 0, 0, 0, - 0, 0, 674, 675, 672, 793, 0, 733, 734, 0, - 0, 597, 598, 402, 0, 616, 410, 369, 503, 404, - 581, 434, 0, 609, 676, 610, 522, 523, 737, 742, - 738, 739, 741, 762, 493, 424, 430, 539, 444, 466, - 525, 580, 501, 530, 367, 570, 541, 472, 661, 689, + 0, 0, 0, 0, 0, 0, 0, 0, 268, 0, + 0, 0, 0, 0, 0, 366, 269, 628, 755, 630, + 629, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 369, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 546, 574, 0, 588, 0, 434, 435, 0, 0, + 0, 0, 0, 0, 0, 350, 553, 571, 367, 540, + 586, 372, 548, 564, 362, 501, 536, 0, 0, 352, + 569, 547, 479, 351, 0, 529, 392, 409, 389, 499, + 0, 0, 568, 599, 388, 589, 0, 579, 354, 0, + 578, 498, 471, 565, 570, 480, 473, 0, 353, 567, + 478, 472, 448, 399, 615, 449, 450, 451, 452, 453, + 454, 413, 514, 469, 515, 414, 486, 485, 487, 415, + 416, 417, 418, 419, 420, 421, 422, 423, 424, 0, + 0, 0, 0, 0, 610, 611, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 747, 0, 952, 752, 0, 582, 0, 0, 0, + 0, 0, 0, 551, 0, 0, 455, 0, 0, 0, + 600, 0, 532, 504, 793, 0, 0, 530, 467, 566, + 516, 572, 554, 580, 523, 517, 344, 555, 391, 481, + 363, 365, 951, 393, 396, 400, 401, 492, 493, 510, + 539, 558, 559, 560, 390, 377, 531, 378, 410, 379, + 345, 382, 381, 383, 541, 384, 347, 511, 563, 0, + 406, 527, 476, 348, 475, 512, 562, 561, 364, 590, + 597, 598, 689, 0, 603, 794, 795, 796, 612, 0, + 518, 360, 357, 0, 0, 0, 386, 513, 373, 375, + 376, 374, 507, 509, 617, 618, 619, 621, 0, 622, + 623, 0, 0, 0, 0, 624, 690, 708, 674, 643, + 605, 698, 640, 644, 645, 427, 428, 429, 430, 711, + 0, 0, 0, 596, 456, 457, 0, 398, 397, 477, + 349, 0, 0, 445, 426, 519, 355, 394, 447, 432, + 458, 459, 460, 461, 462, 0, 463, 464, 404, 339, + 340, 788, 387, 500, 713, 750, 751, 635, 0, 699, + 636, 646, 380, 671, 683, 682, 494, 595, 0, 694, + 697, 625, 787, 0, 691, 705, 792, 704, 784, 506, + 0, 538, 702, 649, 0, 695, 668, 669, 0, 696, + 664, 700, 356, 433, 524, 581, 0, 637, 0, 606, + 609, 639, 726, 727, 728, 346, 608, 730, 731, 732, + 733, 734, 735, 736, 729, 577, 672, 648, 675, 587, + 651, 650, 0, 0, 686, 604, 687, 688, 488, 489, + 490, 491, 408, 714, 371, 607, 521, 522, 0, 673, + 0, 0, 0, 0, 0, 0, 0, 0, 678, 679, + 676, 797, 0, 737, 738, 0, 0, 601, 602, 403, + 0, 620, 411, 370, 505, 405, 585, 436, 0, 613, + 680, 614, 525, 526, 741, 746, 742, 743, 745, 766, + 495, 425, 431, 542, 446, 468, 528, 584, 503, 533, + 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 718, 717, 716, - 715, 714, 713, 712, 711, 0, 0, 658, 384, 781, - 775, 782, 763, 766, 765, 740, 0, 341, 638, 464, - 518, 401, 705, 706, 0, 761, 284, 285, 286, 287, - 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, - 297, 298, 303, 304, 305, 306, 307, 308, 309, 310, - 708, 301, 302, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 324, 0, 0, 0, - 0, 333, 767, 768, 769, 770, 771, 0, 0, 334, - 335, 336, 0, 0, 299, 300, 327, 549, 328, 329, - 330, 331, 0, 0, 587, 588, 589, 612, 0, 590, - 572, 637, 411, 342, 553, 579, 778, 779, 0, 0, - 0, 0, 0, 0, 0, 688, 699, 735, 736, 0, - 749, 750, 752, 754, 753, 756, 546, 547, 764, 0, - 0, 435, 357, 358, 494, 495, 532, 0, 436, 437, - 438, 442, 439, 440, 441, 758, 759, 760, 757, 468, - 531, 554, 540, 777, 481, 0, 785, 627, 628, 786, - 745, 744, 343, 0, 337, 338, 702, 703, 0, 0, - 534, 480, 634, 500, 0, 0, 643, 677, 666, 755, - 630, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 394, 0, 0, 463, 681, 662, 673, 663, 506, - 648, 649, 650, 657, 406, 651, 787, 653, 622, 654, - 623, 655, 656, 0, 680, 629, 542, 482, 0, 697, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 268, 0, 0, 0, 0, 0, 0, 365, 269, - 624, 751, 626, 625, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 368, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 543, 571, 0, 584, 0, 432, - 433, 0, 0, 0, 0, 0, 0, 0, 350, 550, - 568, 366, 537, 582, 371, 545, 561, 361, 499, 533, - 0, 0, 352, 566, 544, 477, 351, 0, 526, 391, - 408, 388, 497, 0, 0, 565, 595, 387, 585, 0, - 576, 354, 0, 575, 496, 469, 562, 567, 478, 471, - 0, 353, 564, 476, 470, 446, 398, 611, 447, 448, - 449, 450, 451, 452, 412, 512, 467, 513, 413, 484, - 483, 485, 414, 415, 416, 417, 418, 419, 420, 421, - 422, 423, 0, 0, 0, 0, 0, 606, 607, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 743, 0, 812, 748, 0, 578, - 0, 0, 0, 0, 0, 0, 548, 0, 0, 453, - 0, 0, 0, 596, 0, 529, 502, 789, 0, 0, - 527, 465, 563, 514, 569, 551, 577, 521, 515, 344, - 552, 390, 479, 362, 364, 776, 392, 395, 399, 400, - 490, 491, 508, 536, 555, 556, 557, 389, 376, 528, - 377, 409, 378, 345, 381, 380, 382, 538, 383, 347, - 509, 560, 0, 405, 524, 474, 348, 473, 510, 559, - 558, 363, 586, 593, 594, 685, 0, 599, 790, 791, - 792, 608, 0, 516, 359, 356, 0, 0, 0, 385, - 511, 372, 374, 375, 373, 505, 507, 613, 614, 615, - 617, 0, 618, 619, 0, 0, 0, 0, 620, 686, - 704, 670, 639, 601, 694, 636, 640, 641, 426, 427, - 428, 429, 707, 0, 0, 0, 592, 454, 455, 0, - 397, 396, 475, 349, 0, 0, 443, 425, 517, 355, - 393, 445, 431, 456, 457, 458, 459, 460, 0, 461, - 462, 403, 339, 340, 784, 386, 498, 709, 746, 747, - 631, 0, 695, 632, 642, 379, 667, 679, 678, 492, - 591, 0, 690, 693, 621, 783, 0, 687, 701, 788, - 700, 780, 504, 0, 535, 698, 645, 0, 691, 664, - 665, 0, 692, 660, 696, 0, 633, 0, 602, 605, - 635, 722, 723, 724, 346, 604, 726, 727, 728, 729, - 730, 731, 732, 725, 574, 668, 644, 671, 583, 647, - 646, 0, 0, 682, 600, 683, 684, 486, 487, 488, - 489, 407, 710, 370, 603, 519, 520, 0, 669, 0, - 0, 0, 0, 0, 0, 0, 0, 674, 675, 672, - 793, 0, 733, 734, 0, 0, 597, 598, 402, 0, - 616, 410, 369, 503, 404, 581, 434, 0, 609, 676, - 610, 522, 523, 737, 742, 738, 739, 741, 762, 493, - 424, 430, 539, 444, 466, 525, 580, 501, 530, 367, - 570, 541, 472, 661, 689, 0, 0, 0, 0, 0, + 0, 0, 0, 722, 721, 720, 719, 718, 717, 716, + 715, 0, 0, 662, 385, 785, 779, 786, 767, 770, + 769, 744, 0, 341, 642, 466, 520, 402, 709, 710, + 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, + 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, + 305, 306, 307, 308, 309, 310, 712, 301, 302, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 0, 0, 0, 0, 333, 771, 772, + 773, 774, 775, 0, 0, 334, 335, 336, 0, 0, + 299, 300, 327, 552, 328, 329, 330, 331, 0, 0, + 591, 592, 593, 616, 0, 594, 575, 641, 412, 342, + 556, 583, 782, 783, 0, 0, 0, 0, 0, 0, + 0, 692, 703, 739, 740, 0, 753, 754, 756, 758, + 757, 760, 549, 550, 768, 0, 0, 437, 358, 359, + 496, 497, 535, 0, 438, 439, 440, 444, 441, 442, + 443, 762, 763, 764, 761, 470, 534, 557, 543, 781, + 483, 0, 789, 631, 632, 790, 749, 748, 343, 0, + 337, 338, 706, 707, 0, 0, 537, 482, 638, 502, + 0, 0, 647, 681, 670, 759, 634, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 395, 0, 0, + 465, 685, 666, 677, 667, 508, 652, 653, 654, 661, + 407, 655, 791, 657, 626, 658, 627, 659, 660, 0, + 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 268, 0, 0, + 0, 0, 0, 0, 366, 269, 628, 755, 630, 629, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 369, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 546, 574, 0, 588, 0, 434, 435, 0, 0, 0, + 0, 0, 0, 0, 350, 553, 571, 367, 540, 586, + 372, 548, 564, 362, 501, 536, 0, 0, 352, 569, + 547, 479, 351, 0, 529, 392, 409, 389, 499, 0, + 0, 568, 599, 388, 589, 0, 579, 354, 0, 578, + 498, 471, 565, 570, 480, 473, 0, 353, 567, 478, + 472, 448, 399, 615, 449, 450, 451, 452, 453, 454, + 413, 514, 469, 515, 414, 486, 485, 487, 415, 416, + 417, 418, 419, 420, 421, 422, 423, 424, 0, 0, + 0, 0, 0, 610, 611, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 747, 0, 0, 752, 0, 582, 0, 0, 0, 0, + 0, 0, 551, 0, 0, 455, 0, 0, 0, 600, + 0, 532, 504, 793, 0, 0, 530, 467, 566, 516, + 572, 554, 580, 523, 517, 344, 555, 391, 481, 363, + 365, 780, 393, 396, 400, 401, 492, 493, 510, 539, + 558, 559, 560, 390, 377, 531, 378, 410, 379, 345, + 382, 381, 383, 541, 384, 347, 511, 563, 0, 406, + 527, 476, 348, 475, 512, 562, 561, 364, 590, 597, + 598, 689, 0, 603, 794, 795, 796, 612, 0, 518, + 360, 357, 0, 0, 0, 386, 513, 373, 375, 376, + 374, 507, 509, 617, 618, 619, 621, 0, 622, 623, + 0, 0, 0, 0, 624, 690, 708, 674, 643, 605, + 698, 640, 644, 645, 427, 428, 429, 430, 711, 0, + 0, 0, 596, 456, 457, 0, 398, 397, 477, 349, + 0, 0, 445, 426, 519, 355, 394, 447, 432, 458, + 459, 460, 461, 462, 0, 463, 464, 404, 339, 340, + 788, 387, 500, 713, 750, 751, 635, 0, 699, 636, + 646, 380, 671, 683, 682, 494, 595, 0, 694, 697, + 625, 787, 0, 691, 705, 792, 704, 784, 506, 0, + 538, 702, 649, 0, 695, 668, 669, 0, 696, 664, + 700, 356, 433, 524, 581, 0, 637, 0, 606, 609, + 639, 726, 727, 728, 346, 608, 730, 731, 732, 733, + 734, 735, 736, 729, 577, 672, 648, 675, 587, 651, + 650, 0, 0, 686, 604, 687, 688, 488, 489, 490, + 491, 408, 714, 371, 607, 521, 522, 0, 673, 0, + 0, 0, 0, 0, 0, 0, 0, 678, 679, 676, + 797, 0, 737, 738, 0, 0, 601, 602, 403, 0, + 620, 411, 370, 505, 405, 585, 436, 0, 613, 680, + 614, 525, 526, 741, 746, 742, 743, 745, 766, 495, + 425, 431, 542, 446, 468, 528, 584, 503, 533, 368, + 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 718, 717, 716, 715, 714, 713, 712, 711, - 0, 0, 658, 384, 781, 775, 782, 763, 766, 765, - 740, 0, 341, 638, 464, 518, 401, 705, 706, 0, - 761, 284, 285, 286, 287, 288, 289, 290, 291, 332, + 0, 0, 722, 721, 720, 719, 718, 717, 716, 715, + 0, 0, 662, 385, 785, 779, 786, 767, 770, 769, + 744, 0, 341, 642, 466, 520, 402, 709, 710, 0, + 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, - 306, 307, 308, 309, 310, 708, 301, 302, 311, 312, + 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 324, 0, 0, 0, 0, 333, 767, 768, 769, - 770, 771, 0, 0, 334, 335, 336, 0, 0, 299, - 300, 327, 549, 328, 329, 330, 331, 0, 0, 587, - 588, 589, 612, 0, 590, 572, 637, 411, 342, 553, - 579, 778, 779, 0, 0, 0, 0, 0, 0, 0, - 688, 699, 735, 736, 0, 749, 750, 752, 754, 753, - 756, 546, 547, 764, 0, 0, 435, 357, 358, 494, - 495, 532, 0, 436, 437, 438, 442, 439, 440, 441, - 758, 759, 760, 757, 468, 531, 554, 540, 777, 481, - 0, 785, 627, 628, 786, 745, 744, 343, 0, 337, - 338, 702, 703, 0, 0, 534, 480, 634, 500, 0, - 0, 643, 677, 666, 755, 630, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 394, 0, 0, 463, - 681, 662, 673, 663, 506, 648, 649, 650, 657, 406, - 651, 787, 653, 622, 654, 623, 655, 656, 0, 680, - 629, 542, 482, 0, 697, 0, 0, 0, 0, 0, + 323, 324, 0, 0, 0, 0, 333, 771, 772, 773, + 774, 775, 0, 0, 334, 335, 336, 0, 0, 299, + 300, 327, 552, 328, 329, 330, 331, 0, 0, 591, + 592, 593, 616, 0, 594, 575, 641, 412, 342, 556, + 583, 782, 783, 0, 0, 0, 0, 0, 0, 0, + 692, 703, 739, 740, 0, 753, 754, 756, 758, 757, + 760, 549, 550, 768, 0, 0, 437, 358, 359, 496, + 497, 535, 0, 438, 439, 440, 444, 441, 442, 443, + 762, 763, 764, 761, 470, 534, 557, 543, 781, 483, + 0, 789, 631, 632, 790, 749, 748, 343, 0, 337, + 338, 706, 707, 0, 0, 537, 482, 638, 502, 0, + 0, 647, 681, 670, 759, 634, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 395, 0, 0, 465, + 685, 666, 677, 667, 508, 652, 653, 654, 661, 407, + 655, 791, 657, 626, 658, 627, 659, 660, 0, 684, + 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, 0, 0, 0, - 0, 0, 0, 365, 269, 624, 751, 626, 625, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 368, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 543, - 571, 0, 584, 0, 432, 433, 0, 0, 0, 0, - 0, 0, 0, 350, 550, 568, 366, 537, 582, 371, - 545, 561, 361, 499, 533, 0, 0, 352, 566, 544, - 477, 351, 0, 526, 391, 408, 388, 497, 0, 0, - 565, 595, 387, 585, 0, 576, 354, 0, 575, 496, - 469, 562, 567, 478, 471, 0, 353, 564, 476, 470, - 446, 398, 611, 447, 448, 449, 450, 451, 452, 412, - 512, 467, 513, 413, 484, 483, 485, 414, 415, 416, - 417, 418, 419, 420, 421, 422, 423, 0, 0, 0, - 0, 0, 606, 607, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 743, - 0, 0, 748, 0, 578, 0, 0, 0, 0, 0, - 0, 548, 0, 0, 453, 0, 0, 0, 596, 0, - 529, 502, 789, 0, 0, 527, 465, 563, 514, 569, - 551, 577, 521, 515, 344, 552, 390, 479, 362, 364, - 776, 392, 395, 399, 400, 490, 491, 508, 536, 555, - 556, 557, 389, 376, 528, 377, 409, 378, 345, 381, - 380, 382, 538, 383, 347, 509, 560, 0, 405, 524, - 474, 348, 473, 510, 559, 558, 363, 586, 593, 594, - 685, 0, 599, 790, 791, 792, 608, 0, 516, 359, - 356, 0, 0, 0, 385, 511, 372, 374, 375, 373, - 505, 507, 613, 614, 615, 617, 0, 618, 619, 0, - 0, 0, 0, 620, 686, 704, 670, 639, 601, 694, - 636, 640, 641, 426, 427, 428, 429, 707, 0, 0, - 0, 592, 454, 455, 0, 397, 396, 475, 349, 0, - 0, 443, 425, 517, 355, 393, 445, 431, 456, 457, - 458, 459, 460, 0, 461, 462, 403, 339, 340, 784, - 386, 498, 709, 746, 747, 631, 0, 695, 632, 642, - 379, 667, 679, 678, 492, 591, 0, 690, 693, 621, - 783, 0, 687, 701, 788, 700, 780, 504, 0, 535, - 698, 645, 0, 691, 664, 665, 0, 692, 660, 696, - 0, 633, 0, 602, 605, 635, 722, 723, 724, 346, - 604, 726, 727, 728, 729, 730, 731, 732, 725, 574, - 668, 644, 671, 583, 647, 646, 0, 0, 682, 600, - 683, 684, 486, 487, 488, 489, 407, 710, 370, 603, - 519, 520, 0, 669, 0, 0, 0, 0, 0, 0, - 0, 0, 674, 675, 672, 793, 0, 733, 734, 0, - 0, 597, 598, 402, 0, 616, 410, 369, 503, 404, - 581, 434, 0, 609, 676, 610, 522, 523, 737, 742, - 738, 739, 741, 762, 493, 424, 430, 539, 444, 466, - 525, 580, 501, 530, 367, 570, 541, 472, 661, 689, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 718, 717, 716, - 715, 714, 713, 712, 711, 1208, 0, 658, 384, 781, - 775, 782, 763, 766, 765, 740, 0, 341, 638, 464, - 518, 401, 705, 706, 0, 761, 284, 285, 286, 287, - 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, - 297, 298, 303, 304, 305, 306, 307, 308, 309, 310, - 708, 301, 302, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 324, 0, 0, 0, - 0, 333, 767, 768, 769, 770, 771, 0, 0, 334, - 335, 336, 0, 0, 299, 300, 327, 549, 328, 329, - 330, 331, 0, 0, 587, 588, 589, 612, 0, 590, - 572, 637, 411, 342, 553, 579, 778, 779, 0, 0, - 0, 0, 0, 0, 0, 688, 699, 735, 736, 0, - 749, 750, 752, 754, 753, 756, 546, 547, 764, 0, - 0, 435, 357, 358, 494, 495, 532, 0, 436, 437, - 438, 442, 439, 440, 441, 758, 759, 760, 757, 468, - 531, 554, 540, 777, 481, 0, 785, 627, 628, 786, - 745, 744, 343, 0, 337, 338, 702, 703, 0, 0, - 534, 480, 634, 500, 0, 0, 643, 677, 666, 755, - 630, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 394, 0, 0, 463, 681, 662, 673, 663, 506, - 648, 649, 650, 657, 406, 651, 787, 653, 622, 654, - 623, 655, 656, 0, 680, 629, 542, 482, 0, 697, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 268, 0, 0, 0, 0, 0, 0, 365, 269, - 624, 751, 626, 625, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 368, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 543, 571, 0, 584, 0, 432, - 433, 0, 0, 0, 0, 0, 0, 0, 350, 550, - 568, 366, 537, 582, 371, 545, 561, 361, 499, 533, - 0, 0, 352, 566, 544, 477, 351, 0, 526, 391, - 408, 388, 497, 0, 0, 565, 595, 387, 585, 0, - 576, 354, 0, 575, 496, 469, 562, 567, 478, 471, - 0, 353, 564, 476, 470, 446, 398, 611, 447, 448, - 449, 450, 451, 452, 412, 512, 467, 513, 413, 484, - 483, 485, 414, 415, 416, 417, 418, 419, 420, 421, - 422, 423, 0, 0, 0, 0, 0, 606, 607, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 743, 0, 948, 748, 0, 578, - 0, 0, 0, 0, 0, 0, 548, 0, 0, 453, - 0, 0, 0, 596, 0, 529, 502, 789, 0, 0, - 527, 465, 563, 514, 569, 551, 577, 521, 515, 344, - 552, 390, 479, 362, 364, 947, 392, 395, 399, 400, - 490, 491, 508, 536, 555, 556, 557, 389, 376, 528, - 377, 409, 378, 345, 381, 380, 382, 538, 383, 347, - 509, 560, 0, 405, 524, 474, 348, 473, 510, 559, - 558, 363, 586, 593, 594, 685, 0, 599, 790, 791, - 792, 608, 0, 516, 359, 356, 0, 0, 0, 385, - 511, 372, 374, 375, 373, 505, 507, 613, 614, 615, - 617, 0, 618, 619, 0, 0, 0, 0, 620, 686, - 704, 670, 639, 601, 694, 636, 640, 641, 426, 427, - 428, 429, 707, 0, 0, 0, 592, 454, 455, 0, - 397, 396, 475, 349, 0, 0, 443, 425, 517, 355, - 393, 445, 431, 456, 457, 458, 459, 460, 0, 461, - 462, 403, 339, 340, 784, 386, 498, 709, 746, 747, - 631, 0, 695, 632, 642, 379, 667, 679, 678, 492, - 591, 0, 690, 693, 621, 783, 0, 687, 701, 788, - 700, 780, 504, 0, 535, 698, 645, 0, 691, 664, - 665, 0, 692, 660, 696, 0, 633, 0, 602, 605, - 635, 722, 723, 724, 346, 604, 726, 727, 728, 729, - 730, 731, 732, 725, 574, 668, 644, 671, 583, 647, - 646, 0, 0, 682, 600, 683, 684, 486, 487, 488, - 489, 407, 710, 370, 603, 519, 520, 0, 669, 0, - 0, 0, 0, 0, 0, 0, 0, 674, 675, 672, - 793, 0, 733, 734, 0, 0, 597, 598, 402, 0, - 616, 410, 369, 503, 404, 581, 434, 0, 609, 676, - 610, 522, 523, 737, 742, 738, 739, 741, 762, 493, - 424, 430, 539, 444, 466, 525, 580, 501, 530, 367, - 570, 541, 472, 661, 689, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 718, 717, 716, 715, 714, 713, 712, 711, - 0, 0, 658, 384, 781, 775, 782, 763, 766, 765, - 740, 0, 341, 638, 464, 518, 401, 705, 706, 0, - 761, 284, 285, 286, 287, 288, 289, 290, 291, 332, - 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, - 306, 307, 308, 309, 310, 708, 301, 302, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 324, 0, 0, 0, 0, 333, 767, 768, 769, - 770, 771, 0, 0, 334, 335, 336, 0, 0, 299, - 300, 327, 549, 328, 329, 330, 331, 0, 0, 587, - 588, 589, 612, 0, 590, 572, 637, 411, 342, 553, - 579, 778, 779, 0, 0, 0, 0, 0, 0, 0, - 688, 699, 735, 736, 0, 749, 750, 752, 754, 753, - 756, 546, 547, 764, 0, 0, 435, 357, 358, 494, - 495, 532, 0, 436, 437, 438, 442, 439, 440, 441, - 758, 759, 760, 757, 468, 531, 554, 540, 777, 481, - 0, 785, 627, 628, 786, 745, 744, 343, 0, 337, - 338, 702, 703, 0, 0, 534, 480, 634, 500, 0, - 0, 643, 677, 666, 755, 630, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 394, 0, 0, 463, - 681, 662, 673, 663, 506, 648, 649, 650, 657, 406, - 651, 787, 653, 622, 654, 623, 655, 656, 0, 680, - 629, 542, 482, 0, 697, 0, 0, 0, 0, 0, + 0, 0, 0, 366, 269, 628, 755, 630, 629, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 369, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 546, + 574, 0, 588, 0, 434, 435, 0, 0, 0, 0, + 0, 0, 0, 350, 553, 571, 367, 540, 586, 372, + 548, 564, 362, 501, 536, 0, 0, 352, 569, 547, + 479, 351, 0, 529, 392, 409, 389, 499, 0, 0, + 568, 599, 388, 589, 0, 579, 354, 0, 578, 498, + 471, 565, 570, 480, 473, 0, 353, 567, 478, 472, + 448, 399, 615, 449, 450, 451, 452, 453, 454, 413, + 514, 469, 515, 414, 486, 485, 487, 415, 416, 417, + 418, 419, 420, 421, 422, 423, 424, 0, 0, 0, + 0, 0, 610, 611, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 747, + 0, 0, 752, 0, 582, 0, 0, 0, 0, 0, + 0, 551, 0, 0, 455, 0, 0, 0, 600, 0, + 532, 504, 793, 0, 0, 530, 467, 566, 516, 572, + 554, 580, 523, 517, 344, 555, 391, 481, 363, 365, + 780, 393, 396, 400, 401, 492, 493, 510, 539, 558, + 559, 560, 390, 377, 531, 378, 410, 379, 345, 382, + 381, 383, 541, 384, 347, 511, 563, 0, 406, 3971, + 476, 348, 475, 512, 562, 561, 364, 590, 597, 598, + 689, 0, 603, 794, 795, 796, 612, 0, 518, 360, + 357, 0, 0, 0, 386, 513, 373, 375, 376, 374, + 507, 509, 617, 618, 619, 621, 0, 622, 623, 0, + 0, 0, 0, 624, 690, 708, 674, 643, 605, 698, + 640, 644, 645, 427, 428, 429, 430, 711, 0, 0, + 0, 596, 456, 457, 0, 398, 397, 477, 349, 0, + 0, 445, 426, 519, 355, 394, 447, 432, 458, 459, + 460, 461, 462, 0, 463, 464, 404, 339, 340, 788, + 387, 500, 713, 750, 751, 635, 0, 699, 636, 646, + 380, 671, 683, 682, 494, 595, 0, 694, 697, 625, + 787, 0, 691, 705, 792, 704, 784, 506, 0, 538, + 702, 649, 0, 695, 668, 669, 0, 696, 664, 700, + 356, 433, 524, 581, 0, 637, 0, 606, 609, 639, + 726, 727, 728, 346, 608, 730, 731, 732, 733, 734, + 735, 736, 729, 577, 672, 648, 675, 587, 651, 650, + 0, 0, 686, 604, 687, 688, 488, 489, 490, 491, + 408, 714, 371, 607, 521, 522, 0, 673, 0, 0, + 0, 0, 0, 0, 0, 0, 678, 679, 676, 797, + 0, 737, 738, 0, 0, 601, 602, 403, 0, 620, + 411, 370, 505, 405, 585, 436, 0, 613, 680, 614, + 525, 526, 741, 746, 742, 743, 745, 766, 495, 425, + 431, 542, 446, 468, 528, 584, 503, 533, 368, 573, + 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 268, 0, 0, 0, - 0, 0, 0, 365, 269, 624, 751, 626, 625, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 368, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 543, - 571, 0, 584, 0, 432, 433, 0, 0, 0, 0, - 0, 0, 0, 350, 550, 568, 366, 537, 582, 371, - 545, 561, 361, 499, 533, 0, 0, 352, 566, 544, - 477, 351, 0, 526, 391, 408, 388, 497, 0, 0, - 565, 595, 387, 585, 0, 576, 354, 0, 575, 496, - 469, 562, 567, 478, 471, 0, 353, 564, 476, 470, - 446, 398, 611, 447, 448, 449, 450, 451, 452, 412, - 512, 467, 513, 413, 484, 483, 485, 414, 415, 416, - 417, 418, 419, 420, 421, 422, 423, 0, 0, 0, - 0, 0, 606, 607, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 743, - 0, 0, 748, 0, 578, 0, 0, 0, 0, 0, - 0, 548, 0, 0, 453, 0, 0, 0, 596, 0, - 529, 502, 789, 0, 0, 527, 465, 563, 514, 569, - 551, 577, 521, 515, 344, 552, 390, 479, 362, 364, - 776, 392, 395, 399, 400, 490, 491, 508, 536, 555, - 556, 557, 389, 376, 528, 377, 409, 378, 345, 381, - 380, 382, 538, 383, 347, 509, 560, 0, 405, 524, - 474, 348, 473, 510, 559, 558, 363, 586, 593, 594, - 685, 0, 599, 790, 791, 792, 608, 0, 516, 359, - 356, 0, 0, 0, 385, 511, 372, 374, 375, 373, - 505, 507, 613, 614, 615, 617, 0, 618, 619, 0, - 0, 0, 0, 620, 686, 704, 670, 639, 601, 694, - 636, 640, 641, 426, 427, 428, 429, 707, 0, 0, - 0, 592, 454, 455, 0, 397, 396, 475, 349, 0, - 0, 443, 425, 517, 355, 393, 445, 431, 456, 457, - 458, 459, 460, 0, 461, 462, 403, 339, 340, 784, - 386, 498, 709, 746, 747, 631, 0, 695, 632, 642, - 379, 667, 679, 678, 492, 591, 0, 690, 693, 621, - 783, 0, 687, 701, 788, 700, 780, 504, 0, 535, - 698, 645, 0, 691, 664, 665, 0, 692, 660, 696, - 0, 633, 0, 602, 605, 635, 722, 723, 724, 346, - 604, 726, 727, 728, 729, 730, 731, 732, 725, 574, - 668, 644, 671, 583, 647, 646, 0, 0, 682, 600, - 683, 684, 486, 487, 488, 489, 407, 710, 370, 603, - 519, 520, 0, 669, 0, 0, 0, 0, 0, 0, - 0, 0, 674, 675, 672, 793, 0, 733, 734, 0, - 0, 597, 598, 402, 0, 616, 410, 369, 503, 404, - 581, 434, 0, 609, 676, 610, 522, 523, 737, 742, - 738, 739, 741, 762, 493, 424, 430, 539, 444, 466, - 525, 580, 501, 530, 367, 570, 541, 472, 661, 689, + 0, 722, 721, 720, 719, 718, 717, 716, 715, 0, + 0, 662, 385, 785, 779, 786, 767, 770, 769, 744, + 0, 341, 642, 466, 520, 402, 709, 710, 0, 765, + 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, + 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, + 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, + 324, 0, 0, 0, 0, 333, 771, 772, 773, 774, + 775, 0, 0, 334, 335, 336, 0, 0, 299, 300, + 327, 552, 328, 329, 330, 331, 0, 0, 591, 592, + 593, 616, 0, 594, 575, 641, 412, 342, 556, 583, + 782, 783, 0, 0, 0, 0, 0, 0, 0, 692, + 703, 739, 740, 0, 753, 754, 756, 758, 757, 760, + 549, 550, 768, 0, 0, 437, 358, 359, 496, 497, + 535, 0, 438, 439, 440, 444, 441, 442, 443, 762, + 763, 764, 761, 470, 534, 557, 543, 781, 483, 0, + 789, 631, 632, 790, 749, 748, 343, 0, 337, 338, + 706, 707, 0, 0, 537, 482, 638, 647, 681, 670, + 759, 634, 0, 0, 0, 0, 0, 2451, 0, 0, + 0, 0, 395, 0, 0, 465, 685, 666, 677, 667, + 508, 652, 653, 654, 661, 407, 655, 791, 657, 626, + 658, 627, 659, 660, 0, 684, 633, 545, 484, 0, + 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 268, 0, 0, 2453, 0, 0, 0, 366, + 269, 628, 755, 630, 629, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 369, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 546, 574, 0, 588, 0, + 434, 435, 0, 0, 0, 0, 0, 0, 0, 350, + 553, 571, 367, 540, 586, 372, 548, 564, 362, 501, + 536, 0, 0, 352, 569, 547, 479, 351, 0, 529, + 392, 409, 389, 499, 0, 0, 568, 599, 388, 589, + 0, 579, 354, 0, 578, 498, 471, 565, 570, 480, + 473, 0, 353, 567, 478, 472, 448, 399, 615, 449, + 450, 451, 452, 453, 454, 413, 514, 469, 515, 414, + 486, 485, 487, 415, 416, 417, 418, 419, 420, 421, + 422, 423, 424, 0, 0, 0, 0, 0, 610, 611, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 747, 0, 0, 752, 0, + 582, 0, 0, 0, 0, 0, 0, 551, 0, 0, + 455, 0, 0, 0, 600, 0, 532, 504, 793, 0, + 0, 530, 467, 566, 516, 572, 554, 580, 523, 517, + 344, 555, 391, 481, 363, 365, 780, 393, 396, 400, + 401, 492, 493, 510, 539, 558, 559, 560, 390, 377, + 531, 378, 410, 379, 345, 382, 381, 383, 541, 384, + 347, 511, 563, 0, 406, 527, 476, 348, 475, 512, + 562, 561, 364, 590, 597, 598, 689, 0, 603, 794, + 795, 796, 612, 0, 518, 360, 357, 0, 0, 0, + 386, 513, 373, 375, 376, 374, 507, 509, 617, 618, + 619, 621, 0, 622, 623, 0, 0, 0, 0, 624, + 690, 708, 674, 643, 605, 698, 640, 644, 645, 427, + 428, 429, 430, 711, 0, 0, 0, 596, 456, 457, + 0, 398, 397, 477, 349, 0, 0, 445, 426, 519, + 355, 394, 447, 432, 458, 459, 460, 461, 462, 0, + 463, 464, 404, 339, 340, 788, 387, 500, 713, 750, + 751, 635, 0, 699, 636, 646, 380, 671, 683, 682, + 494, 595, 0, 694, 697, 625, 787, 0, 691, 705, + 792, 704, 784, 506, 0, 538, 702, 649, 0, 695, + 668, 669, 0, 696, 664, 700, 356, 433, 524, 581, + 0, 637, 0, 606, 609, 639, 726, 727, 728, 346, + 608, 730, 731, 732, 733, 734, 735, 736, 729, 577, + 672, 648, 675, 587, 651, 650, 0, 0, 686, 604, + 687, 688, 488, 489, 490, 491, 408, 714, 371, 607, + 521, 522, 0, 673, 0, 0, 0, 0, 0, 0, + 0, 0, 678, 679, 676, 797, 0, 737, 738, 0, + 0, 601, 602, 403, 0, 620, 411, 370, 505, 405, + 585, 436, 0, 613, 680, 614, 525, 526, 741, 746, + 742, 743, 745, 766, 495, 425, 431, 542, 446, 468, + 528, 584, 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 718, 717, 716, - 715, 714, 713, 712, 711, 0, 0, 658, 384, 781, - 775, 782, 763, 766, 765, 740, 0, 341, 638, 464, - 518, 401, 705, 706, 0, 761, 284, 285, 286, 287, + 0, 0, 0, 0, 0, 0, 0, 722, 721, 720, + 719, 718, 717, 716, 715, 0, 0, 662, 385, 785, + 779, 786, 767, 770, 769, 744, 0, 341, 642, 466, + 520, 402, 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, 308, 309, 310, - 708, 301, 302, 311, 312, 313, 314, 315, 316, 317, + 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, 0, 0, - 0, 333, 767, 768, 769, 770, 771, 0, 0, 334, - 335, 336, 0, 0, 299, 300, 327, 549, 328, 329, - 330, 331, 0, 0, 587, 588, 589, 612, 0, 590, - 572, 637, 411, 342, 553, 579, 778, 779, 0, 0, - 0, 0, 0, 0, 0, 688, 699, 735, 736, 0, - 749, 750, 752, 754, 753, 756, 546, 547, 764, 0, - 0, 435, 357, 358, 494, 495, 532, 0, 436, 437, - 438, 442, 439, 440, 441, 758, 759, 760, 757, 468, - 531, 554, 540, 777, 481, 0, 785, 627, 628, 786, - 745, 744, 343, 0, 337, 338, 702, 703, 0, 0, - 534, 480, 634, 500, 0, 0, 643, 677, 666, 755, - 630, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 394, 0, 0, 463, 681, 662, 673, 663, 506, - 648, 649, 650, 657, 406, 651, 787, 653, 622, 654, - 623, 655, 656, 0, 680, 629, 542, 482, 0, 697, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 268, 0, 0, 0, 0, 0, 0, 365, 269, - 624, 751, 626, 625, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 368, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 543, 571, 0, 584, 0, 432, - 433, 0, 0, 0, 0, 0, 0, 0, 350, 550, - 568, 366, 537, 582, 371, 545, 561, 361, 499, 533, - 0, 0, 352, 566, 544, 477, 351, 0, 526, 391, - 408, 388, 497, 0, 0, 565, 595, 387, 585, 0, - 576, 354, 0, 575, 496, 469, 562, 567, 478, 471, - 0, 353, 564, 476, 470, 446, 398, 611, 447, 448, - 449, 450, 451, 452, 412, 512, 467, 513, 413, 484, - 483, 485, 414, 415, 416, 417, 418, 419, 420, 421, - 422, 423, 0, 0, 0, 0, 0, 606, 607, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 743, 0, 0, 748, 0, 578, - 0, 0, 0, 0, 0, 0, 548, 0, 0, 453, - 0, 0, 0, 596, 0, 529, 502, 789, 0, 0, - 527, 465, 563, 514, 569, 551, 577, 521, 515, 344, - 552, 390, 479, 362, 364, 776, 392, 395, 399, 400, - 490, 491, 508, 536, 555, 556, 557, 389, 376, 528, - 377, 409, 378, 345, 381, 380, 382, 538, 383, 347, - 509, 560, 0, 405, 3967, 474, 348, 473, 510, 559, - 558, 363, 586, 593, 594, 685, 0, 599, 790, 791, - 792, 608, 0, 516, 359, 356, 0, 0, 0, 385, - 511, 372, 374, 375, 373, 505, 507, 613, 614, 615, - 617, 0, 618, 619, 0, 0, 0, 0, 620, 686, - 704, 670, 639, 601, 694, 636, 640, 641, 426, 427, - 428, 429, 707, 0, 0, 0, 592, 454, 455, 0, - 397, 396, 475, 349, 0, 0, 443, 425, 517, 355, - 393, 445, 431, 456, 457, 458, 459, 460, 0, 461, - 462, 403, 339, 340, 784, 386, 498, 709, 746, 747, - 631, 0, 695, 632, 642, 379, 667, 679, 678, 492, - 591, 0, 690, 693, 621, 783, 0, 687, 701, 788, - 700, 780, 504, 0, 535, 698, 645, 0, 691, 664, - 665, 0, 692, 660, 696, 0, 633, 0, 602, 605, - 635, 722, 723, 724, 346, 604, 726, 727, 728, 729, - 730, 731, 732, 725, 574, 668, 644, 671, 583, 647, - 646, 0, 0, 682, 600, 683, 684, 486, 487, 488, - 489, 407, 710, 370, 603, 519, 520, 0, 669, 0, - 0, 0, 0, 0, 0, 0, 0, 674, 675, 672, - 793, 0, 733, 734, 0, 0, 597, 598, 402, 0, - 616, 410, 369, 503, 404, 581, 434, 0, 609, 676, - 610, 522, 523, 737, 742, 738, 739, 741, 762, 493, - 424, 430, 539, 444, 466, 525, 580, 501, 530, 367, - 570, 541, 472, 661, 689, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 718, 717, 716, 715, 714, 713, 712, 711, - 0, 0, 658, 384, 781, 775, 782, 763, 766, 765, - 740, 0, 341, 638, 464, 518, 401, 705, 706, 0, - 761, 284, 285, 286, 287, 288, 289, 290, 291, 332, - 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, - 306, 307, 308, 309, 310, 708, 301, 302, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 324, 0, 0, 0, 0, 333, 767, 768, 769, - 770, 771, 0, 0, 334, 335, 336, 0, 0, 299, - 300, 327, 549, 328, 329, 330, 331, 0, 0, 587, - 588, 589, 612, 0, 590, 572, 637, 411, 342, 553, - 579, 778, 779, 0, 0, 0, 0, 0, 0, 0, - 688, 699, 735, 736, 0, 749, 750, 752, 754, 753, - 756, 546, 547, 764, 0, 0, 435, 357, 358, 494, - 495, 532, 0, 436, 437, 438, 442, 439, 440, 441, - 758, 759, 760, 757, 468, 531, 554, 540, 777, 481, - 0, 785, 627, 628, 786, 745, 744, 343, 0, 337, - 338, 702, 703, 0, 0, 534, 480, 634, 643, 677, - 666, 755, 630, 0, 0, 0, 0, 0, 2447, 0, - 0, 0, 0, 394, 0, 0, 463, 681, 662, 673, - 663, 506, 648, 649, 650, 657, 406, 651, 787, 653, - 622, 654, 623, 655, 656, 0, 680, 629, 542, 482, - 0, 697, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 268, 0, 0, 2449, 0, 0, 0, - 365, 269, 624, 751, 626, 625, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 368, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 543, 571, 0, 584, - 0, 432, 433, 0, 0, 0, 0, 0, 0, 0, - 350, 550, 568, 366, 537, 582, 371, 545, 561, 361, - 499, 533, 0, 0, 352, 566, 544, 477, 351, 0, - 526, 391, 408, 388, 497, 0, 0, 565, 595, 387, - 585, 0, 576, 354, 0, 575, 496, 469, 562, 567, - 478, 471, 0, 353, 564, 476, 470, 446, 398, 611, - 447, 448, 449, 450, 451, 452, 412, 512, 467, 513, - 413, 484, 483, 485, 414, 415, 416, 417, 418, 419, - 420, 421, 422, 423, 0, 0, 0, 0, 0, 606, - 607, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 743, 0, 0, 748, - 0, 578, 0, 0, 0, 0, 0, 0, 548, 0, - 0, 453, 0, 0, 0, 596, 0, 529, 502, 789, - 0, 0, 527, 465, 563, 514, 569, 551, 577, 521, - 515, 344, 552, 390, 479, 362, 364, 776, 392, 395, - 399, 400, 490, 491, 508, 536, 555, 556, 557, 389, - 376, 528, 377, 409, 378, 345, 381, 380, 382, 538, - 383, 347, 509, 560, 0, 405, 524, 474, 348, 473, - 510, 559, 558, 363, 586, 593, 594, 685, 0, 599, - 790, 791, 792, 608, 0, 516, 359, 356, 0, 0, - 0, 385, 511, 372, 374, 375, 373, 505, 507, 613, - 614, 615, 617, 0, 618, 619, 0, 0, 0, 0, - 620, 686, 704, 670, 639, 601, 694, 636, 640, 641, - 426, 427, 428, 429, 707, 0, 0, 0, 592, 454, - 455, 0, 397, 396, 475, 349, 0, 0, 443, 425, - 517, 355, 393, 445, 431, 456, 457, 458, 459, 460, - 0, 461, 462, 403, 339, 340, 784, 386, 498, 709, - 746, 747, 631, 0, 695, 632, 642, 379, 667, 679, - 678, 492, 591, 0, 690, 693, 621, 783, 0, 687, - 701, 788, 700, 780, 504, 0, 535, 698, 645, 0, - 691, 664, 665, 0, 692, 660, 696, 0, 633, 0, - 602, 605, 635, 722, 723, 724, 346, 604, 726, 727, - 728, 729, 730, 731, 732, 725, 574, 668, 644, 671, - 583, 647, 646, 0, 0, 682, 600, 683, 684, 486, - 487, 488, 489, 407, 710, 370, 603, 519, 520, 0, - 669, 0, 0, 0, 0, 0, 0, 0, 0, 674, - 675, 672, 793, 0, 733, 734, 0, 0, 597, 598, - 402, 0, 616, 410, 369, 503, 404, 581, 434, 0, - 609, 676, 610, 522, 523, 737, 742, 738, 739, 741, - 762, 493, 424, 430, 539, 444, 466, 525, 580, 501, - 530, 367, 570, 541, 472, 661, 689, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, + 0, 333, 771, 772, 773, 774, 775, 0, 0, 334, + 335, 336, 0, 0, 299, 300, 327, 552, 328, 329, + 330, 331, 0, 0, 591, 592, 593, 616, 0, 594, + 575, 641, 412, 342, 556, 583, 782, 783, 0, 0, + 0, 0, 0, 0, 0, 692, 703, 739, 740, 0, + 753, 754, 756, 758, 757, 760, 549, 550, 768, 0, + 0, 437, 358, 359, 496, 497, 535, 0, 438, 439, + 440, 444, 441, 442, 443, 762, 763, 764, 761, 470, + 534, 557, 543, 781, 483, 0, 789, 631, 632, 790, + 749, 0, 343, 0, 337, 338, 706, 707, 0, 0, + 537, 482, 638, 502, 0, 0, 647, 681, 670, 759, + 634, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 395, 0, 0, 465, 685, 666, 677, 667, 508, + 652, 653, 654, 661, 407, 655, 791, 657, 626, 658, + 627, 659, 660, 0, 684, 633, 545, 484, 0, 701, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 268, 0, 0, 0, 0, 0, 0, 366, 269, + 628, 755, 630, 629, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 369, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 546, 574, 0, 588, 0, 434, + 435, 0, 0, 0, 0, 0, 0, 0, 350, 553, + 571, 367, 540, 586, 372, 548, 2368, 362, 501, 536, + 0, 0, 352, 569, 547, 479, 351, 0, 529, 392, + 409, 389, 499, 0, 0, 568, 599, 388, 589, 0, + 579, 354, 0, 578, 498, 471, 565, 570, 480, 473, + 0, 353, 567, 478, 472, 448, 399, 615, 449, 450, + 451, 452, 453, 454, 413, 514, 469, 515, 414, 486, + 485, 487, 415, 416, 417, 418, 419, 420, 421, 422, + 423, 424, 0, 0, 0, 0, 0, 610, 611, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 747, 0, 0, 752, 0, 582, + 0, 0, 0, 0, 0, 0, 551, 0, 0, 455, + 0, 0, 0, 600, 0, 532, 504, 793, 0, 0, + 530, 467, 566, 516, 572, 554, 580, 523, 517, 344, + 555, 391, 481, 363, 365, 780, 393, 396, 400, 401, + 492, 493, 510, 539, 558, 559, 560, 390, 377, 531, + 378, 410, 379, 345, 382, 381, 383, 541, 384, 347, + 511, 563, 0, 406, 527, 476, 348, 475, 512, 562, + 561, 364, 590, 597, 598, 689, 0, 603, 794, 795, + 796, 612, 0, 518, 360, 357, 0, 0, 0, 386, + 513, 373, 375, 376, 374, 507, 509, 617, 618, 619, + 621, 0, 622, 623, 0, 0, 0, 0, 624, 690, + 708, 674, 643, 605, 698, 640, 644, 645, 427, 428, + 429, 430, 711, 0, 0, 0, 596, 456, 457, 0, + 398, 397, 477, 349, 0, 0, 445, 426, 519, 355, + 394, 447, 432, 458, 459, 460, 461, 462, 0, 463, + 464, 404, 339, 340, 788, 387, 500, 713, 750, 751, + 635, 0, 699, 636, 646, 380, 671, 683, 682, 494, + 595, 0, 694, 697, 625, 787, 0, 691, 705, 792, + 704, 784, 506, 0, 538, 702, 649, 0, 695, 668, + 669, 0, 696, 664, 700, 356, 433, 524, 581, 0, + 637, 0, 606, 609, 639, 726, 727, 728, 346, 608, + 730, 731, 732, 733, 734, 735, 736, 729, 577, 672, + 648, 675, 587, 651, 650, 0, 0, 686, 604, 687, + 688, 488, 489, 490, 491, 408, 714, 371, 607, 521, + 522, 0, 673, 0, 0, 0, 0, 0, 0, 0, + 0, 678, 679, 676, 797, 0, 737, 738, 0, 0, + 601, 602, 403, 0, 620, 411, 370, 505, 405, 585, + 436, 0, 613, 680, 614, 525, 526, 741, 746, 742, + 743, 745, 766, 495, 425, 431, 542, 446, 468, 528, + 584, 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 718, 717, 716, 715, 714, 713, - 712, 711, 0, 0, 658, 384, 781, 775, 782, 763, - 766, 765, 740, 0, 341, 638, 464, 518, 401, 705, - 706, 0, 761, 284, 285, 286, 287, 288, 289, 290, - 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, - 304, 305, 306, 307, 308, 309, 310, 708, 301, 302, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 324, 0, 0, 0, 0, 333, 767, - 768, 769, 770, 771, 0, 0, 334, 335, 336, 0, - 0, 299, 300, 327, 549, 328, 329, 330, 331, 0, - 0, 587, 588, 589, 612, 0, 590, 572, 637, 411, - 342, 553, 579, 778, 779, 0, 0, 0, 0, 0, - 0, 0, 688, 699, 735, 736, 0, 749, 750, 752, - 754, 753, 756, 546, 547, 764, 0, 0, 435, 357, - 358, 494, 495, 532, 0, 436, 437, 438, 442, 439, - 440, 441, 758, 759, 760, 757, 468, 531, 554, 540, - 777, 481, 0, 785, 627, 628, 786, 745, 0, 343, - 0, 337, 338, 702, 703, 0, 0, 534, 480, 634, - 500, 0, 0, 643, 677, 666, 755, 630, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 394, 0, - 0, 463, 681, 662, 673, 663, 506, 648, 649, 650, - 657, 406, 651, 787, 653, 622, 654, 623, 655, 656, - 0, 680, 629, 542, 482, 0, 697, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 268, 0, - 0, 0, 0, 0, 0, 365, 269, 624, 751, 626, - 625, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 368, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 543, 571, 0, 584, 0, 432, 433, 0, 0, - 0, 0, 0, 0, 0, 350, 550, 568, 366, 537, - 582, 371, 545, 2364, 361, 499, 533, 0, 0, 352, - 566, 544, 477, 351, 0, 526, 391, 408, 388, 497, - 0, 0, 565, 595, 387, 585, 0, 576, 354, 0, - 575, 496, 469, 562, 567, 478, 471, 0, 353, 564, - 476, 470, 446, 398, 611, 447, 448, 449, 450, 451, - 452, 412, 512, 467, 513, 413, 484, 483, 485, 414, - 415, 416, 417, 418, 419, 420, 421, 422, 423, 0, - 0, 0, 0, 0, 606, 607, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 743, 0, 0, 748, 0, 578, 0, 0, 0, - 0, 0, 0, 548, 0, 0, 453, 0, 0, 0, - 596, 0, 529, 502, 789, 0, 0, 527, 465, 563, - 514, 569, 551, 577, 521, 515, 344, 552, 390, 479, - 362, 364, 776, 392, 395, 399, 400, 490, 491, 508, - 536, 555, 556, 557, 389, 376, 528, 377, 409, 378, - 345, 381, 380, 382, 538, 383, 347, 509, 560, 0, - 405, 524, 474, 348, 473, 510, 559, 558, 363, 586, - 593, 594, 685, 0, 599, 790, 791, 792, 608, 0, - 516, 359, 356, 0, 0, 0, 385, 511, 372, 374, - 375, 373, 505, 507, 613, 614, 615, 617, 0, 618, - 619, 0, 0, 0, 0, 620, 686, 704, 670, 639, - 601, 694, 636, 640, 641, 426, 427, 428, 429, 707, - 0, 0, 0, 592, 454, 455, 0, 397, 396, 475, - 349, 0, 0, 443, 425, 517, 355, 393, 445, 431, - 456, 457, 458, 459, 460, 0, 461, 462, 403, 339, - 340, 784, 386, 498, 709, 746, 747, 631, 0, 695, - 632, 642, 379, 667, 679, 678, 492, 591, 0, 690, - 693, 621, 783, 0, 687, 701, 788, 700, 780, 504, - 0, 535, 698, 645, 0, 691, 664, 665, 0, 692, - 660, 696, 0, 633, 0, 602, 605, 635, 722, 723, - 724, 346, 604, 726, 727, 728, 729, 730, 731, 732, - 725, 574, 668, 644, 671, 583, 647, 646, 0, 0, - 682, 600, 683, 684, 486, 487, 488, 489, 407, 710, - 370, 603, 519, 520, 0, 669, 0, 0, 0, 0, - 0, 0, 0, 0, 674, 675, 672, 793, 0, 733, - 734, 0, 0, 597, 598, 402, 0, 616, 410, 369, - 503, 404, 581, 434, 0, 609, 676, 610, 522, 523, - 737, 742, 738, 739, 741, 762, 493, 424, 430, 539, - 444, 466, 525, 580, 501, 530, 367, 570, 541, 472, - 661, 689, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 718, - 717, 716, 715, 714, 713, 712, 711, 0, 0, 658, - 384, 781, 775, 782, 763, 766, 765, 740, 0, 341, - 638, 464, 518, 401, 705, 706, 0, 761, 284, 285, - 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, - 295, 296, 297, 298, 303, 304, 305, 306, 307, 308, - 309, 310, 708, 301, 302, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, - 0, 0, 0, 333, 767, 768, 769, 770, 771, 0, - 0, 334, 335, 336, 0, 0, 299, 300, 327, 549, - 328, 329, 330, 331, 0, 0, 587, 588, 589, 612, - 0, 590, 572, 637, 411, 342, 553, 579, 778, 779, - 0, 0, 0, 0, 0, 0, 0, 688, 699, 735, - 736, 0, 749, 750, 752, 754, 753, 756, 546, 547, - 764, 0, 0, 435, 357, 358, 494, 495, 532, 0, - 436, 437, 438, 442, 439, 440, 441, 758, 759, 760, - 757, 468, 531, 554, 540, 777, 481, 0, 785, 627, - 628, 786, 745, 744, 343, 0, 337, 338, 702, 703, - 0, 0, 534, 480, 634, 500, 0, 0, 643, 677, - 666, 755, 630, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 394, 0, 0, 463, 681, 662, 673, - 663, 506, 648, 649, 650, 657, 406, 651, 787, 653, - 622, 654, 623, 655, 656, 0, 680, 629, 542, 482, - 0, 697, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 268, 0, 0, 0, 0, 0, 0, - 365, 269, 624, 751, 626, 625, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 368, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 543, 571, 0, 584, - 0, 432, 433, 0, 0, 0, 0, 0, 0, 0, - 350, 550, 1845, 366, 537, 582, 371, 545, 561, 361, - 499, 533, 0, 0, 352, 566, 544, 477, 351, 0, - 526, 391, 408, 388, 497, 0, 0, 565, 595, 387, - 585, 0, 576, 354, 0, 575, 496, 469, 562, 567, - 478, 471, 0, 353, 564, 476, 470, 446, 398, 611, - 447, 448, 449, 450, 451, 452, 412, 512, 467, 513, - 413, 484, 483, 485, 414, 415, 416, 417, 418, 419, - 420, 421, 422, 423, 0, 0, 0, 0, 0, 606, - 607, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 743, 0, 0, 748, - 0, 578, 0, 0, 0, 0, 0, 0, 548, 0, - 0, 453, 0, 0, 0, 596, 0, 529, 502, 789, - 0, 0, 527, 465, 563, 514, 569, 551, 577, 521, - 515, 344, 552, 390, 479, 362, 364, 776, 392, 395, - 399, 400, 490, 491, 508, 536, 555, 556, 557, 389, - 376, 528, 377, 409, 378, 345, 381, 380, 382, 538, - 383, 347, 509, 560, 0, 405, 524, 474, 348, 473, - 510, 559, 558, 363, 586, 593, 594, 685, 0, 599, - 790, 791, 792, 608, 0, 516, 359, 356, 0, 0, - 0, 385, 511, 372, 374, 375, 373, 505, 507, 613, - 614, 615, 617, 0, 618, 619, 0, 0, 0, 0, - 620, 686, 704, 670, 639, 601, 694, 636, 640, 641, - 426, 427, 428, 429, 707, 0, 0, 0, 592, 454, - 455, 0, 397, 396, 475, 349, 0, 0, 443, 425, - 517, 355, 393, 445, 431, 456, 457, 458, 459, 460, - 0, 461, 462, 403, 339, 340, 784, 386, 498, 709, - 746, 747, 631, 0, 695, 632, 642, 379, 667, 679, - 678, 492, 591, 0, 690, 693, 621, 783, 0, 687, - 701, 788, 700, 780, 504, 0, 535, 698, 645, 0, - 691, 664, 665, 0, 692, 660, 696, 0, 633, 0, - 602, 605, 635, 722, 723, 724, 346, 604, 726, 727, - 728, 729, 730, 731, 732, 725, 574, 668, 644, 671, - 583, 647, 646, 0, 0, 682, 600, 683, 684, 486, - 487, 488, 489, 407, 710, 370, 603, 519, 520, 0, - 669, 0, 0, 0, 0, 0, 0, 0, 0, 674, - 675, 672, 793, 0, 733, 734, 0, 0, 597, 598, - 402, 0, 616, 410, 369, 503, 404, 581, 434, 0, - 609, 676, 610, 522, 523, 737, 742, 738, 739, 741, - 762, 493, 424, 430, 539, 444, 466, 525, 580, 501, - 530, 367, 570, 541, 472, 661, 689, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 718, 717, 716, 715, 714, 713, - 712, 711, 0, 0, 658, 384, 781, 775, 782, 763, - 766, 765, 740, 0, 341, 638, 464, 518, 401, 705, - 706, 0, 761, 284, 285, 286, 287, 288, 289, 290, - 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, - 304, 305, 306, 307, 308, 309, 310, 708, 301, 302, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 324, 0, 0, 0, 0, 333, 767, - 768, 769, 770, 771, 0, 0, 334, 335, 336, 0, - 0, 299, 300, 327, 549, 328, 329, 330, 331, 0, - 0, 587, 588, 589, 612, 0, 590, 572, 637, 411, - 342, 553, 579, 778, 779, 0, 0, 0, 0, 0, - 0, 0, 688, 699, 735, 736, 0, 749, 750, 752, - 754, 753, 756, 546, 547, 764, 0, 0, 435, 357, - 358, 494, 495, 532, 0, 436, 437, 438, 442, 439, - 440, 441, 758, 759, 760, 757, 468, 531, 554, 540, - 777, 481, 0, 785, 627, 628, 786, 745, 744, 343, - 0, 337, 338, 702, 703, 0, 0, 534, 480, 634, - 500, 0, 0, 643, 677, 666, 755, 630, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 394, 0, - 0, 463, 681, 662, 673, 663, 506, 648, 649, 650, - 657, 406, 651, 787, 653, 622, 654, 623, 655, 656, - 0, 680, 629, 542, 482, 0, 697, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 268, 0, - 0, 0, 0, 0, 0, 365, 269, 624, 751, 626, - 625, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 368, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 543, 571, 0, 584, 0, 432, 433, 0, 0, - 0, 0, 0, 0, 0, 350, 550, 1843, 366, 537, - 582, 371, 545, 561, 361, 499, 533, 0, 0, 352, - 566, 544, 477, 351, 0, 526, 391, 408, 388, 497, - 0, 0, 565, 595, 387, 585, 0, 576, 354, 0, - 575, 496, 469, 562, 567, 478, 471, 0, 353, 564, - 476, 470, 446, 398, 611, 447, 448, 449, 450, 451, - 452, 412, 512, 467, 513, 413, 484, 483, 485, 414, - 415, 416, 417, 418, 419, 420, 421, 422, 423, 0, - 0, 0, 0, 0, 606, 607, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 743, 0, 0, 748, 0, 578, 0, 0, 0, - 0, 0, 0, 548, 0, 0, 453, 0, 0, 0, - 596, 0, 529, 502, 789, 0, 0, 527, 465, 563, - 514, 569, 551, 577, 521, 515, 344, 552, 390, 479, - 362, 364, 776, 392, 395, 399, 400, 490, 491, 508, - 536, 555, 556, 557, 389, 376, 528, 377, 409, 378, - 345, 381, 380, 382, 538, 383, 347, 509, 560, 0, - 405, 524, 474, 348, 473, 510, 559, 558, 363, 586, - 593, 594, 685, 0, 599, 790, 791, 792, 608, 0, - 516, 359, 356, 0, 0, 0, 385, 511, 372, 374, - 375, 373, 505, 507, 613, 614, 615, 617, 0, 618, - 619, 0, 0, 0, 0, 620, 686, 704, 670, 639, - 601, 694, 636, 640, 641, 426, 427, 428, 429, 707, - 0, 0, 0, 592, 454, 455, 0, 397, 396, 475, - 349, 0, 0, 443, 425, 517, 355, 393, 445, 431, - 456, 457, 458, 459, 460, 0, 461, 462, 403, 339, - 340, 784, 386, 498, 709, 746, 747, 631, 0, 695, - 632, 642, 379, 667, 679, 678, 492, 591, 0, 690, - 693, 621, 783, 0, 687, 701, 788, 700, 780, 504, - 0, 535, 698, 645, 0, 691, 664, 665, 0, 692, - 660, 696, 0, 633, 0, 602, 605, 635, 722, 723, - 724, 346, 604, 726, 727, 728, 729, 730, 731, 732, - 725, 574, 668, 644, 671, 583, 647, 646, 0, 0, - 682, 600, 683, 684, 486, 487, 488, 489, 407, 710, - 370, 603, 519, 520, 0, 669, 0, 0, 0, 0, - 0, 0, 0, 0, 674, 675, 672, 793, 0, 733, - 734, 0, 0, 597, 598, 402, 0, 616, 410, 369, - 503, 404, 581, 434, 0, 609, 676, 610, 522, 523, - 737, 742, 738, 739, 741, 762, 493, 424, 430, 539, - 444, 466, 525, 580, 501, 530, 367, 570, 541, 472, - 661, 689, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 718, - 717, 716, 715, 714, 713, 712, 711, 0, 0, 658, - 384, 781, 775, 782, 763, 766, 765, 740, 0, 341, - 638, 464, 518, 401, 705, 706, 0, 761, 284, 285, - 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, - 295, 296, 297, 298, 303, 304, 305, 306, 307, 308, - 309, 310, 708, 301, 302, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, - 0, 0, 0, 333, 767, 768, 769, 770, 771, 0, - 0, 334, 335, 336, 0, 0, 299, 300, 327, 549, - 328, 329, 330, 331, 0, 0, 587, 588, 589, 612, - 0, 590, 572, 637, 411, 342, 553, 579, 778, 779, - 0, 0, 0, 0, 0, 0, 0, 688, 699, 735, - 736, 0, 749, 750, 752, 754, 753, 756, 546, 547, - 764, 0, 0, 435, 357, 358, 494, 495, 532, 0, - 436, 437, 438, 442, 439, 440, 441, 758, 759, 760, - 757, 468, 531, 554, 540, 777, 481, 0, 785, 627, - 628, 786, 745, 744, 343, 0, 337, 338, 702, 703, - 0, 0, 534, 480, 634, 500, 0, 0, 643, 677, - 666, 755, 630, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 394, 0, 0, 463, 681, 662, 673, - 663, 506, 648, 649, 650, 657, 406, 651, 787, 653, - 622, 654, 623, 655, 656, 0, 680, 629, 542, 482, - 0, 697, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 268, 0, 0, 0, 0, 0, 0, - 365, 269, 624, 751, 626, 625, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 368, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 543, 571, 0, 584, - 0, 432, 433, 0, 0, 0, 0, 0, 0, 0, - 350, 550, 568, 366, 537, 582, 371, 545, 1754, 361, - 499, 533, 0, 0, 352, 566, 544, 477, 351, 0, - 526, 391, 408, 388, 497, 0, 0, 565, 595, 387, - 585, 0, 576, 354, 0, 575, 496, 469, 562, 567, - 478, 471, 0, 353, 564, 476, 470, 446, 398, 611, - 447, 448, 449, 450, 451, 452, 412, 512, 467, 513, - 413, 484, 483, 485, 414, 415, 416, 417, 418, 419, - 420, 421, 422, 423, 0, 0, 0, 0, 0, 606, - 607, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 743, 0, 0, 748, - 0, 578, 0, 0, 0, 0, 0, 0, 548, 0, - 0, 453, 0, 0, 0, 596, 0, 529, 502, 789, - 0, 0, 527, 465, 563, 514, 569, 551, 577, 521, - 515, 344, 552, 390, 479, 362, 364, 776, 392, 395, - 399, 400, 490, 491, 508, 536, 555, 556, 557, 389, - 376, 528, 377, 409, 378, 345, 381, 380, 382, 538, - 383, 347, 509, 560, 0, 405, 524, 474, 348, 473, - 510, 559, 558, 363, 586, 593, 594, 685, 0, 599, - 790, 791, 792, 608, 0, 516, 359, 356, 0, 0, - 0, 385, 511, 372, 374, 375, 373, 505, 507, 613, - 614, 615, 617, 0, 618, 619, 0, 0, 0, 0, - 620, 686, 704, 670, 639, 601, 694, 636, 640, 641, - 426, 427, 428, 429, 707, 0, 0, 0, 592, 454, - 455, 0, 397, 396, 475, 349, 0, 0, 443, 425, - 517, 355, 393, 445, 431, 456, 457, 458, 459, 460, - 0, 461, 462, 403, 339, 340, 784, 386, 498, 709, - 746, 747, 631, 0, 695, 632, 642, 379, 667, 679, - 678, 492, 591, 0, 690, 693, 621, 783, 0, 687, - 701, 788, 700, 780, 504, 0, 535, 698, 645, 0, - 691, 664, 665, 0, 692, 660, 696, 0, 633, 0, - 602, 605, 635, 722, 723, 724, 346, 604, 726, 727, - 728, 729, 730, 731, 732, 725, 574, 668, 644, 671, - 583, 647, 646, 0, 0, 682, 600, 683, 684, 486, - 487, 488, 489, 407, 710, 370, 603, 519, 520, 0, - 669, 0, 0, 0, 0, 0, 0, 0, 0, 674, - 675, 672, 793, 0, 733, 734, 0, 0, 597, 598, - 402, 0, 616, 410, 369, 503, 404, 581, 434, 0, - 609, 676, 610, 522, 523, 737, 742, 738, 739, 741, - 762, 493, 424, 430, 539, 444, 466, 525, 580, 501, - 530, 367, 570, 541, 472, 661, 689, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 718, 717, 716, 715, 714, 713, - 712, 711, 0, 0, 658, 384, 781, 775, 782, 763, - 766, 765, 740, 0, 341, 638, 464, 518, 401, 705, - 706, 0, 761, 284, 285, 286, 287, 288, 289, 290, - 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, - 304, 305, 306, 307, 308, 309, 310, 708, 301, 302, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 324, 0, 0, 0, 0, 333, 767, - 768, 769, 770, 771, 0, 0, 334, 335, 336, 0, - 0, 299, 300, 327, 549, 328, 329, 330, 331, 0, - 0, 587, 588, 589, 612, 0, 590, 572, 637, 411, - 342, 553, 579, 778, 779, 0, 0, 0, 0, 0, - 0, 0, 688, 699, 735, 736, 0, 749, 750, 752, - 754, 753, 756, 546, 547, 764, 0, 0, 435, 357, - 358, 494, 495, 532, 0, 436, 437, 438, 442, 439, - 440, 441, 758, 759, 760, 757, 468, 531, 554, 540, - 777, 481, 0, 785, 627, 628, 786, 745, 744, 343, - 0, 337, 338, 702, 703, 0, 0, 534, 480, 634, - 500, 0, 0, 643, 677, 666, 755, 630, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 394, 0, - 0, 463, 681, 662, 673, 663, 506, 648, 649, 650, - 657, 406, 651, 787, 653, 622, 654, 623, 655, 656, - 0, 680, 629, 542, 482, 0, 697, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 268, 0, - 0, 0, 0, 0, 0, 365, 269, 624, 751, 626, - 625, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 368, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 543, 571, 0, 584, 0, 432, 433, 0, 0, - 0, 0, 0, 0, 0, 350, 550, 568, 366, 537, - 582, 371, 545, 561, 361, 499, 533, 0, 0, 352, - 566, 544, 477, 351, 0, 526, 391, 408, 388, 497, - 0, 0, 565, 595, 387, 585, 0, 576, 354, 0, - 575, 496, 469, 562, 567, 478, 471, 0, 353, 564, - 476, 470, 446, 398, 611, 447, 448, 449, 450, 451, - 452, 412, 512, 467, 513, 413, 484, 483, 485, 414, - 415, 416, 417, 418, 419, 420, 421, 422, 423, 0, - 0, 0, 0, 0, 606, 607, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 743, 0, 0, 748, 0, 578, 0, 0, 0, - 0, 0, 0, 548, 0, 0, 453, 0, 0, 0, - 596, 0, 529, 502, 789, 0, 0, 527, 465, 563, - 514, 569, 551, 577, 899, 515, 344, 552, 390, 479, - 362, 364, 776, 392, 395, 399, 400, 490, 491, 508, - 536, 555, 556, 557, 389, 376, 528, 377, 409, 378, - 345, 381, 380, 382, 538, 383, 347, 509, 560, 0, - 405, 524, 474, 348, 473, 510, 559, 558, 363, 586, - 593, 594, 685, 0, 599, 790, 791, 792, 608, 0, - 516, 359, 356, 0, 0, 0, 385, 511, 372, 374, - 375, 373, 505, 507, 613, 614, 615, 617, 0, 618, - 619, 0, 0, 0, 0, 620, 686, 704, 670, 639, - 601, 694, 636, 640, 641, 426, 427, 428, 429, 707, - 0, 0, 0, 592, 454, 455, 0, 397, 396, 475, - 349, 0, 0, 443, 425, 517, 355, 393, 445, 431, - 456, 457, 458, 459, 460, 0, 461, 462, 403, 339, - 340, 784, 386, 498, 709, 746, 747, 631, 0, 695, - 632, 642, 379, 667, 679, 678, 492, 591, 0, 690, - 693, 621, 783, 0, 687, 701, 788, 700, 780, 504, - 0, 535, 698, 645, 0, 691, 664, 665, 0, 692, - 660, 696, 0, 633, 0, 602, 605, 635, 722, 723, - 724, 346, 604, 726, 727, 728, 729, 730, 731, 900, - 725, 574, 668, 644, 671, 583, 647, 646, 0, 0, - 682, 600, 683, 684, 486, 487, 488, 489, 407, 710, - 370, 603, 519, 520, 0, 669, 0, 0, 0, 0, - 0, 0, 0, 0, 674, 675, 672, 793, 0, 733, - 734, 0, 0, 597, 598, 402, 0, 616, 410, 369, - 503, 404, 581, 434, 0, 609, 676, 610, 522, 523, - 737, 742, 738, 739, 741, 762, 493, 424, 430, 539, - 444, 466, 525, 580, 501, 530, 367, 570, 541, 472, - 661, 689, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 718, - 717, 716, 715, 714, 713, 712, 711, 0, 0, 658, - 384, 781, 775, 782, 763, 766, 765, 740, 0, 341, - 638, 464, 518, 401, 705, 706, 0, 761, 284, 285, - 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, - 295, 296, 297, 298, 303, 304, 305, 306, 307, 308, - 309, 310, 708, 301, 302, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, - 0, 0, 0, 333, 767, 768, 769, 770, 771, 0, - 0, 334, 335, 336, 0, 0, 299, 300, 327, 549, - 328, 329, 330, 331, 0, 0, 587, 588, 589, 612, - 0, 590, 572, 637, 411, 342, 553, 579, 778, 779, - 0, 0, 0, 0, 0, 0, 0, 688, 699, 735, - 736, 0, 749, 750, 752, 754, 753, 756, 546, 547, - 764, 0, 0, 435, 357, 358, 494, 495, 532, 0, - 436, 437, 438, 442, 439, 440, 441, 758, 759, 760, - 757, 468, 531, 554, 540, 777, 481, 0, 785, 627, - 628, 786, 745, 744, 343, 0, 337, 338, 702, 703, - 0, 0, 534, 480, 634, 500, 0, 0, 643, 677, - 666, 755, 630, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 394, 0, 0, 463, 681, 662, 673, - 663, 506, 648, 649, 650, 657, 406, 651, 787, 653, - 622, 654, 623, 655, 656, 0, 680, 629, 542, 482, - 0, 697, 0, 0, 0, 0, 0, 0, 0, 0, + 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 722, 721, 720, 719, + 718, 717, 716, 715, 0, 0, 662, 385, 785, 779, + 786, 767, 770, 769, 744, 0, 341, 642, 466, 520, + 402, 709, 710, 0, 765, 284, 285, 286, 287, 288, + 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, + 298, 303, 304, 305, 306, 307, 308, 309, 310, 712, + 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 0, 0, 0, 0, + 333, 771, 772, 773, 774, 775, 0, 0, 334, 335, + 336, 0, 0, 299, 300, 327, 552, 328, 329, 330, + 331, 0, 0, 591, 592, 593, 616, 0, 594, 575, + 641, 412, 342, 556, 583, 782, 783, 0, 0, 0, + 0, 0, 0, 0, 692, 703, 739, 740, 0, 753, + 754, 756, 758, 757, 760, 549, 550, 768, 0, 0, + 437, 358, 359, 496, 497, 535, 0, 438, 439, 440, + 444, 441, 442, 443, 762, 763, 764, 761, 470, 534, + 557, 543, 781, 483, 0, 789, 631, 632, 790, 749, + 748, 343, 0, 337, 338, 706, 707, 0, 0, 537, + 482, 638, 502, 0, 0, 647, 681, 670, 759, 634, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 395, 0, 0, 465, 685, 666, 677, 667, 508, 652, + 653, 654, 661, 407, 655, 791, 657, 626, 658, 627, + 659, 660, 0, 684, 633, 545, 484, 0, 701, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 268, 0, 0, 0, 0, 0, 0, 366, 269, 628, + 755, 630, 629, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 369, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 546, 574, 0, 588, 0, 434, 435, + 0, 0, 0, 0, 0, 0, 0, 350, 553, 1849, + 367, 540, 586, 372, 548, 564, 362, 501, 536, 0, + 0, 352, 569, 547, 479, 351, 0, 529, 392, 409, + 389, 499, 0, 0, 568, 599, 388, 589, 0, 579, + 354, 0, 578, 498, 471, 565, 570, 480, 473, 0, + 353, 567, 478, 472, 448, 399, 615, 449, 450, 451, + 452, 453, 454, 413, 514, 469, 515, 414, 486, 485, + 487, 415, 416, 417, 418, 419, 420, 421, 422, 423, + 424, 0, 0, 0, 0, 0, 610, 611, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 747, 0, 0, 752, 0, 582, 0, + 0, 0, 0, 0, 0, 551, 0, 0, 455, 0, + 0, 0, 600, 0, 532, 504, 793, 0, 0, 530, + 467, 566, 516, 572, 554, 580, 523, 517, 344, 555, + 391, 481, 363, 365, 780, 393, 396, 400, 401, 492, + 493, 510, 539, 558, 559, 560, 390, 377, 531, 378, + 410, 379, 345, 382, 381, 383, 541, 384, 347, 511, + 563, 0, 406, 527, 476, 348, 475, 512, 562, 561, + 364, 590, 597, 598, 689, 0, 603, 794, 795, 796, + 612, 0, 518, 360, 357, 0, 0, 0, 386, 513, + 373, 375, 376, 374, 507, 509, 617, 618, 619, 621, + 0, 622, 623, 0, 0, 0, 0, 624, 690, 708, + 674, 643, 605, 698, 640, 644, 645, 427, 428, 429, + 430, 711, 0, 0, 0, 596, 456, 457, 0, 398, + 397, 477, 349, 0, 0, 445, 426, 519, 355, 394, + 447, 432, 458, 459, 460, 461, 462, 0, 463, 464, + 404, 339, 340, 788, 387, 500, 713, 750, 751, 635, + 0, 699, 636, 646, 380, 671, 683, 682, 494, 595, + 0, 694, 697, 625, 787, 0, 691, 705, 792, 704, + 784, 506, 0, 538, 702, 649, 0, 695, 668, 669, + 0, 696, 664, 700, 356, 433, 524, 581, 0, 637, + 0, 606, 609, 639, 726, 727, 728, 346, 608, 730, + 731, 732, 733, 734, 735, 736, 729, 577, 672, 648, + 675, 587, 651, 650, 0, 0, 686, 604, 687, 688, + 488, 489, 490, 491, 408, 714, 371, 607, 521, 522, + 0, 673, 0, 0, 0, 0, 0, 0, 0, 0, + 678, 679, 676, 797, 0, 737, 738, 0, 0, 601, + 602, 403, 0, 620, 411, 370, 505, 405, 585, 436, + 0, 613, 680, 614, 525, 526, 741, 746, 742, 743, + 745, 766, 495, 425, 431, 542, 446, 468, 528, 584, + 503, 533, 368, 573, 544, 474, 665, 693, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, + 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 722, 721, 720, 719, 718, + 717, 716, 715, 0, 0, 662, 385, 785, 779, 786, + 767, 770, 769, 744, 0, 341, 642, 466, 520, 402, + 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, + 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, + 303, 304, 305, 306, 307, 308, 309, 310, 712, 301, + 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 0, 0, 0, 0, 333, + 771, 772, 773, 774, 775, 0, 0, 334, 335, 336, + 0, 0, 299, 300, 327, 552, 328, 329, 330, 331, + 0, 0, 591, 592, 593, 616, 0, 594, 575, 641, + 412, 342, 556, 583, 782, 783, 0, 0, 0, 0, + 0, 0, 0, 692, 703, 739, 740, 0, 753, 754, + 756, 758, 757, 760, 549, 550, 768, 0, 0, 437, + 358, 359, 496, 497, 535, 0, 438, 439, 440, 444, + 441, 442, 443, 762, 763, 764, 761, 470, 534, 557, + 543, 781, 483, 0, 789, 631, 632, 790, 749, 748, + 343, 0, 337, 338, 706, 707, 0, 0, 537, 482, + 638, 502, 0, 0, 647, 681, 670, 759, 634, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 395, + 0, 0, 465, 685, 666, 677, 667, 508, 652, 653, + 654, 661, 407, 655, 791, 657, 626, 658, 627, 659, + 660, 0, 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 268, 0, 0, 0, 0, 0, 0, - 365, 269, 624, 751, 626, 625, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 368, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 543, 571, 0, 584, - 0, 432, 433, 0, 0, 0, 0, 0, 0, 0, - 350, 550, 568, 366, 537, 582, 371, 545, 561, 361, - 499, 533, 0, 0, 352, 566, 544, 477, 351, 0, - 526, 391, 408, 388, 497, 0, 0, 565, 595, 387, - 585, 0, 576, 354, 0, 575, 496, 469, 562, 567, - 478, 471, 0, 353, 564, 476, 470, 446, 398, 611, - 447, 448, 449, 450, 451, 452, 412, 512, 467, 513, - 413, 484, 483, 485, 414, 415, 416, 417, 418, 419, - 420, 421, 422, 423, 0, 0, 0, 0, 0, 606, - 607, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 743, 0, 0, 748, - 0, 578, 0, 0, 0, 0, 0, 0, 548, 0, - 0, 453, 0, 0, 0, 596, 0, 529, 502, 789, - 0, 0, 527, 465, 563, 514, 569, 551, 577, 521, - 515, 344, 552, 390, 479, 362, 364, 776, 392, 395, - 399, 400, 490, 491, 508, 536, 555, 556, 557, 389, - 376, 528, 377, 409, 378, 345, 381, 380, 382, 538, - 383, 347, 509, 560, 0, 405, 524, 474, 348, 473, - 510, 559, 558, 363, 586, 593, 594, 685, 0, 599, - 790, 791, 792, 608, 0, 516, 359, 356, 0, 0, - 0, 385, 511, 372, 374, 375, 373, 505, 507, 613, - 614, 615, 617, 0, 618, 619, 0, 0, 0, 0, - 620, 686, 704, 670, 639, 601, 694, 636, 640, 641, - 426, 427, 428, 429, 707, 0, 0, 0, 592, 454, - 455, 0, 397, 396, 475, 349, 0, 0, 443, 425, - 517, 355, 393, 445, 431, 456, 457, 458, 459, 460, - 0, 461, 462, 403, 339, 340, 784, 386, 498, 709, - 746, 747, 631, 0, 695, 632, 642, 379, 667, 679, - 678, 492, 591, 0, 690, 693, 621, 783, 0, 687, - 701, 788, 700, 780, 504, 0, 535, 698, 645, 0, - 691, 664, 665, 0, 692, 660, 696, 0, 633, 0, - 602, 605, 635, 722, 723, 724, 346, 604, 726, 727, - 728, 729, 730, 731, 732, 725, 574, 668, 644, 671, - 583, 647, 646, 0, 0, 682, 600, 683, 684, 486, - 487, 488, 489, 407, 710, 370, 603, 519, 520, 0, - 669, 0, 0, 0, 0, 0, 0, 0, 0, 674, - 675, 672, 793, 0, 733, 734, 0, 0, 597, 598, - 402, 0, 616, 410, 369, 503, 404, 581, 434, 0, - 609, 676, 610, 522, 523, 737, 742, 738, 739, 741, - 762, 493, 424, 430, 539, 444, 466, 525, 580, 501, - 530, 367, 570, 541, 472, 661, 689, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, + 0, 0, 0, 0, 0, 0, 366, 269, 628, 755, + 630, 629, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 369, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 546, 574, 0, 588, 0, 434, 435, 0, + 0, 0, 0, 0, 0, 0, 350, 553, 1847, 367, + 540, 586, 372, 548, 564, 362, 501, 536, 0, 0, + 352, 569, 547, 479, 351, 0, 529, 392, 409, 389, + 499, 0, 0, 568, 599, 388, 589, 0, 579, 354, + 0, 578, 498, 471, 565, 570, 480, 473, 0, 353, + 567, 478, 472, 448, 399, 615, 449, 450, 451, 452, + 453, 454, 413, 514, 469, 515, 414, 486, 485, 487, + 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, + 0, 0, 0, 0, 0, 610, 611, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 747, 0, 0, 752, 0, 582, 0, 0, + 0, 0, 0, 0, 551, 0, 0, 455, 0, 0, + 0, 600, 0, 532, 504, 793, 0, 0, 530, 467, + 566, 516, 572, 554, 580, 523, 517, 344, 555, 391, + 481, 363, 365, 780, 393, 396, 400, 401, 492, 493, + 510, 539, 558, 559, 560, 390, 377, 531, 378, 410, + 379, 345, 382, 381, 383, 541, 384, 347, 511, 563, + 0, 406, 527, 476, 348, 475, 512, 562, 561, 364, + 590, 597, 598, 689, 0, 603, 794, 795, 796, 612, + 0, 518, 360, 357, 0, 0, 0, 386, 513, 373, + 375, 376, 374, 507, 509, 617, 618, 619, 621, 0, + 622, 623, 0, 0, 0, 0, 624, 690, 708, 674, + 643, 605, 698, 640, 644, 645, 427, 428, 429, 430, + 711, 0, 0, 0, 596, 456, 457, 0, 398, 397, + 477, 349, 0, 0, 445, 426, 519, 355, 394, 447, + 432, 458, 459, 460, 461, 462, 0, 463, 464, 404, + 339, 340, 788, 387, 500, 713, 750, 751, 635, 0, + 699, 636, 646, 380, 671, 683, 682, 494, 595, 0, + 694, 697, 625, 787, 0, 691, 705, 792, 704, 784, + 506, 0, 538, 702, 649, 0, 695, 668, 669, 0, + 696, 664, 700, 356, 433, 524, 581, 0, 637, 0, + 606, 609, 639, 726, 727, 728, 346, 608, 730, 731, + 732, 733, 734, 735, 736, 729, 577, 672, 648, 675, + 587, 651, 650, 0, 0, 686, 604, 687, 688, 488, + 489, 490, 491, 408, 714, 371, 607, 521, 522, 0, + 673, 0, 0, 0, 0, 0, 0, 0, 0, 678, + 679, 676, 797, 0, 737, 738, 0, 0, 601, 602, + 403, 0, 620, 411, 370, 505, 405, 585, 436, 0, + 613, 680, 614, 525, 526, 741, 746, 742, 743, 745, + 766, 495, 425, 431, 542, 446, 468, 528, 584, 503, + 533, 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 718, 717, 716, 715, 714, 713, - 712, 711, 0, 0, 658, 384, 781, 775, 782, 763, - 766, 765, 836, 0, 341, 638, 464, 518, 401, 705, - 706, 0, 761, 284, 285, 286, 287, 288, 289, 290, + 0, 0, 0, 0, 722, 721, 720, 719, 718, 717, + 716, 715, 0, 0, 662, 385, 785, 779, 786, 767, + 770, 769, 744, 0, 341, 642, 466, 520, 402, 709, + 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, - 304, 305, 306, 307, 308, 309, 310, 708, 301, 302, + 304, 305, 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 324, 0, 0, 0, 0, 333, 767, - 768, 769, 770, 771, 0, 0, 334, 335, 336, 0, - 0, 299, 300, 327, 549, 328, 329, 330, 331, 0, - 0, 587, 588, 589, 612, 0, 590, 572, 637, 411, - 342, 553, 579, 778, 779, 0, 0, 0, 0, 0, - 0, 0, 688, 699, 735, 736, 0, 749, 750, 752, - 754, 753, 756, 546, 547, 764, 0, 0, 435, 357, - 358, 494, 495, 532, 0, 436, 437, 438, 442, 439, - 440, 441, 758, 759, 760, 757, 468, 531, 554, 540, - 777, 481, 0, 785, 627, 628, 786, 745, 744, 343, - 0, 337, 338, 702, 703, 0, 0, 534, 480, 634, - 500, 0, 0, 643, 677, 666, 755, 630, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 394, 0, - 0, 463, 681, 662, 673, 663, 506, 648, 649, 650, - 657, 406, 651, 787, 653, 622, 654, 623, 655, 656, - 0, 680, 629, 542, 482, 0, 697, 0, 0, 0, + 321, 322, 323, 324, 0, 0, 0, 0, 333, 771, + 772, 773, 774, 775, 0, 0, 334, 335, 336, 0, + 0, 299, 300, 327, 552, 328, 329, 330, 331, 0, + 0, 591, 592, 593, 616, 0, 594, 575, 641, 412, + 342, 556, 583, 782, 783, 0, 0, 0, 0, 0, + 0, 0, 692, 703, 739, 740, 0, 753, 754, 756, + 758, 757, 760, 549, 550, 768, 0, 0, 437, 358, + 359, 496, 497, 535, 0, 438, 439, 440, 444, 441, + 442, 443, 762, 763, 764, 761, 470, 534, 557, 543, + 781, 483, 0, 789, 631, 632, 790, 749, 748, 343, + 0, 337, 338, 706, 707, 0, 0, 537, 482, 638, + 502, 0, 0, 647, 681, 670, 759, 634, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 395, 0, + 0, 465, 685, 666, 677, 667, 508, 652, 653, 654, + 661, 407, 655, 791, 657, 626, 658, 627, 659, 660, + 0, 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 268, 0, - 0, 0, 0, 0, 0, 365, 269, 624, 751, 626, - 625, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 368, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 543, 571, 0, 584, 0, 432, 433, 0, 0, - 0, 0, 0, 0, 0, 350, 550, 568, 366, 537, - 582, 371, 545, 561, 361, 499, 533, 0, 0, 352, - 566, 544, 477, 351, 0, 526, 391, 408, 388, 497, - 0, 0, 565, 595, 387, 585, 0, 576, 354, 0, - 575, 496, 469, 562, 567, 478, 471, 0, 353, 564, - 476, 470, 446, 398, 611, 447, 448, 449, 450, 451, - 452, 412, 512, 467, 513, 413, 484, 483, 485, 414, - 415, 416, 417, 418, 419, 420, 421, 422, 423, 0, - 0, 0, 0, 0, 606, 607, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 743, 0, 0, 748, 0, 578, 0, 0, 0, - 0, 0, 0, 548, 0, 0, 453, 0, 0, 0, - 596, 0, 529, 502, 789, 0, 0, 527, 465, 563, - 514, 569, 551, 577, 521, 515, 344, 552, 390, 479, - 362, 364, 776, 392, 395, 399, 400, 490, 491, 508, - 536, 555, 556, 557, 389, 376, 528, 377, 409, 378, - 345, 381, 380, 382, 538, 383, 347, 509, 560, 0, - 405, 0, 474, 348, 473, 510, 559, 558, 363, 586, - 593, 594, 685, 0, 599, 790, 791, 792, 608, 0, - 516, 359, 356, 0, 0, 0, 385, 511, 372, 374, - 375, 373, 505, 507, 613, 614, 615, 617, 0, 618, - 619, 0, 0, 0, 0, 620, 686, 704, 670, 639, - 601, 694, 636, 640, 641, 426, 427, 428, 429, 707, - 0, 0, 0, 592, 454, 455, 0, 397, 396, 475, - 349, 0, 0, 443, 425, 517, 355, 393, 445, 431, - 456, 457, 458, 459, 460, 0, 461, 462, 403, 339, - 340, 784, 386, 498, 709, 746, 747, 631, 0, 695, - 632, 642, 379, 667, 679, 678, 492, 591, 0, 690, - 693, 621, 783, 0, 687, 701, 788, 700, 780, 504, - 0, 535, 698, 645, 0, 691, 664, 665, 0, 692, - 660, 696, 0, 633, 0, 602, 605, 635, 722, 723, - 724, 346, 604, 726, 727, 728, 729, 730, 731, 732, - 725, 574, 668, 644, 671, 583, 647, 646, 0, 0, - 682, 600, 683, 684, 486, 487, 488, 489, 407, 710, - 370, 603, 519, 520, 0, 669, 0, 0, 0, 0, - 0, 0, 0, 0, 674, 675, 672, 793, 0, 733, - 734, 0, 0, 597, 598, 402, 0, 616, 410, 369, - 503, 404, 581, 434, 0, 609, 676, 610, 522, 523, - 737, 742, 738, 739, 741, 762, 493, 424, 430, 539, - 444, 466, 525, 580, 501, 530, 367, 570, 541, 472, - 661, 689, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 366, 269, 628, 755, 630, + 629, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 369, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 546, 574, 0, 588, 0, 434, 435, 0, 0, + 0, 0, 0, 0, 0, 350, 553, 571, 367, 540, + 586, 372, 548, 1758, 362, 501, 536, 0, 0, 352, + 569, 547, 479, 351, 0, 529, 392, 409, 389, 499, + 0, 0, 568, 599, 388, 589, 0, 579, 354, 0, + 578, 498, 471, 565, 570, 480, 473, 0, 353, 567, + 478, 472, 448, 399, 615, 449, 450, 451, 452, 453, + 454, 413, 514, 469, 515, 414, 486, 485, 487, 415, + 416, 417, 418, 419, 420, 421, 422, 423, 424, 0, + 0, 0, 0, 0, 610, 611, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 747, 0, 0, 752, 0, 582, 0, 0, 0, + 0, 0, 0, 551, 0, 0, 455, 0, 0, 0, + 600, 0, 532, 504, 793, 0, 0, 530, 467, 566, + 516, 572, 554, 580, 523, 517, 344, 555, 391, 481, + 363, 365, 780, 393, 396, 400, 401, 492, 493, 510, + 539, 558, 559, 560, 390, 377, 531, 378, 410, 379, + 345, 382, 381, 383, 541, 384, 347, 511, 563, 0, + 406, 527, 476, 348, 475, 512, 562, 561, 364, 590, + 597, 598, 689, 0, 603, 794, 795, 796, 612, 0, + 518, 360, 357, 0, 0, 0, 386, 513, 373, 375, + 376, 374, 507, 509, 617, 618, 619, 621, 0, 622, + 623, 0, 0, 0, 0, 624, 690, 708, 674, 643, + 605, 698, 640, 644, 645, 427, 428, 429, 430, 711, + 0, 0, 0, 596, 456, 457, 0, 398, 397, 477, + 349, 0, 0, 445, 426, 519, 355, 394, 447, 432, + 458, 459, 460, 461, 462, 0, 463, 464, 404, 339, + 340, 788, 387, 500, 713, 750, 751, 635, 0, 699, + 636, 646, 380, 671, 683, 682, 494, 595, 0, 694, + 697, 625, 787, 0, 691, 705, 792, 704, 784, 506, + 0, 538, 702, 649, 0, 695, 668, 669, 0, 696, + 664, 700, 356, 433, 524, 581, 0, 637, 0, 606, + 609, 639, 726, 727, 728, 346, 608, 730, 731, 732, + 733, 734, 735, 736, 729, 577, 672, 648, 675, 587, + 651, 650, 0, 0, 686, 604, 687, 688, 488, 489, + 490, 491, 408, 714, 371, 607, 521, 522, 0, 673, + 0, 0, 0, 0, 0, 0, 0, 0, 678, 679, + 676, 797, 0, 737, 738, 0, 0, 601, 602, 403, + 0, 620, 411, 370, 505, 405, 585, 436, 0, 613, + 680, 614, 525, 526, 741, 746, 742, 743, 745, 766, + 495, 425, 431, 542, 446, 468, 528, 584, 503, 533, + 368, 573, 544, 474, 665, 693, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 722, 721, 720, 719, 718, 717, 716, + 715, 0, 0, 662, 385, 785, 779, 786, 767, 770, + 769, 744, 0, 341, 642, 466, 520, 402, 709, 710, + 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, + 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, + 305, 306, 307, 308, 309, 310, 712, 301, 302, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 0, 0, 0, 0, 333, 771, 772, + 773, 774, 775, 0, 0, 334, 335, 336, 0, 0, + 299, 300, 327, 552, 328, 329, 330, 331, 0, 0, + 591, 592, 593, 616, 0, 594, 575, 641, 412, 342, + 556, 583, 782, 783, 0, 0, 0, 0, 0, 0, + 0, 692, 703, 739, 740, 0, 753, 754, 756, 758, + 757, 760, 549, 550, 768, 0, 0, 437, 358, 359, + 496, 497, 535, 0, 438, 439, 440, 444, 441, 442, + 443, 762, 763, 764, 761, 470, 534, 557, 543, 781, + 483, 0, 789, 631, 632, 790, 749, 748, 343, 0, + 337, 338, 706, 707, 0, 0, 537, 482, 638, 502, + 0, 0, 647, 681, 670, 759, 634, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 395, 0, 0, + 465, 685, 666, 677, 667, 508, 652, 653, 654, 661, + 407, 655, 791, 657, 626, 658, 627, 659, 660, 0, + 684, 633, 545, 484, 0, 701, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 268, 0, 0, + 0, 0, 0, 0, 366, 269, 628, 755, 630, 629, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 369, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 546, 574, 0, 588, 0, 434, 435, 0, 0, 0, + 0, 0, 0, 0, 350, 553, 571, 367, 540, 586, + 372, 548, 564, 362, 501, 536, 0, 0, 352, 569, + 547, 479, 351, 0, 529, 392, 409, 389, 499, 0, + 0, 568, 599, 388, 589, 0, 579, 354, 0, 578, + 498, 471, 565, 570, 480, 473, 0, 353, 567, 478, + 472, 448, 399, 615, 449, 450, 451, 452, 453, 454, + 413, 514, 469, 515, 414, 486, 485, 487, 415, 416, + 417, 418, 419, 420, 421, 422, 423, 424, 0, 0, + 0, 0, 0, 610, 611, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 747, 0, 0, 752, 0, 582, 0, 0, 0, 0, + 0, 0, 551, 0, 0, 455, 0, 0, 0, 600, + 0, 532, 504, 793, 0, 0, 530, 467, 566, 516, + 572, 554, 580, 903, 517, 344, 555, 391, 481, 363, + 365, 780, 393, 396, 400, 401, 492, 493, 510, 539, + 558, 559, 560, 390, 377, 531, 378, 410, 379, 345, + 382, 381, 383, 541, 384, 347, 511, 563, 0, 406, + 527, 476, 348, 475, 512, 562, 561, 364, 590, 597, + 598, 689, 0, 603, 794, 795, 796, 612, 0, 518, + 360, 357, 0, 0, 0, 386, 513, 373, 375, 376, + 374, 507, 509, 617, 618, 619, 621, 0, 622, 623, + 0, 0, 0, 0, 624, 690, 708, 674, 643, 605, + 698, 640, 644, 645, 427, 428, 429, 430, 711, 0, + 0, 0, 596, 456, 457, 0, 398, 397, 477, 349, + 0, 0, 445, 426, 519, 355, 394, 447, 432, 458, + 459, 460, 461, 462, 0, 463, 464, 404, 339, 340, + 788, 387, 500, 713, 750, 751, 635, 0, 699, 636, + 646, 380, 671, 683, 682, 494, 595, 0, 694, 697, + 625, 787, 0, 691, 705, 792, 704, 784, 506, 0, + 538, 702, 649, 0, 695, 668, 669, 0, 696, 664, + 700, 356, 433, 524, 581, 0, 637, 0, 606, 609, + 639, 726, 727, 728, 346, 608, 730, 731, 732, 733, + 734, 735, 904, 729, 577, 672, 648, 675, 587, 651, + 650, 0, 0, 686, 604, 687, 688, 488, 489, 490, + 491, 408, 714, 371, 607, 521, 522, 0, 673, 0, + 0, 0, 0, 0, 0, 0, 0, 678, 679, 676, + 797, 0, 737, 738, 0, 0, 601, 602, 403, 0, + 620, 411, 370, 505, 405, 585, 436, 0, 613, 680, + 614, 525, 526, 741, 746, 742, 743, 745, 766, 495, + 425, 431, 542, 446, 468, 528, 584, 503, 533, 368, + 573, 544, 474, 665, 693, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 722, 721, 720, 719, 718, 717, 716, 715, + 0, 0, 662, 385, 785, 779, 786, 767, 770, 769, + 744, 0, 341, 642, 466, 520, 402, 709, 710, 0, + 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, + 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, + 306, 307, 308, 309, 310, 712, 301, 302, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 0, 0, 0, 0, 333, 771, 772, 773, + 774, 775, 0, 0, 334, 335, 336, 0, 0, 299, + 300, 327, 552, 328, 329, 330, 331, 0, 0, 591, + 592, 593, 616, 0, 594, 575, 641, 412, 342, 556, + 583, 782, 783, 0, 0, 0, 0, 0, 0, 0, + 692, 703, 739, 740, 0, 753, 754, 756, 758, 757, + 760, 549, 550, 768, 0, 0, 437, 358, 359, 496, + 497, 535, 0, 438, 439, 440, 444, 441, 442, 443, + 762, 763, 764, 761, 470, 534, 557, 543, 781, 483, + 0, 789, 631, 632, 790, 749, 748, 343, 0, 337, + 338, 706, 707, 0, 0, 537, 482, 638, 502, 0, + 0, 647, 681, 670, 759, 634, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 395, 0, 0, 465, + 685, 666, 677, 667, 508, 652, 653, 654, 661, 407, + 655, 791, 657, 626, 658, 627, 659, 660, 0, 684, + 633, 545, 484, 0, 701, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 268, 0, 0, 0, + 0, 0, 0, 366, 269, 628, 755, 630, 629, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 369, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 546, + 574, 0, 588, 0, 434, 435, 0, 0, 0, 0, + 0, 0, 0, 350, 553, 571, 367, 540, 586, 372, + 548, 564, 362, 501, 536, 0, 0, 352, 569, 547, + 479, 351, 0, 529, 392, 409, 389, 499, 0, 0, + 568, 599, 388, 589, 0, 579, 354, 0, 578, 498, + 471, 565, 570, 480, 473, 0, 353, 567, 478, 472, + 448, 399, 615, 449, 450, 451, 452, 453, 454, 413, + 514, 469, 515, 414, 486, 485, 487, 415, 416, 417, + 418, 419, 420, 421, 422, 423, 424, 0, 0, 0, + 0, 0, 610, 611, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 747, + 0, 0, 752, 0, 582, 0, 0, 0, 0, 0, + 0, 551, 0, 0, 455, 0, 0, 0, 600, 0, + 532, 504, 793, 0, 0, 530, 467, 566, 516, 572, + 554, 580, 523, 517, 344, 555, 391, 481, 363, 365, + 780, 393, 396, 400, 401, 492, 493, 510, 539, 558, + 559, 560, 390, 377, 531, 378, 410, 379, 345, 382, + 381, 383, 541, 384, 347, 511, 563, 0, 406, 527, + 476, 348, 475, 512, 562, 561, 364, 590, 597, 598, + 689, 0, 603, 794, 795, 796, 612, 0, 518, 360, + 357, 0, 0, 0, 386, 513, 373, 375, 376, 374, + 507, 509, 617, 618, 619, 621, 0, 622, 623, 0, + 0, 0, 0, 624, 690, 708, 674, 643, 605, 698, + 640, 644, 645, 427, 428, 429, 430, 711, 0, 0, + 0, 596, 456, 457, 0, 398, 397, 477, 349, 0, + 0, 445, 426, 519, 355, 394, 447, 432, 458, 459, + 460, 461, 462, 0, 463, 464, 404, 339, 340, 788, + 387, 500, 713, 750, 751, 635, 0, 699, 636, 646, + 380, 671, 683, 682, 494, 595, 0, 694, 697, 625, + 787, 0, 691, 705, 792, 704, 784, 506, 0, 538, + 702, 649, 0, 695, 668, 669, 0, 696, 664, 700, + 356, 433, 524, 581, 0, 637, 0, 606, 609, 639, + 726, 727, 728, 346, 608, 730, 731, 732, 733, 734, + 735, 736, 729, 577, 672, 648, 675, 587, 651, 650, + 0, 0, 686, 604, 687, 688, 488, 489, 490, 491, + 408, 714, 371, 607, 521, 522, 0, 673, 0, 0, + 0, 0, 0, 0, 0, 0, 678, 679, 676, 797, + 0, 737, 738, 0, 0, 601, 602, 403, 0, 620, + 411, 370, 505, 405, 585, 436, 0, 613, 680, 614, + 525, 526, 741, 746, 742, 743, 745, 766, 495, 425, + 431, 542, 446, 468, 528, 584, 503, 533, 368, 573, + 544, 474, 665, 693, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 722, 721, 720, 719, 718, 717, 716, 715, 0, + 0, 662, 385, 785, 779, 786, 767, 770, 769, 840, + 0, 341, 642, 466, 520, 402, 709, 710, 0, 765, + 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, + 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, + 307, 308, 309, 310, 712, 301, 302, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, + 324, 0, 0, 0, 0, 333, 771, 772, 773, 774, + 775, 0, 0, 334, 335, 336, 0, 0, 299, 300, + 327, 552, 328, 329, 330, 331, 0, 0, 591, 592, + 593, 616, 0, 594, 575, 641, 412, 342, 556, 583, + 782, 783, 0, 0, 0, 0, 0, 0, 0, 692, + 703, 739, 740, 0, 753, 754, 756, 758, 757, 760, + 549, 550, 768, 0, 0, 437, 358, 359, 496, 497, + 535, 0, 438, 439, 440, 444, 441, 442, 443, 762, + 763, 764, 761, 470, 534, 557, 543, 781, 483, 0, + 789, 631, 632, 790, 749, 748, 343, 0, 337, 338, + 706, 707, 0, 0, 537, 482, 638, 502, 0, 0, + 647, 681, 670, 759, 634, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 395, 0, 0, 465, 685, + 666, 677, 667, 508, 652, 653, 654, 661, 407, 655, + 791, 657, 626, 658, 627, 659, 660, 0, 684, 633, + 545, 484, 0, 701, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 268, 0, 0, 0, 0, + 0, 0, 366, 269, 628, 755, 630, 629, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 369, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 546, 574, + 0, 588, 0, 434, 435, 0, 0, 0, 0, 0, + 0, 0, 350, 553, 571, 367, 540, 586, 372, 548, + 564, 362, 501, 536, 0, 0, 352, 569, 547, 479, + 351, 0, 529, 392, 409, 389, 499, 0, 0, 568, + 599, 388, 589, 0, 579, 354, 0, 578, 498, 471, + 565, 570, 480, 473, 0, 353, 567, 478, 472, 448, + 399, 615, 449, 450, 451, 452, 453, 454, 413, 514, + 469, 515, 414, 486, 485, 487, 415, 416, 417, 418, + 419, 420, 421, 422, 423, 424, 0, 0, 0, 0, + 0, 610, 611, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 747, 0, + 0, 752, 0, 582, 0, 0, 0, 0, 0, 0, + 551, 0, 0, 455, 0, 0, 0, 600, 0, 532, + 504, 793, 0, 0, 530, 467, 566, 516, 572, 554, + 580, 523, 517, 344, 555, 391, 481, 363, 365, 780, + 393, 396, 400, 401, 492, 493, 510, 539, 558, 559, + 560, 390, 377, 531, 378, 410, 379, 345, 382, 381, + 383, 541, 384, 347, 511, 563, 0, 406, 0, 476, + 348, 475, 512, 562, 561, 364, 590, 597, 598, 689, + 0, 603, 794, 795, 796, 612, 0, 518, 360, 357, + 0, 0, 0, 386, 513, 373, 375, 376, 374, 507, + 509, 617, 618, 619, 621, 0, 622, 623, 0, 0, + 0, 0, 624, 690, 708, 674, 643, 605, 698, 640, + 644, 645, 427, 428, 429, 430, 711, 0, 0, 0, + 596, 456, 457, 0, 398, 397, 477, 349, 0, 0, + 445, 426, 519, 355, 394, 447, 432, 458, 459, 460, + 461, 462, 0, 463, 464, 404, 339, 340, 788, 387, + 500, 713, 750, 751, 635, 0, 699, 636, 646, 380, + 671, 683, 682, 494, 595, 0, 694, 697, 625, 787, + 0, 691, 705, 792, 704, 784, 506, 0, 538, 702, + 649, 0, 695, 668, 669, 0, 696, 664, 700, 356, + 433, 524, 581, 0, 637, 0, 606, 609, 639, 726, + 727, 728, 346, 608, 730, 731, 732, 733, 734, 735, + 736, 729, 577, 672, 648, 675, 587, 651, 650, 0, + 0, 686, 604, 687, 688, 488, 489, 490, 491, 408, + 714, 371, 607, 521, 522, 0, 673, 0, 0, 0, + 0, 0, 0, 0, 0, 678, 679, 676, 797, 0, + 737, 738, 0, 0, 601, 602, 403, 0, 620, 411, + 370, 505, 405, 585, 436, 0, 613, 680, 614, 525, + 526, 741, 746, 742, 743, 745, 766, 495, 425, 431, + 542, 446, 468, 528, 584, 503, 533, 368, 573, 544, + 474, 665, 693, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 722, 721, 720, 719, 718, 717, 716, 715, 0, 0, + 662, 385, 785, 779, 786, 767, 770, 769, 744, 0, + 341, 642, 466, 520, 402, 709, 710, 0, 765, 284, + 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, + 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, + 308, 309, 310, 712, 301, 302, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 0, 0, 0, 0, 333, 771, 772, 773, 774, 775, + 0, 0, 334, 335, 336, 0, 0, 299, 300, 327, + 552, 328, 329, 330, 331, 0, 0, 591, 592, 593, + 616, 0, 594, 575, 641, 412, 342, 556, 583, 782, + 783, 0, 0, 0, 0, 0, 0, 0, 692, 703, + 739, 740, 0, 753, 754, 756, 758, 757, 760, 549, + 550, 768, 0, 0, 437, 358, 359, 496, 497, 535, + 0, 438, 439, 440, 444, 441, 442, 443, 762, 763, + 764, 761, 470, 534, 557, 543, 781, 483, 0, 789, + 631, 632, 790, 749, 748, 343, 0, 337, 338, 706, + 707, 0, 0, 537, 482, 638, 502, 0, 0, 647, + 681, 670, 759, 634, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 395, 0, 0, 465, 685, 666, + 677, 667, 508, 652, 653, 654, 661, 407, 655, 791, + 657, 626, 658, 627, 659, 660, 0, 684, 633, 545, + 484, 0, 701, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 268, 0, 0, 0, 0, 0, + 0, 366, 269, 628, 755, 630, 629, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 369, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 546, 574, 0, + 588, 0, 434, 435, 0, 0, 0, 0, 0, 0, + 0, 350, 553, 571, 367, 540, 586, 372, 548, 564, + 362, 501, 536, 0, 0, 352, 569, 547, 479, 351, + 0, 529, 392, 409, 389, 499, 0, 0, 568, 599, + 388, 589, 0, 579, 354, 0, 578, 498, 471, 565, + 570, 480, 473, 0, 353, 567, 478, 472, 448, 399, + 615, 449, 450, 451, 452, 453, 454, 413, 514, 469, + 515, 414, 486, 485, 487, 415, 416, 417, 418, 419, + 420, 421, 422, 423, 424, 0, 0, 0, 0, 0, + 610, 611, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 747, 0, 0, + 752, 0, 582, 0, 0, 0, 0, 0, 0, 551, + 0, 0, 455, 0, 0, 0, 600, 0, 532, 504, + 793, 0, 0, 530, 467, 566, 516, 572, 554, 580, + 523, 517, 344, 555, 391, 481, 363, 365, 780, 393, + 396, 400, 401, 492, 493, 510, 539, 558, 559, 560, + 390, 377, 531, 378, 410, 379, 345, 382, 381, 383, + 541, 384, 347, 511, 563, 0, 406, 527, 476, 348, + 475, 512, 562, 561, 364, 590, 597, 598, 689, 0, + 603, 794, 795, 796, 612, 0, 518, 360, 357, 0, + 0, 0, 386, 513, 373, 375, 376, 374, 507, 509, + 617, 618, 619, 621, 0, 622, 623, 0, 0, 0, + 0, 624, 690, 708, 674, 643, 605, 698, 640, 644, + 645, 427, 428, 429, 430, 711, 0, 0, 0, 596, + 456, 457, 0, 398, 397, 477, 349, 0, 0, 445, + 426, 519, 355, 394, 447, 432, 458, 459, 460, 461, + 462, 0, 463, 464, 404, 339, 340, 788, 387, 500, + 713, 750, 751, 635, 0, 699, 636, 646, 380, 671, + 683, 682, 494, 595, 0, 694, 697, 625, 787, 0, + 691, 705, 792, 704, 784, 506, 0, 538, 702, 649, + 0, 695, 668, 669, 0, 696, 664, 700, 356, 433, + 524, 581, 0, 637, 0, 606, 609, 639, 726, 727, + 728, 346, 608, 730, 731, 732, 733, 734, 735, 736, + 729, 577, 672, 648, 675, 587, 651, 650, 0, 0, + 686, 604, 687, 688, 488, 489, 490, 491, 408, 714, + 371, 607, 521, 522, 0, 673, 0, 0, 0, 0, + 0, 0, 0, 0, 678, 679, 676, 797, 0, 737, + 738, 0, 0, 601, 602, 403, 0, 620, 411, 370, + 505, 405, 585, 436, 0, 613, 680, 614, 525, 526, + 741, 746, 742, 743, 745, 766, 495, 425, 431, 542, + 446, 468, 528, 584, 503, 533, 368, 573, 544, 474, + 665, 693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 718, - 717, 716, 715, 714, 713, 712, 711, 0, 0, 658, - 384, 781, 775, 782, 763, 766, 765, 740, 0, 341, - 638, 464, 518, 401, 705, 706, 0, 761, 284, 285, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 722, + 721, 720, 719, 718, 717, 716, 715, 0, 0, 662, + 385, 785, 779, 786, 767, 770, 769, 744, 0, 341, + 642, 466, 520, 402, 709, 710, 0, 765, 284, 285, 286, 287, 288, 289, 290, 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, 304, 305, 306, 307, 308, - 309, 310, 708, 301, 302, 311, 312, 313, 314, 315, + 309, 310, 712, 301, 302, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 0, - 0, 0, 0, 333, 767, 768, 769, 770, 771, 0, - 0, 334, 335, 336, 0, 0, 299, 300, 327, 549, - 328, 329, 330, 331, 0, 0, 587, 588, 589, 612, - 0, 590, 572, 637, 411, 342, 553, 579, 778, 779, - 0, 0, 0, 0, 0, 0, 0, 688, 699, 735, - 736, 0, 749, 750, 752, 754, 753, 756, 546, 547, - 764, 0, 0, 435, 357, 358, 494, 495, 532, 0, - 436, 437, 438, 442, 439, 440, 441, 758, 759, 760, - 757, 468, 531, 554, 540, 777, 481, 0, 785, 627, - 628, 786, 745, 744, 343, 0, 337, 338, 702, 703, - 0, 0, 534, 480, 634, 500, 0, 0, 643, 677, - 666, 755, 630, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 394, 0, 0, 463, 681, 662, 673, - 663, 506, 648, 649, 650, 657, 406, 651, 787, 653, - 622, 654, 623, 655, 656, 0, 680, 629, 542, 482, - 0, 697, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 268, 0, 0, 0, 0, 0, 0, - 365, 269, 624, 751, 626, 625, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 368, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 543, 571, 0, 584, - 0, 432, 433, 0, 0, 0, 0, 0, 0, 0, - 350, 550, 568, 366, 537, 582, 371, 545, 561, 361, - 499, 533, 0, 0, 352, 566, 544, 477, 351, 0, - 526, 391, 408, 388, 497, 0, 0, 565, 595, 387, - 585, 0, 576, 354, 0, 575, 496, 469, 562, 567, - 478, 471, 0, 353, 564, 476, 470, 446, 398, 611, - 447, 448, 449, 450, 451, 452, 412, 512, 467, 513, - 413, 484, 483, 485, 414, 415, 416, 417, 418, 419, - 420, 421, 422, 423, 0, 0, 0, 0, 0, 606, - 607, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 743, 0, 0, 748, - 0, 578, 0, 0, 0, 0, 0, 0, 548, 0, - 0, 453, 0, 0, 0, 596, 0, 529, 502, 789, - 0, 0, 527, 465, 563, 514, 569, 551, 577, 521, - 515, 344, 552, 390, 479, 362, 364, 776, 392, 395, - 399, 400, 490, 491, 508, 536, 555, 556, 557, 389, - 376, 528, 377, 409, 378, 345, 381, 380, 382, 538, - 383, 347, 509, 560, 0, 405, 524, 474, 348, 473, - 510, 559, 558, 363, 586, 593, 594, 685, 0, 599, - 790, 791, 792, 608, 0, 516, 359, 356, 0, 0, - 0, 385, 511, 372, 374, 375, 373, 505, 507, 613, - 614, 615, 617, 0, 618, 619, 0, 0, 0, 0, - 620, 686, 704, 670, 639, 601, 694, 636, 640, 641, - 426, 427, 428, 429, 707, 0, 0, 0, 592, 454, - 455, 0, 397, 396, 475, 349, 0, 0, 443, 425, - 517, 355, 393, 445, 431, 456, 457, 458, 459, 460, - 0, 461, 462, 403, 339, 340, 784, 386, 498, 709, - 746, 747, 631, 0, 695, 632, 642, 379, 667, 679, - 678, 492, 591, 0, 690, 693, 621, 783, 0, 687, - 701, 788, 700, 780, 504, 0, 535, 698, 645, 0, - 691, 664, 665, 0, 692, 660, 696, 0, 633, 0, - 602, 605, 635, 722, 723, 724, 346, 604, 726, 727, - 728, 729, 730, 731, 732, 725, 574, 668, 644, 671, - 583, 647, 646, 0, 0, 682, 600, 683, 684, 486, - 487, 488, 489, 407, 710, 370, 603, 519, 520, 0, - 669, 0, 0, 0, 0, 0, 0, 0, 0, 674, - 675, 672, 793, 0, 733, 734, 0, 0, 597, 598, - 402, 0, 616, 410, 369, 503, 404, 581, 434, 0, - 609, 676, 610, 522, 523, 737, 742, 738, 739, 741, - 762, 493, 424, 430, 539, 444, 466, 525, 580, 501, - 530, 367, 570, 541, 472, 661, 689, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 325, 326, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 718, 717, 716, 715, 714, 713, - 712, 711, 0, 0, 658, 384, 781, 775, 782, 763, - 766, 765, 740, 0, 341, 638, 464, 518, 401, 705, - 706, 0, 761, 284, 285, 286, 287, 288, 289, 290, - 291, 332, 292, 293, 294, 295, 296, 297, 298, 303, - 304, 305, 306, 307, 308, 309, 310, 708, 301, 302, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 324, 0, 0, 0, 0, 333, 767, - 768, 769, 770, 771, 0, 0, 334, 335, 336, 0, - 0, 299, 300, 327, 549, 328, 329, 330, 331, 0, - 0, 587, 588, 589, 612, 0, 590, 572, 637, 411, - 342, 553, 579, 778, 779, 0, 0, 0, 0, 0, - 0, 0, 688, 699, 735, 736, 0, 749, 750, 752, - 754, 753, 756, 546, 547, 764, 0, 0, 435, 357, - 358, 494, 495, 532, 0, 436, 437, 438, 442, 439, - 440, 441, 758, 759, 760, 757, 468, 531, 554, 540, - 777, 481, 0, 785, 627, 628, 786, 745, 0, 343, - 0, 337, 338, 702, 703, 0, 0, 534, 480, 634, + 0, 0, 0, 333, 771, 772, 773, 774, 775, 0, + 0, 334, 335, 336, 0, 0, 299, 300, 327, 552, + 328, 329, 330, 331, 0, 0, 591, 592, 593, 616, + 0, 594, 575, 641, 412, 342, 556, 583, 782, 783, + 0, 0, 0, 0, 0, 0, 0, 692, 703, 739, + 740, 0, 753, 754, 756, 758, 757, 760, 549, 550, + 768, 0, 0, 437, 358, 359, 496, 497, 535, 0, + 438, 439, 440, 444, 441, 442, 443, 762, 763, 764, + 761, 470, 534, 557, 543, 781, 483, 0, 789, 631, + 632, 790, 749, 0, 343, 0, 337, 338, 706, 707, + 0, 0, 537, 482, 638, } var yyPact = [...]int{ - 6178, -1000, -1000, -365, -1000, -1000, -1000, -1000, -1000, 20904, + 6208, -1000, -1000, -382, -1000, -1000, -1000, -1000, -1000, 20971, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 74894, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 823, 74894, 1559, -358, -1000, 4064, -1000, 1659, + -1000, -1000, -1000, -1000, 668, 72617, 22506, -1000, 74894, 990, + 978, 80963, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 74543, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 760, 74543, 1418, -326, -1000, 4043, -1000, 1541, - -1000, -1000, -1000, -1000, 576, 72278, 22431, -1000, 74543, 964, - 960, 80580, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 1569, 1568, 6935, -1000, 80204, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 1382, 7612, 74135, 16384, 4047, -167, + -1000, -1000, 2652, 49, 3951, 911, 80, 62, 970, 1823, + 1844, 2028, 1801, 74894, 1787, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 5219, 34665, + 73376, 1676, 4619, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 2030, 1561, 1676, 29355, 412, 406, 2159, 4827, 2209, -1000, + -1000, 50, 5910, -1000, -1000, 2500, 74894, 6208, 271, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 16384, 16384, 20971, -434, 20971, 16384, 74894, 74894, -1000, -1000, + -1000, -1000, 1559, -358, 72617, 1382, 7612, 16384, 4047, 3951, + 911, 80, 62, 970, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 1445, 1437, 6632, -1000, 79825, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 1305, 6786, 73788, 16341, 4025, -117, - -1000, -1000, 2341, 84, 3933, 805, 89, 85, 947, 1698, - 1730, 2122, 1932, 74543, 1645, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 7165, 34526, - 73033, 1714, 4600, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 509, 1420, 1714, 29244, 360, 354, 2531, 4806, 2318, -1000, - -1000, 77, 2266, -1000, -1000, 2491, 74543, 6178, 290, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 16341, 16341, 20904, -412, 20904, 16341, 74543, 74543, -1000, -1000, - -1000, -1000, 1418, -326, 72278, 1305, 6786, 16341, 4025, 3933, - 805, 89, 85, 947, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 50, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 77, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, @@ -10532,19 +10584,19 @@ 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, 406, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 354, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 4619, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 4600, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, @@ -10552,549 +10604,547 @@ 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, 494, -1000, 2579, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 3633, 4391, + 2569, 74894, 3950, -1000, -1000, -1000, -1000, -1000, -1000, 2159, + 4727, 71858, -1000, -1000, 4804, -1000, 74894, 220, 74894, 534, + 2967, -1000, 2245, 1343, 1325, 2469, 727, 2564, -1000, -1000, + -1000, -1000, -1000, -1000, 4096, 1158, 4803, -1000, 74894, 74894, + 74894, 4409, 74894, 74894, 547, 4724, -1000, 256, -61, -325, + -340, 4440, 2658, 2658, 4770, 4770, 4722, 4721, 1194, 1190, + 1170, 2658, 1038, -1000, 2828, 2828, 2828, 2828, 2658, 782, + 1221, 4717, 4390, 4717, 374, 2828, 297, 2658, 2658, 297, + 2658, 2658, 887, -1000, 2937, 896, 533, -257, -1000, -1000, + -1000, 2828, 2828, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 4693, 4692, -1000, 734, 1191, -1000, 6310, 4633, 2250, 1528, + 4437, -1000, -1000, 4389, -1000, 731, 939, 523, 1011, 812, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 650, -1000, 4699, + -1000, -1000, 710, -1000, -1000, 735, -1000, -1000, -1000, 401, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 209, 74894, -1000, -1000, 1977, 3121, 16384, 3381, -1000, + 845, 2773, -1000, -1000, -1000, 8740, 20199, 20199, 20199, 20199, + 20199, 74894, -1000, -1000, 4231, 16384, 4388, 4387, 4386, 4385, + -1000, -1000, -1000, -1000, -1000, -1000, 4382, 2561, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 3257, -1000, -1000, + -1000, 19436, -1000, 4359, 4357, 4356, 4355, 4353, 4352, 4351, + 4350, 4345, 4342, 4341, 4338, 4337, 4336, 4335, 4147, 23265, + 4332, 3946, 3945, 4328, 4326, 4325, 3943, 4318, 4317, 4314, + 4147, 4147, 4310, 4308, 4307, 4306, 4304, 4303, 4302, 4300, + 4298, 4297, 4296, 4293, 4291, 4289, 4286, 4285, 4284, 4283, + 4282, 4281, 4280, 4276, 4275, 4274, 4272, 4271, 4270, 4269, + 4267, 4264, 4263, 4259, 4258, 4257, 4256, 4254, 4251, 4250, + 4246, 4243, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 525, -1000, 2493, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 3575, 4390, 2490, 74543, 3931, -1000, - -1000, -1000, -1000, -1000, -1000, 2531, 4711, 71523, -1000, -1000, - 4779, -1000, 74543, 207, 74543, 471, 2897, -1000, 813, 1590, - 982, 1717, 610, 2453, -1000, -1000, -1000, -1000, -1000, -1000, - 4052, 1128, 4778, -1000, 74543, 74543, 74543, 4406, 74543, 74543, - 580, 4706, -1000, 252, -59, -296, -311, 4432, 2742, 2742, - 4752, 4752, 4705, 4704, 1212, 1210, 1186, 2742, 1021, -1000, - 2757, 2757, 2757, 2757, 2742, 830, 1200, 4710, 4389, 4710, - 335, 2757, 303, 2742, 2742, 303, 2742, 2742, 811, -1000, - 2723, 897, 636, -205, -1000, -1000, -1000, 2757, 2757, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 4672, 4667, -1000, 774, - 1158, -1000, 7508, 4611, 2259, 1446, 4428, -1000, -1000, 4387, - -1000, 629, 632, 524, 744, 754, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 655, -1000, 4681, -1000, -1000, 605, -1000, - -1000, 608, -1000, -1000, -1000, 351, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 150, 74543, -1000, - -1000, 1877, 3162, 16341, 3248, -1000, 701, 2709, -1000, -1000, - -1000, 8737, 20136, 20136, 20136, 20136, 20136, 74543, -1000, -1000, - 4226, 16341, 4386, 4385, 4384, 4383, -1000, -1000, -1000, -1000, - -1000, -1000, 4382, 2452, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 3108, -1000, -1000, -1000, 19377, -1000, 4378, - 4374, 4351, 4350, 4349, 4348, 4346, 4345, 4344, 4338, 4337, - 4336, 4335, 4334, 4329, 4122, 23186, 4326, 3928, 3927, 4324, - 4320, 4314, 3924, 4311, 4306, 4302, 4122, 4122, 4301, 4300, - 4299, 4298, 4296, 4294, 4293, 4292, 4291, 4290, 4289, 4288, - 4287, 4282, 4281, 4280, 4279, 4278, 4277, 4274, 4272, 4270, - 4268, 4267, 4266, 4265, 4264, 4263, 4262, 4261, 4257, 4255, - 4253, 4252, 4250, 4247, 4242, 4240, 4239, 4238, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2159, 4172, 4861, + 2140, -1000, 4242, 4830, 4756, 4726, 1848, 16384, -241, 4680, + 4676, 4674, 4668, 4241, 3542, -1000, -1000, 157, 74894, 74894, + 363, 74894, -270, 547, 904, -32, -42, 901, -45, 1376, + -1000, 795, -1000, -1000, 1794, -1000, 1762, 79445, 1471, -1000, + -1000, 74894, 1333, 1333, 1333, -302, 532, 1333, 74894, 946, + 1395, 1644, 1333, 1333, 1333, 1333, 1397, 1333, 1551, 1542, + 1541, 1333, 81, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 2965, 2962, 4539, 3094, 3003, 1311, 71858, 71858, 74894, + -1000, 2333, 74894, -1000, 4216, 1734, -1000, -1000, -1000, -1000, + 60472, -303, 530, 1382, 1382, 74894, 1382, 74894, 697, 481, + 74894, 1382, 1382, 1382, 74894, 1387, -346, 239, 78686, 77927, + 3717, 734, 1189, 1183, 2266, 2939, -1000, 2724, 74894, 74894, + 2724, 2724, 33906, 33147, -1000, 74894, -1000, 4830, 1848, -1000, + 4715, 1892, -1000, 4760, 4118, 2679, 4827, 4827, 4172, -1000, + -167, -46, 1382, 1382, -306, 529, 1382, 1382, 1382, 1382, + 1382, 1536, 1382, 1382, 1382, 74894, 1382, 71099, 1382, 900, + 1382, 1382, 1382, 13327, 2500, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 20971, + 3206, 3337, 270, 64, -319, 403, -1000, -1000, 74894, 4598, + 2626, -1000, -1000, -1000, 4189, 4185, -1000, 4188, 4188, 4188, + 4188, 1752, -1000, 4185, -1000, -1000, -1000, 4185, -1000, -1000, + -1000, -1000, 4188, 4188, 4188, 4188, 4188, 4188, 4187, 4239, + -1000, -1000, 4186, 4186, 4186, 4185, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 1875, 4182, 4183, 4183, 4182, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 74894, 4833, -1000, -1000, 16384, 74894, + 1467, 4618, 4830, 4620, 4717, 4756, 1288, 3439, -1000, -317, + 74894, 626, -1000, 2523, 3536, 3942, -1000, 727, -1000, 2401, + 727, -1000, 1414, 1414, 2834, -1000, 1910, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 74894, 209, 7012, -1000, -1000, -1000, + 3887, 1091, -1000, 4238, 805, -1000, -1000, -1000, -1000, 74894, + 4717, -67, 4719, 2658, 3106, 3026, 2658, -1000, -1000, -1000, + 1177, 4770, 20199, 20199, -1000, -1000, 16384, -1000, 477, 70340, + 2828, 2658, 2658, -1000, -1000, 74894, -1000, -1000, -1000, 2828, + 74894, 2828, 2828, 4770, 2828, -1000, -1000, -1000, 2658, 2658, + -1000, -1000, 16384, 2629, -1000, -1000, 2828, 2828, -1000, -1000, + 4770, 74894, 395, 4770, 4770, 365, -1000, -1000, 74894, -1000, + 2658, 3941, -1000, 74894, 74894, 1333, 74894, -1000, 74894, 74894, + -1000, -1000, -1000, 1075, 2096, 2342, -1000, 804, 7633, 58195, + 734, 58195, 74894, -1000, -1000, -1000, -1000, -1000, -1000, 386, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 2531, 4179, 4828, 2004, -1000, 4237, 4818, - 4738, 4708, 2126, 16341, -191, 4669, 4654, 4652, 4644, 4235, - 3501, -1000, -1000, 184, 74543, 74543, 368, 74543, -216, 580, - 840, 14, 5, 838, -1, 1577, -1000, 802, -1000, -1000, - 1765, -1000, 1618, 79070, 1363, -1000, -1000, 74543, 1296, 1296, - 1296, -272, 467, 1296, 74543, 876, 1330, 1613, 1296, 1296, - 1296, 1296, 1367, 1296, 1417, 1416, 1411, 1296, 118, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2896, 2894, 4518, - 3047, 2951, 1264, 71523, 71523, 74543, -1000, 2306, 74543, -1000, - 4212, 1598, -1000, -1000, -1000, -1000, 60197, -274, 459, 1305, - 1305, 74543, 1305, 74543, 617, 411, 74543, 1305, 1305, 1305, - 74543, 1308, -310, 244, 78315, 77560, 3570, 774, 1155, 1153, - 2224, 2830, -1000, 2762, 74543, 74543, 2762, 2762, 33771, 33016, - -1000, 74543, -1000, 4818, 2126, -1000, 4699, 2214, -1000, 4742, - 4104, 2443, 4806, 4806, 4179, -1000, -117, -9, 1305, 1305, - -276, 450, 1305, 1305, 1305, 1305, 1305, 1408, 1305, 1305, - 1305, 74543, 1305, 70768, 1305, 829, 1305, 1305, 1305, 13300, - 2491, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 20904, 3023, 3147, 288, 80, - -308, 457, -1000, -1000, 74543, 4579, 2560, -1000, -1000, -1000, - 4184, 4177, -1000, 4181, 4181, 4181, 4181, 1710, -1000, 4177, - -1000, -1000, -1000, 4177, -1000, -1000, -1000, -1000, 4181, 4181, - 4181, 4181, 4181, 4181, 4180, 4234, -1000, -1000, 4178, 4178, - 4178, 4177, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1872, 4175, 4176, - 4176, 4175, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 712, -1000, 4802, 16384, 16384, 16384, + 16384, -1000, 1285, 18673, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 20199, 20199, 20199, 20199, 20199, 20199, 20199, 20199, 20199, + 20199, 20199, 20199, 20199, 20199, 4230, 3083, 3020, 4704, 20199, + 20199, 20199, 20199, 20199, 405, 36942, 2679, 3954, 2334, 443, + 2644, 2644, 2644, 2644, 2644, 16384, -1000, 3002, 3121, 16384, + 16384, 16384, 16384, 46050, 74894, -1000, -1000, 8740, 6091, 16384, + 16384, 7167, 20199, 16384, 4664, 16384, 16384, 16384, 4115, 9503, + 74894, 16384, -1000, 4114, 4113, -1000, -1000, 3264, 16384, -1000, + -1000, 16384, -1000, -1000, 16384, 20199, 16384, -1000, 16384, 16384, + 16384, -1000, -1000, 2112, 2112, 1439, 4664, 16384, 16384, 4664, + 4664, 2984, 16384, 16384, 4664, 4664, 4664, 2969, 4664, 4664, + 4664, 4664, 4664, 4664, 4664, 4013, 4664, 4664, 4664, 4664, + 4664, 4112, 4109, 4108, 4107, 16384, 4106, 16384, 16384, 16384, + 16384, 16384, 15621, 4830, 2159, 4715, -167, 14090, 4620, 4717, + 4604, -141, 4756, -1000, -1000, -1000, -1000, 3121, -247, 4236, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 74894, 3937, + 3928, -387, -388, 1836, -388, 2515, -1000, -282, 1815, 337, + 74894, -1000, 3927, 3535, 74894, 3926, 3533, 501, 497, 74894, + 74894, 74894, 233, 1818, 1770, 1784, -1000, -1000, 74894, 77168, + -1000, 74894, 2608, 74894, 74894, 1333, 1333, 74894, 4653, -1000, + 74894, 74894, 1333, 1333, -1000, 68063, 3918, 58195, 74894, 74894, + 734, 74894, 74894, 1333, 1333, 1333, 74894, -1000, 4548, 58195, + 4543, 2037, 2991, -1000, -1000, 74894, 16384, 2991, 2027, 4235, + 1311, 1311, -1000, 74894, 2333, 4651, 74894, 1387, -1000, 600, + -1000, -1000, -1000, -1000, 76409, 76409, 25548, 76409, -1000, 254, + 74894, 74894, 74894, 74894, 5471, 74894, 576, 4632, 1621, 68063, + 69581, 4691, -1000, 58195, 74894, 74894, 2328, -1000, 1456, 30114, + -1000, 74894, 2282, -1000, 246, -1000, 227, 239, 2724, 239, + 2724, 1451, -1000, 1064, 1492, 30873, 968, 58195, 11038, -1000, + -1000, 2724, 2724, 11038, 11038, 2532, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 2325, -1000, 553, 4715, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -167, 16384, + -1000, -1000, 4715, 4715, 1848, 2277, 3530, 68822, 74894, 1382, + 1382, 74894, 68063, 58195, 734, 74894, 1382, 74894, 74894, 74894, + -1000, 74894, -1000, 4626, 74894, 1382, 74894, 74894, 74894, 2178, + -1000, -1000, 32388, 2504, -1000, -1000, 2979, -1000, 16384, 20971, + -222, 16384, 20971, 20971, 16384, 20971, -1000, 16384, 2463, -1000, + -1000, 652, -1000, -1000, 3520, -1000, 3519, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 74543, 4811, -1000, -1000, 16341, 74543, 1360, 4599, 4818, 4604, - 4710, 4738, 1241, 3400, -1000, -287, 74543, 500, -1000, 2444, - 3500, 3918, -1000, 610, -1000, 1348, 610, -1000, 1125, 1125, - 2719, -1000, 2014, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 74543, 150, 6128, -1000, -1000, -1000, 3867, 1026, -1000, 4232, - 812, -1000, -1000, -1000, -1000, 74543, 4710, -24, 4703, 2742, - 2976, 2958, 2742, -1000, -1000, -1000, 1150, 4752, 20136, 20136, - -1000, -1000, 16341, -1000, 437, 70013, 2757, 2742, 2742, -1000, - -1000, 74543, -1000, -1000, -1000, 2757, 74543, 2757, 2757, 4752, - 2757, -1000, -1000, -1000, 2742, 2742, -1000, -1000, 16341, 2533, - -1000, -1000, 2757, 2757, -1000, -1000, 4752, 74543, 350, 4752, - 4752, 342, -1000, -1000, 74543, -1000, 2742, 3914, -1000, 74543, - 74543, 1296, 74543, -1000, 74543, 74543, -1000, -1000, -1000, 994, - 2219, 2118, -1000, 585, 4968, 57932, 774, 57932, 74543, -1000, - -1000, -1000, -1000, -1000, -1000, 334, -1000, -1000, -1000, -1000, + 3917, 3917, -1000, 3518, -1000, -1000, -1000, -1000, 4182, 3513, + -1000, -1000, 3512, -1000, -1000, -1000, -1000, -81, 4105, 1977, + -1000, 3914, 3913, 4715, -1000, 4756, 437, 4756, 4604, 2242, + 4232, 1382, -1000, 266, -400, 2960, 2950, 2946, 4703, 74894, + -1000, 4718, -1000, -1000, 727, -1000, -1000, -1000, 1414, 818, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2499, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 30873, -1000, -1000, -1000, -1000, 755, 6979, 2, 0, 2321, + -1000, -1000, 74894, -1000, 74894, -1000, 74894, -1000, -79, -1000, + -1000, 3509, 4732, 74894, 4770, 74894, -307, 4770, 4770, 74894, + -311, 4770, 734, -1000, 2773, 2773, 3121, 74894, 74894, 74894, + 4408, 74894, 247, 74894, 4770, 4770, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 2828, 4770, 4770, 2356, 4103, 2658, 2828, + -1000, -1000, 2828, -400, -1000, 2828, -1000, -1000, -1000, -400, + 2498, -400, 74894, -1000, -1000, -1000, -1000, -1000, 804, 58195, + 64267, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2376, -1000, + -1000, -1000, 1450, 586, 2831, -1000, -1000, 425, 285, 544, + 1610, 3911, 3121, -1000, 3037, 3054, -1000, 1377, 1336, -1000, + -1000, -1000, -1000, 4231, -1000, -1000, -1000, 3342, 3191, -1000, + 3044, 3044, 2551, 2551, 2551, 2551, 2551, 2933, 2933, 2773, + 2773, -1000, -1000, -1000, 8740, 4230, 20199, 20199, 20199, 20199, + 4230, 20199, 20199, 20199, 20199, 4229, -1000, 1572, 1572, 6047, + 5926, 2644, -1000, -1000, 2585, 2585, -1000, -1000, -1000, -1000, + 16384, 251, 2974, -1000, 16384, 3642, 2457, 3435, 2273, 2825, + -1000, 4185, 16384, 2470, 355, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 723, -1000, 4777, 16341, 16341, 16341, 16341, -1000, 1228, 18618, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 20136, 20136, 20136, - 20136, 20136, 20136, 20136, 20136, 20136, 20136, 20136, 20136, 20136, - 20136, 4225, 2969, 2774, 4687, 20136, 20136, 20136, 20136, 20136, - 422, 36791, 2443, 3925, 2307, 490, 2601, 2601, 2601, 2601, - 2601, 16341, -1000, 2950, 3162, 16341, 16341, 16341, 16341, 45851, - 74543, -1000, -1000, 8737, 7112, 16341, 16341, 6695, 20136, 16341, - 4638, 16341, 16341, 16341, 4101, 9496, 74543, 16341, -1000, 4099, - 4098, -1000, -1000, 3175, 16341, -1000, -1000, 16341, -1000, -1000, - 16341, 20136, 16341, -1000, 16341, 16341, 16341, -1000, -1000, 879, - 879, 1410, 4638, 16341, 16341, 4638, 4638, 2849, 16341, 16341, - 4638, 4638, 4638, 2804, 4638, 4638, 4638, 4638, 4638, 4638, - 4638, 4019, 4638, 4638, 4638, 4638, 4638, 4097, 4094, 4093, - 4092, 16341, 4090, 16341, 16341, 16341, 16341, 16341, 15582, 4818, - 2531, 4699, -117, 14059, 4604, 4710, 4585, -91, 4738, -1000, - -1000, -1000, -1000, 3162, -195, 4231, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 74543, 3913, 3910, -377, -387, 1639, - -387, 2437, -1000, -232, 1660, 349, 74543, -1000, 3900, 3498, - 74543, 3899, 3482, 436, 429, 74543, 74543, 74543, 235, 1655, - 1626, 1634, -1000, -1000, 74543, 76805, -1000, 74543, 2641, 74543, - 74543, 1296, 1296, 74543, 4634, -1000, 74543, 74543, 1296, 1296, - -1000, 67748, 3888, 57932, 74543, 74543, 774, 74543, 74543, 1296, - 1296, 1296, 74543, -1000, 4528, 57932, 4523, 1895, 2945, -1000, - -1000, 74543, 16341, 2945, 2136, 4230, 1264, 1264, -1000, 74543, - 2306, 4633, 74543, 1308, -1000, 489, -1000, -1000, -1000, -1000, - 76050, 76050, 25457, 76050, -1000, 274, 74543, 74543, 74543, 74543, - 5649, 74543, 659, 4609, 1693, 67748, 69258, 4665, -1000, 57932, - 74543, 74543, 2300, -1000, 1359, 29999, -1000, 74543, 2246, -1000, - 229, -1000, 231, 244, 2762, 244, 2762, 1358, -1000, 986, - 593, 30754, 914, 57932, 11023, -1000, -1000, 2762, 2762, 11023, - 11023, 2451, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2299, - -1000, 536, 4699, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -117, 16341, -1000, -1000, 4699, 4699, - 2126, 2243, 3479, 68503, 74543, 1305, 1305, 74543, 67748, 57932, - 774, 74543, 1305, 74543, 74543, 74543, -1000, 74543, -1000, 4608, - 74543, 1305, 74543, 74543, 74543, 2247, -1000, -1000, 32261, 2435, - -1000, -1000, 2939, -1000, 16341, 20904, -177, 16341, 20904, 20904, - 16341, 20904, -1000, 16341, 2422, -1000, -1000, 5648, -1000, -1000, - 3472, -1000, 3469, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 3887, 3887, -1000, 3467, - -1000, -1000, -1000, -1000, 4175, 3461, -1000, -1000, 3460, -1000, - -1000, -1000, -1000, -42, 4088, 1877, -1000, 3877, 3875, 4699, - -1000, 4738, 487, 4738, 4585, 2213, 4229, 1305, -1000, 268, - -393, 2893, 2891, 2888, 4686, 74543, -1000, 4701, -1000, -1000, - 610, -1000, -1000, -1000, 1125, 846, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 2434, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 30754, -1000, -1000, -1000, - -1000, 955, 6945, 76, 75, 2293, -1000, -1000, 74543, -1000, - 74543, -1000, 74543, -1000, -39, -1000, -1000, 3459, 4714, 74543, - 4752, 74543, -278, 4752, 4752, 74543, -281, 4752, 774, -1000, - 2709, 2709, 3162, 74543, 74543, 74543, 4405, 74543, 250, 74543, - 4752, 4752, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2757, - 4752, 4752, 2431, 4087, 2742, 2757, -1000, -1000, 2757, -393, - -1000, 2757, -1000, -1000, -1000, -393, 2418, -393, 74543, -1000, - -1000, -1000, -1000, -1000, 585, 57932, 63972, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 2389, -1000, -1000, -1000, 1352, 516, - 2718, -1000, -1000, 418, 286, 474, 1521, 3874, 3162, -1000, - 2994, 2986, -1000, 1485, 1436, -1000, -1000, -1000, -1000, 4226, - -1000, -1000, -1000, 3005, 3444, -1000, 2887, 2887, 2509, 2509, - 2509, 2509, 2509, 2929, 2929, 2709, 2709, -1000, -1000, -1000, - 8737, 4225, 20136, 20136, 20136, 20136, 4225, 20136, 20136, 20136, - 20136, 4224, -1000, 1475, 1475, 5417, 5387, 2601, -1000, -1000, - 2538, 2538, -1000, -1000, -1000, -1000, 16341, 249, 2920, -1000, - 16341, 3594, 2525, 3439, 2079, 2714, -1000, 4177, 16341, 2414, - 358, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 4102, 4101, 3409, 4800, 5874, + 4090, 16384, -1000, -1000, 2818, 2817, 2815, -1000, 3360, 14858, + -1000, -1000, -1000, 4086, 2446, 4085, -1000, -1000, -1000, 4083, + 2812, 2022, 4081, 2730, 4080, 4079, 4076, 4074, 2315, 2312, + 2311, -1000, -1000, -1000, -1000, 16384, 3939, 3935, 16384, 16384, + 16384, 4072, 2811, 2799, 16384, 16384, 16384, 16384, 4070, 16384, + 16384, 16384, 16384, 16384, 16384, 16384, 16384, -365, 16384, 16384, + 16384, 16384, 16384, 431, 431, 431, 431, 3907, 431, 2533, + 2430, 3900, 3879, 2388, 2303, 2301, 4715, 4830, -1000, -1000, + 2774, -1000, 3121, -1000, -1000, 4756, 4756, -1000, 4828, 4604, + -245, 4228, 3508, 2295, -1000, -1000, -355, 3830, 1449, 74894, + -283, 74894, 1449, 74894, 74894, 2944, 1449, 74894, -285, 3910, + -1000, -1000, 3898, -1000, -1000, 74894, 74894, 74894, 74894, -53, + 4617, 4616, -1000, -1000, 1806, 1753, 1788, -1000, 74894, -1000, + 3896, 4625, 4624, 4716, 1352, 74894, 74894, -12, 74894, 4227, + 4226, 2445, 74894, 74894, 639, -1000, -1000, 74894, 2189, -1000, + 586, 182, 996, 2040, 4407, 1313, 74894, 74894, 74894, 4650, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 4086, 4083, 3385, 4776, 5005, 4082, 16341, -1000, -1000, - 2713, 2712, 2706, -1000, 3252, 14823, -1000, -1000, -1000, 4081, - 2410, 4079, -1000, -1000, -1000, 4076, 2702, 2038, 4075, 2836, - 4074, 4072, 4071, 4069, 2290, 2289, 2284, -1000, -1000, -1000, - -1000, 16341, 3917, 3912, 16341, 16341, 16341, 4068, 2699, 2698, - 16341, 16341, 16341, 16341, 4066, 16341, 16341, 16341, 16341, 16341, - 16341, 16341, 16341, -333, 16341, 16341, 16341, 16341, 16341, 393, - 393, 393, 393, 3901, 393, 2404, 2322, 3897, 3873, 2467, - 2283, 2278, 4699, 4818, -1000, -1000, 2697, -1000, 3162, -1000, - -1000, 4738, 4738, -1000, 4810, 4585, -193, 4223, 3458, 2264, - -1000, -1000, -323, 3786, 1347, 74543, -240, 74543, 1347, 74543, - 74543, 2885, 1347, 74543, -249, 3872, -1000, -1000, 3863, -1000, - -1000, 74543, 74543, 74543, 74543, -14, 4596, 4595, -1000, -1000, - 1656, 1614, 1669, -1000, 74543, -1000, 3860, 4606, 4593, 4700, - 1341, 74543, 74543, 69, 74543, 4222, 4221, 2406, 74543, 74543, - 563, -1000, -1000, 74543, 2015, -1000, 516, 128, 978, 1935, - 4404, 1317, 74543, 74543, 74543, 4630, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 1871, -1000, 4591, 4078, - 3122, 1871, 4424, -120, -1000, 28489, 82090, 74543, 2136, 2136, - -1000, 4220, 2693, -1000, 66993, 60197, 60197, 60197, 60197, 60197, - 60197, 60197, 60197, -1000, 4489, 4447, 4219, -1000, 4473, 4455, - 4454, 847, 4487, 4481, 4439, 4212, -1000, 58687, -1000, -1000, - -1000, 2443, 2692, -1000, 413, 3551, 1512, 16341, 4659, 4557, - 4628, 4212, 2261, -1000, -1000, -1000, -1000, 4741, 1032, 2200, - 1283, 1283, 1712, 4739, 26212, -1000, 2734, 1910, 1346, 4559, - 625, -1000, 2734, -34, 1258, 2734, 2734, 2734, 2734, 2734, - 2734, 2734, 2734, 1116, 1104, 2734, 2734, 2734, 2734, 2734, - 2734, 2734, 2734, 2734, 2734, 2734, 1721, 2734, 2734, 2734, - 2734, 2734, -1000, 2734, 4218, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 1157, 1041, -1000, -1000, 465, 774, 1345, 266, - 257, 558, 4657, 671, -1000, 660, 2015, 983, 4651, 748, - 74543, 74543, 352, 2002, 2762, 244, 219, -1000, -1000, 2246, - 11023, 2246, 11023, 3457, -1000, -1000, 1342, -1000, -1000, 1935, - -1000, 74543, 74543, -1000, -1000, 4217, 2884, -1000, -1000, 23186, - -1000, 11023, 11023, -1000, -1000, 42076, 74543, -1000, 138, -1000, - 217, 4738, 2243, 2234, -1000, 3221, 4064, 4063, -1000, -1000, - -1000, -1000, -1000, -1000, -265, -1000, -1000, 74543, -1000, 74543, - 74543, 1923, -1000, 2229, 1935, 4423, 74543, 1335, -1000, -1000, - 4214, 74543, -1000, 3858, -1000, 4775, -265, 4774, 13300, -1000, - -1000, 66237, -1000, 65482, 2803, -1000, 20904, 3095, 281, -1000, - 424, -314, 264, 3019, 262, 3162, -1000, -1000, 4062, 4061, - 4058, 2691, -1000, 2687, 4056, -1000, 2684, 2683, 3456, -1000, - -316, 291, 4738, 4585, 3856, 2228, -1000, 4585, -1000, -328, - -120, -1000, 27728, 82090, 74543, 3854, 3141, 4626, 3518, -287, - 16341, 64727, 16341, 1582, 2397, 438, -1000, -1000, -1000, 74543, - 2224, 813, 3867, -1000, 2675, -1000, -1000, -1000, -1000, 3455, - -1000, -1000, 2742, 74543, -1000, -1000, 2195, 74543, 50381, -1000, - -1000, -1000, -1000, 74543, -1000, 774, -1000, 57932, -1000, 2742, - -1000, -1000, 4752, -1000, -1000, 16341, 16341, 314, 4752, 2742, - 2742, -1000, 2757, -1000, 74543, -1000, -393, 63972, 2103, -1000, - 1333, 2392, 2391, -1000, 57932, 618, 57932, -1000, -1000, 4723, - -1000, 74543, 4592, -1000, -1000, -1000, 3786, 2883, -391, 74543, + 1857, -1000, 4605, 4099, 3273, 1857, 4436, -168, -1000, 28596, + 82481, 74894, 2027, 2027, -1000, 4225, 2767, -1000, 67304, 60472, + 60472, 60472, 60472, 60472, 60472, 60472, 60472, -1000, 4500, 4483, + 4224, -1000, 4488, 4460, 4458, 861, 4499, 4485, 4444, 4216, + -1000, 58954, -1000, -1000, -1000, 2679, 2749, -1000, 684, 3665, + 1722, 16384, 4690, 4575, 4649, 4216, 2286, -1000, -1000, -1000, + -1000, 4759, 1031, 2214, 1300, 1300, 1688, 4758, 26307, -1000, + 2796, 2164, 1446, 4581, 720, -1000, 2796, -77, 1310, 2796, + 2796, 2796, 2796, 2796, 2796, 2796, 2796, 1150, 1148, 2796, + 2796, 2796, 2796, 2796, 2796, 2796, 2796, 2796, 2796, 2796, + 1833, 2796, 2796, 2796, 2796, 2796, -1000, 2796, 4223, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 1166, 1062, -1000, -1000, + 427, 734, 1441, 269, 265, 634, 4689, 759, -1000, 784, + 2189, 1151, 4688, 811, 74894, 74894, 513, 2166, 2724, 239, + 217, -1000, -1000, 2282, 11038, 2282, 11038, 3507, -1000, -1000, + 1433, -1000, -1000, 2040, -1000, 74894, 74894, -1000, -1000, 4222, + 2941, -1000, -1000, 23265, -1000, 11038, 11038, -1000, -1000, 42255, + 74894, -1000, 208, -1000, 235, 4756, 2277, 2272, -1000, 3277, + 4068, 4067, -1000, -1000, -1000, -1000, -1000, -1000, -296, -1000, + -1000, 74894, -1000, 74894, 74894, 2016, -1000, 2268, 2040, 4428, + 74894, 1322, -1000, -1000, 4218, 74894, -1000, 3891, -1000, 4796, + -296, 4795, 13327, -1000, -1000, 66544, -1000, 65785, 2966, -1000, + 20971, 3253, 263, -1000, 372, -335, 262, 3013, 261, 3121, + -1000, -1000, 4065, 4062, 4061, 2744, -1000, 2738, 4060, -1000, + 2733, 2712, 3504, -1000, -350, 286, 4756, 4604, 3890, 2267, + -1000, 4604, -1000, -360, -168, -1000, 27831, 82481, 74894, 3889, + 3138, 4647, 3563, -317, 16384, 65026, 16384, 1708, 2444, 521, + -1000, -1000, -1000, 74894, 2266, 2245, 3887, -1000, 2687, -1000, + -1000, -1000, -1000, 3502, -1000, -1000, 2658, 74894, -1000, -1000, + 1904, 74894, 50604, -1000, -1000, -1000, -1000, 74894, -1000, 734, + -1000, 58195, -1000, 2658, -1000, -1000, 4770, -1000, -1000, 16384, + 16384, 287, 4770, 2658, 2658, -1000, 2828, -1000, 74894, -1000, + -400, 64267, 2188, -1000, 1408, 2439, 2425, -1000, 58195, 713, + 58195, -1000, -1000, 4740, -1000, 74894, 4615, -1000, -1000, -1000, + 3830, 2930, -398, 74894, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 2685, -1000, 1572, 1572, 6047, 5794, + -1000, 1572, 1572, 6047, 5679, 20199, -1000, 20199, -1000, 20199, + -1000, -1000, -1000, -1000, 3875, -1000, 2743, -1000, 16384, 3240, + 405, 16384, 405, 2945, 36183, 46050, -54, 4612, 3847, 74894, + 16384, -1000, -1000, 16384, 16384, 20199, -1000, 3843, -1000, -1000, + -1000, -1000, 16384, 16384, 3332, -1000, 74894, -1000, -1000, -1000, + -1000, 36183, -1000, 20199, -1000, -1000, -1000, -1000, 16384, 16384, + 16384, 2151, -366, -366, 2151, 3838, 2683, 431, 431, -366, + 3827, 3822, 3803, 2682, 431, 3780, 3772, 3768, 3761, 3752, + 3736, 3718, 3714, 4767, 3701, 3695, 2680, 3686, 2375, -1000, + 63508, -1000, -1000, -1000, 431, -1000, -377, 16384, -377, 16384, + -377, -377, 16384, 3167, 17910, 4756, 4715, 14090, -1000, 4604, + 4604, 707, -1000, -1000, 4217, 1306, 2249, 3501, 3881, 197, + -1000, 2925, -1000, 807, -1000, 74894, 4794, -1000, 2424, 3878, + 62749, -1000, 1780, 74894, -1000, -1000, 4793, 4790, -1000, -1000, + 74894, 74894, 74894, -1000, -1000, -1000, 1738, -1000, 3877, -1000, + -1000, 662, 504, 3370, 4825, 4823, 2980, 3876, 676, 1888, + 24783, 74894, 4216, 4216, 369, 2796, 925, 1106, 58195, 1173, + -1000, 61990, 3451, 2924, 4427, 1870, 4594, 74894, 61231, 2306, + 1373, 4214, 949, 652, -1000, 4605, 4213, 74894, 4605, -1000, + -360, -1000, 4592, 1995, -1000, 4210, -1000, 2668, 4535, -1000, + 2423, 2246, -1000, 2918, 2667, 2662, 2917, -360, 325, 6208, + -1000, 74894, 74894, 2330, -1000, 2416, 466, 4399, 4399, 4399, + -1000, 4399, 4399, -1000, -1000, -1000, -1000, 4498, 3866, -1000, + 4497, -1000, 4484, -1000, 4481, -1000, -1000, -1000, -1000, 4457, + -1000, -1000, -1000, 30114, -1000, 60472, -1000, 1722, -1000, 4711, + 1674, 1674, 1674, 4059, 41496, 40737, -1000, -1000, 949, 652, + 4646, 5837, 1113, 74894, 74894, -1000, -1000, 74894, 74894, 74894, + 4130, -1000, 74894, -1000, -1000, 1355, -1000, 1674, 1674, 1333, + 74894, 3075, 1674, 3072, 4208, -1000, -1000, 74894, 74894, 74894, + 74894, -1000, -1000, 74894, 59713, -1000, 74894, 74894, -1000, 74894, + 3071, 74894, 3070, 4597, -1000, 2796, 2796, 1691, -1000, -1000, + 1088, -1000, 59713, 3498, 3497, 3496, 3492, 3490, 3864, 3858, + 3857, 2796, 2796, 3483, 3856, 58954, 3854, 1941, 3471, 3465, + 3461, 3417, 3853, 1666, -1000, 3850, 3357, 3339, 3319, 74894, + 4204, 3765, -1000, -1000, 3370, 3848, 4203, 3458, 3845, 1593, + 734, 3839, 4426, 369, 2796, 757, 74894, 2916, 2912, 1106, + 994, 994, 995, 128, 31632, -1000, -1000, -1000, 74894, 74894, + 11038, -1000, -1000, 244, 221, -1000, -1000, -1000, -1000, 58195, + 3836, 968, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 4604, + 16384, 4579, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 74894, 1322, -1000, -1000, -1000, 24783, -1000, -1000, 74894, -1000, + 4770, -1000, 30114, -1000, -1000, -1000, 2414, -1000, 2745, -383, + 20971, 2684, 2660, -1000, 16384, 20971, 16384, -231, 742, -233, + -1000, -1000, -1000, -1000, 3835, -1000, -1000, -1000, 3457, -1000, + 3444, -1000, 222, 476, 510, 4604, -1000, 543, 3636, -1000, + -1000, 13327, 1995, 2653, 4532, 2246, 2643, -1000, -1000, -1000, + -1000, 4627, -1000, -1000, -1000, -1000, -1000, 245, -407, -408, + 241, 3834, 74894, 3442, -1000, -1000, -1000, -1000, 4770, 2658, + 4770, 50604, 2658, 2873, -1000, -1000, -1000, -1000, 2040, -1000, + 4770, -1000, 3121, 3121, -1000, -1000, -400, 4770, 4770, 2658, + -1000, -1000, 4787, 58195, 734, 2612, 57436, -1000, 705, 2339, + 1018, 3832, -1000, 1535, 191, 3831, 3830, -1000, -1000, -1000, + -1000, 20199, -1000, -1000, 20199, 2836, 2773, -1000, -1000, -1000, + 3121, 16384, 4057, 3193, 4056, 4055, -1000, -1000, 4188, 4188, + -1000, 4185, 4186, 4185, 2585, 2585, 4053, -1000, 4198, -1000, + 4612, -1000, 2642, 3441, 3662, 5576, 431, 3658, 3634, 16384, + 2411, 4052, 5457, 2169, 1917, 3603, 77, 431, 4766, 431, + -114, 431, 431, -1000, -1000, -1000, 431, 431, 431, 431, + 431, -1000, 431, 431, 431, 431, 431, 431, 431, 431, + 4196, 431, 431, 431, 431, 16384, -1000, 81722, -1000, 431, + 4576, 2350, 431, 2337, 431, 431, 3598, 19, -263, -41, + -264, 4604, 4756, -1000, -1000, -1000, 16384, 418, 4051, 7167, + 2236, 1002, 1002, 3830, 3829, 74894, 3826, -290, 74894, -1000, + -409, -410, -291, 74894, 3823, 74894, 74894, 281, 2940, 3097, + -1000, 3820, -1000, -1000, 56677, 74894, 74894, 75653, 1056, 74894, + 74894, 3819, -1000, -1000, 4193, -1000, 4192, -82, 4191, -26, + 3818, 4049, 2232, -1000, -1000, 74894, -1000, -1000, -1000, 4039, + 2230, -1000, -1000, -1000, 652, 4189, 4188, 4188, 1752, 4185, + -1000, -1000, -1000, 4185, -1000, -1000, -1000, -1000, 4188, 4188, + 4188, 4188, 4188, 4188, 4187, -1000, -1000, 4186, 4186, 4186, + 4185, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 1875, 4182, 4183, 4183, 4182, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 2670, -1000, 1475, 1475, 5417, 4909, -1000, 1475, 1475, 5417, - 4712, 20136, -1000, 20136, -1000, 20136, -1000, -1000, -1000, -1000, - 3869, -1000, 2717, -1000, 16341, 3064, 422, 16341, 422, 2450, - 36036, 45851, -15, 4590, 3837, 74543, 16341, -1000, -1000, 16341, - 16341, 20136, -1000, 3802, -1000, -1000, -1000, -1000, 16341, 16341, - 3201, -1000, 74543, -1000, -1000, -1000, -1000, 36036, -1000, 20136, - -1000, -1000, -1000, -1000, 16341, 16341, 16341, 2058, -335, -335, - 2058, 3795, 2660, 393, 393, -335, 3763, 3739, 3732, 2658, - 393, 3728, 3721, 3716, 3711, 3704, 3646, 3631, 3613, 4750, - 3589, 3585, 2656, 3579, 2415, -1000, 63217, -1000, -1000, -1000, - 393, -1000, -354, 16341, -354, 16341, -354, -354, 16341, 3104, - 17859, 4738, 4699, 14059, -1000, 4585, 4585, 598, -1000, -1000, - 4213, 1257, 2212, 3452, 3853, 180, -1000, 2877, -1000, 728, - -1000, 74543, 4771, -1000, 2384, 3852, 62462, -1000, 1650, 74543, - -1000, -1000, 4770, 4769, -1000, -1000, 74543, 74543, 74543, -1000, - -1000, -1000, 1611, -1000, 3850, -1000, -1000, 461, 431, 3313, - 4808, 4807, 2946, 3849, 579, 1976, 24696, 74543, 4212, 4212, - 389, 2734, 889, 1012, 57932, 1140, -1000, 61707, 3255, 2875, - 4419, 1686, 4575, 74543, 60952, 987, 1338, 4209, 904, 5648, - -1000, 4591, 4202, 74543, 4591, -1000, -328, -1000, 4583, 1886, - -1000, 4200, -1000, 2652, 4515, -1000, 2372, 2183, -1000, 2874, - 2649, 2647, 2873, -328, 353, 6178, -1000, 74543, 74543, 1926, - -1000, 2354, 323, 4396, 4396, 4396, -1000, 4396, 4396, -1000, - -1000, -1000, -1000, 4485, 3848, -1000, 4482, -1000, 4477, -1000, - 4461, -1000, -1000, -1000, -1000, 4451, -1000, -1000, -1000, 29999, - -1000, 60197, -1000, 1512, -1000, 4695, 1549, 1549, 1549, 4055, - 41321, 40566, -1000, -1000, 904, 5648, 4621, 5747, 1078, 74543, - 74543, -1000, -1000, 74543, 74543, 74543, 4107, -1000, 74543, -1000, - -1000, 1514, -1000, 1549, 1549, 1296, 74543, 3057, 1549, 3054, - 4199, -1000, -1000, 74543, 74543, 74543, 74543, -1000, -1000, 74543, - 59442, -1000, 74543, 74543, -1000, 74543, 3053, 74543, 3048, 4544, - -1000, 2734, 2734, 1510, -1000, -1000, 968, -1000, 59442, 3446, - 3445, 3443, 3440, 3438, 3847, 3830, 3828, 2734, 2734, 3436, - 3825, 58687, 3821, 1958, 3434, 3417, 3415, 3318, 3818, 1609, - -1000, 3815, 3300, 3291, 3287, 74543, 4198, 3717, -1000, -1000, - 3313, 3814, 4196, 3413, 3805, 1440, 774, 3801, 4416, 389, - 2734, 654, 74543, 2868, 2865, 1012, 935, 935, 966, 127, - 31509, -1000, -1000, -1000, 74543, 74543, 11023, -1000, -1000, 224, - 222, -1000, -1000, -1000, -1000, 57932, 3800, 914, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 4585, 16341, 4556, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 74543, 1335, -1000, -1000, - -1000, 24696, -1000, -1000, 74543, -1000, 4752, -1000, 29999, -1000, - -1000, -1000, 2343, -1000, 2953, -367, 20904, 2703, 2603, -1000, - 16341, 20904, 16341, -179, 640, -181, -1000, -1000, -1000, -1000, - 3796, -1000, -1000, -1000, 3409, -1000, 3407, -1000, 172, 420, - 442, 4585, -1000, 472, 3524, -1000, -1000, 13300, 1886, 2643, - 4512, 2183, 2640, -1000, -1000, -1000, -1000, 4685, -1000, -1000, - -1000, -1000, -1000, 245, -401, -403, 241, 3794, 74543, 3404, - -1000, -1000, -1000, -1000, 4752, 2742, 4752, 50381, 2742, 2701, - -1000, -1000, -1000, -1000, 1935, -1000, 4752, -1000, 3162, 3162, - -1000, -1000, -393, 4752, 4752, 2742, -1000, -1000, 4768, 57932, - 774, 2529, 57177, -1000, 596, 2288, 942, 3791, -1000, 1404, - 179, 3789, 3786, -1000, -1000, -1000, -1000, 20136, -1000, -1000, - 20136, 2739, 2709, -1000, -1000, -1000, 3162, 16341, 4054, 3157, - 4053, 4049, -1000, -1000, 4181, 4181, -1000, 4177, 4178, 4177, - 2538, 2538, 4048, -1000, 4192, -1000, 4590, -1000, 2638, 3106, - 3567, 5349, 393, 3548, 3529, 16341, 2339, 4047, 4102, 1995, - 1937, 3522, 112, 393, 4748, 393, -75, 393, 393, -1000, - -1000, -1000, 393, 393, 393, 393, 393, -1000, 393, 393, - 393, 393, 393, 393, 393, 393, 4191, 393, 393, 393, - 393, 16341, -1000, 81335, -1000, 393, 4555, 2301, 393, 2238, - 393, 393, 3517, 1, -210, 0, -212, 4585, 4738, -1000, - -1000, -1000, 16341, 458, 4037, 6695, 2180, 989, 989, 3786, - 3781, 74543, 3777, -252, 74543, -1000, -404, -408, -256, 74543, - 3776, 74543, 74543, 277, 2810, 3042, -1000, 3774, -1000, -1000, - 56422, 74543, 74543, 75298, 1040, 74543, 74543, 3773, -1000, -1000, - 4189, -1000, 4186, -47, 4185, 64, 3772, 4027, 2169, -1000, - -1000, 74543, -1000, -1000, -1000, 4023, 2149, -1000, -1000, -1000, - 5648, 4184, 4181, 4181, 1710, 4177, -1000, -1000, -1000, 4177, - -1000, -1000, -1000, -1000, 4181, 4181, 4181, 4181, 4181, 4181, - 4180, -1000, -1000, 4178, 4178, 4178, 4177, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 1872, 4175, 4176, 4176, - 4175, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 4644, 4643, 3553, -1000, -1000, -1000, + 39978, 74894, 994, -1000, -1000, -1000, 1188, 767, 3440, 997, + -1000, 74894, 956, 799, 4554, 2899, 3814, 74894, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 4594, -1000, + 1643, -400, 74894, 924, 21736, -1000, 1797, 4642, 74894, -1000, + 74894, 55917, -1000, -167, -1000, -1000, 24024, -1000, 2796, 24024, + 912, 2923, -1000, 16384, 2620, 4605, -1000, 3067, -168, 14090, + 2073, 74894, -168, 74894, 74894, 14090, -1000, 74894, -1000, 74894, + 16384, -1000, -1000, -360, 4038, -1000, 1288, 2117, 219, 30114, + 74894, -1000, 52881, 16384, -1000, -1000, 16384, 4181, -1000, -1000, + -1000, -371, -1000, 4037, -1000, -1000, -1000, -1000, -1000, 4461, + -1000, 384, -1000, 4179, 4556, -1000, -1000, -1000, -1000, 2224, + 51363, -1000, 2898, -1000, -1000, 2197, 49845, -1000, 2896, -1000, + -1000, 912, -1000, 1857, -1000, 2308, 1187, 27066, 1022, 776, + 761, -1000, 1168, -1000, 903, 1819, 884, 1304, 1304, -1000, + 1244, 4566, 652, -1000, 74894, -1000, 74894, 74894, -1000, 74894, + 74894, 1333, 16384, 4566, 74894, 1406, -1000, 2195, -1000, 4612, + -1000, -1000, 2190, -1000, -1000, -1000, -1000, 74894, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 36183, 36183, 4684, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 4620, 4619, 3509, -1000, -1000, -1000, 39811, 74543, 935, -1000, - -1000, -1000, 1163, 823, 3395, 920, -1000, 74543, 883, 721, - 4533, 2848, 3770, 74543, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 4575, -1000, 1820, -393, 74543, 887, - 21665, -1000, 2225, 4618, 74543, -1000, 74543, 55666, -1000, -117, - -1000, -1000, 23941, -1000, 2734, 23941, 880, 2798, -1000, 16341, - 2631, 4591, -1000, 3030, -120, 14059, 2277, 74543, -120, 74543, - 74543, 14059, -1000, 74543, -1000, 74543, 16341, -1000, -1000, -328, - 4022, -1000, 1241, 2134, 200, 29999, 74543, -1000, 52646, 16341, - -1000, -1000, 16341, 4171, -1000, -1000, -1000, -341, -1000, 4021, - -1000, -1000, -1000, -1000, -1000, 4457, -1000, 276, -1000, 4155, - 4545, -1000, -1000, -1000, -1000, 2146, 51136, -1000, 2842, -1000, - -1000, 2145, 49626, -1000, 2839, -1000, -1000, 880, -1000, 1871, - -1000, 2101, 1299, 26967, 1007, 778, 742, -1000, 1099, -1000, - 903, 1654, 865, 1384, 1384, -1000, 1226, 4551, 5648, -1000, - 74543, -1000, 74543, 74543, -1000, 74543, 74543, 1296, 16341, 4551, - 74543, 1332, -1000, 2141, -1000, 4590, -1000, -1000, 2131, -1000, - -1000, -1000, -1000, 74543, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 36036, 36036, 4649, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 3769, 3768, + -1000, -1000, 3813, 3807, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 74543, - 2630, -1000, 2833, 3766, 64, 10264, -1000, -1000, 1328, -1000, - 4415, 1403, 3509, 39811, 2829, 2762, 3765, 3762, 935, -1000, - 3760, 3755, -1000, 3255, 2827, 1401, 74543, -1000, 1928, 74543, - 74543, -1000, 2123, -1000, 2819, 2147, -1000, -1000, -1000, -1000, - 2103, 4018, -1000, -1000, 4580, -1000, -1000, 4560, -1000, -1000, - 4017, 885, 4747, 2075, 54911, -1000, -367, 2607, -1000, 3006, - 260, 3001, 74543, -1000, -1000, -1000, 4016, 4015, -1000, -131, - 435, 4737, 4736, 4580, -163, 3749, -1000, 1869, 2272, -120, - -1000, 1688, -1000, -1000, -1000, -1000, -410, -1000, -1000, -1000, - 4752, -1000, 2742, 4752, 4752, -280, -1000, -1000, -1000, -1000, - 4752, 774, -1000, 2119, -1000, -1000, -1000, -1000, -1000, -1000, - 498, -1000, 74543, -1000, 2067, 169, -1000, -1000, -1000, 3162, - -1000, 422, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 39056, -1000, -1000, -1000, 16341, -1000, -1000, -1000, - -1000, -1000, 3463, 74543, -1000, -1000, 16341, 16341, -1000, 4013, - 3742, -1000, 4154, -1000, 4012, 3737, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 74894, 2614, -1000, 2895, 3801, -26, 10275, + -1000, -1000, 1403, -1000, 4420, 1495, 3553, 39978, 2890, 2724, + 3800, 3799, 994, -1000, 3795, 3791, -1000, 3451, 2889, 1477, + 74894, -1000, 2035, 74894, 74894, -1000, 2114, -1000, 2878, 2161, + -1000, -1000, -1000, -1000, 2188, 4032, -1000, -1000, 4591, -1000, + -1000, 4570, -1000, -1000, 4029, 920, 4765, 2156, 55158, -1000, + -383, 2686, -1000, 3201, 257, 2934, 74894, -1000, -1000, -1000, + 4028, 4027, -1000, -175, 506, 4755, 4753, 4591, -190, 3787, + -1000, 1971, 1886, -168, -1000, 1863, -1000, -1000, -1000, -1000, + -426, -1000, -1000, -1000, 4770, -1000, 2658, 4770, 4770, -308, + -1000, -1000, -1000, -1000, 4770, 734, -1000, 2050, -1000, -1000, + -1000, -1000, -1000, -1000, 570, -1000, 74894, -1000, 2118, 190, + -1000, -1000, -1000, 3121, -1000, 405, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 39219, -1000, -1000, -1000, + 16384, -1000, -1000, -1000, -1000, -1000, 3549, 74894, -1000, -1000, + 16384, 16384, -1000, 4026, 3781, -1000, 4177, -1000, 4025, 3779, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 4818, -1000, -1000, -1000, -1000, 3396, 4011, 1232, -1000, - -1000, -1000, -354, 16341, -1000, -354, 16341, -1000, -1000, 4767, - 2621, 4009, 4008, 2610, 4003, 4001, 4580, 4585, 1877, 3999, - 2000, -1000, -1000, -1000, -1000, -1000, -1000, 3996, 6695, 1537, - 3730, 1537, -1000, -1000, -1000, -1000, 74543, -1000, -1000, -1000, - 74543, 4765, 38301, 1321, -393, 918, 4153, -1000, 940, 2810, - 1648, 4152, 3724, -1000, 74543, 4763, 74543, 3313, 1031, 3313, - 1119, 74543, -265, 51136, 49626, 61, 3390, 10264, -1000, 3720, - -1000, -18, 1976, 5648, 1386, 24696, 4571, 2225, 2225, -1000, - 3719, 511, -1000, -1000, -1000, 814, -1000, 3389, -1000, -1000, - 3269, 2342, 543, -1000, -1000, -1000, -1000, -1000, -1000, 3397, - 74543, 54156, 3397, 3450, 2816, -396, -1000, 4151, -1000, 2734, - 2734, 2734, 1321, 884, 74543, 3993, 1980, -1000, -1000, -1000, - -1000, -1000, 2225, -1000, 4540, 74543, 2004, 3991, -269, 3990, - 1268, 2765, 2749, -1000, 3386, 2604, 4511, 1599, -1000, 3989, - 1943, -120, -1000, -1000, 1886, 2338, -1000, -1000, -1000, 2815, - 3162, -1000, -1000, 53401, 29999, 52646, 2018, -1000, 2326, -1000, - 2932, 3162, 74543, -1000, 2323, -1000, -1000, -1000, 51891, -1000, - 4735, 4734, 51136, 2602, 50381, 49626, 2600, 48871, 1268, -1000, - 1000, 3368, 20136, 4150, 20136, 4149, 1013, 4147, -1000, -1000, - -1000, -1000, -1000, 1181, 4570, -1000, 759, -1000, -1000, -1000, - -1000, 1054, 1048, -1000, 2596, -1000, 74543, -1000, -1000, 74543, - 6649, 4146, -1000, 4145, 4144, 4403, 988, 4143, 4142, 74543, - 3391, -1000, 4551, 74543, 74543, -1000, 74543, -1000, 2416, -1000, - 36036, -1000, -1000, 2594, -1000, 3717, 3715, -1000, -1000, 3985, - 3162, -1000, 2341, 774, 1390, 74543, -1000, 511, 3714, 11023, - -1000, -1000, -1000, -1000, -1000, 4533, 3713, 3397, 74543, -1000, - 74543, 1928, 1928, 4818, 29999, 74543, 14059, -328, -1000, -1000, - 4554, 2563, -1000, -1000, -1000, 74543, 4744, 4733, -1000, 1293, - 20904, -183, 637, -1000, -1000, -1000, -148, 3712, -1000, -1000, - 4732, 3710, 3532, -1000, 291, 3709, -1000, -120, -1000, 1886, - 3707, -1000, -1000, -1000, 4752, -1000, -1000, 74543, -1000, 1935, - -1000, -1000, 1808, 1122, -1000, 3984, 2800, -1000, -1000, -1000, - 3370, -1000, -1000, 3358, 3334, -335, -1000, 4818, 393, -1000, - 3983, 393, -1000, 4818, -1000, 4730, 393, 3330, 393, 3278, - -354, 4552, -1000, 3705, -1000, -1000, -1000, 3701, -1000, -1000, - -1000, 4580, -1000, 16341, -1000, 3980, -1000, 3696, -1000, -1000, - 3694, 3693, -262, -1000, -1000, 720, 1321, -1000, 562, 74543, - 1006, -1000, 48116, 10264, -397, 871, 74543, 4762, 3692, 3313, - 3691, 3313, 74543, 1028, -1000, 2583, 2582, 4617, 3672, -1000, - 3972, -1000, 3667, 3666, -1000, -1000, 5648, -1000, 2400, 4809, - 4809, -1000, -1000, 4721, -1000, 2279, 716, -1000, -1000, 3228, - 973, -1000, -1000, 3663, 961, -1000, 1928, -1000, -1000, 2814, - 3173, 3588, 45851, 36036, 36791, 3662, -1000, 74543, -1000, 6273, - 23941, -1000, 1321, 4677, 856, 4699, 758, 4808, 6379, 1753, - 2728, -1000, 3367, -1000, 3366, -1000, -1000, 4141, 74543, -1000, - -1000, 1886, 74543, 16341, 4752, 2018, 197, -328, -1000, 2518, - 312, -1000, 37546, 2571, -1000, 16341, 2546, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1753, - 4107, 4729, -1000, 3784, 74543, 3625, 74543, 4140, 2811, 20136, - 7406, 7406, 7406, 7406, 7406, 20136, -1000, -1000, -1000, 2809, - -1000, -1000, -1000, 1226, 4510, -1000, -1000, 6649, -1000, -1000, - 3072, 3065, 20136, -1000, -1000, 3659, 3658, 3651, 36791, 1389, - 2801, 2799, 1456, 4139, -1000, 1071, 4789, 3361, -1000, -1000, - -1000, 1500, -170, 4138, 3008, 3000, -1000, 74543, -1000, 45851, - 45851, 45851, 1809, 1809, 45851, 45851, 4136, 1384, -1000, -1000, - -1000, -1000, 2734, 2394, -1000, -1000, -1000, -1000, -1000, 74543, - 2312, -1000, -1000, -1000, 3450, -1000, -1000, 1923, -1000, 4710, - 2018, -1000, -1000, -1000, -1000, -1000, 4504, -1000, -343, 16341, - 17100, -1000, -367, 74543, 74543, -150, 3359, -1000, 3640, 432, - -1000, -1000, 420, -1000, 1886, -1000, -1000, 2742, -152, 342, - 36036, 2797, -1000, 3971, 526, -25, -1000, -1000, -1000, 393, - 3966, -1000, 393, -1000, 523, 16341, -1000, -354, -1000, -354, - 393, -1000, 3965, 3953, -1000, 3256, -1000, -1000, -1000, -1000, - 74543, 74543, -1000, 74543, 3639, 3356, -1000, -1000, 2534, -1000, - -1000, -1000, 2984, 2980, 2530, 3951, 3559, 74543, 852, 74543, - -265, 3632, -265, 3630, 1027, 3313, -1000, -1000, -200, -1000, - -1000, -1000, -1000, -19, -1000, -1000, -1000, 652, -1000, 977, - 3525, 3354, -1000, -1000, 715, -1000, -1000, -1000, 3397, 3629, - -1000, -1000, 168, -1000, 2792, 2515, -1000, -1000, -1000, 814, - 1224, -1000, 2225, 4616, 6003, -1000, 1910, -1000, -1000, -1000, - 74543, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1808, 2734, - -1000, 1224, 1117, 2824, -1000, 3350, -1000, -1000, 16341, 1831, - -1000, 3162, 4818, -328, -1000, 13300, -1000, 2974, 74543, 74543, - -1000, -1000, -1000, 47361, 1112, -1000, 1009, -1000, 2511, -1000, - 2506, 46606, 3347, 3380, -1000, 2734, 2734, 3624, 3621, 804, - -1000, -1000, 2734, 2734, 2734, 2734, 2734, 2734, 4130, 3615, - 3606, 2734, 2734, 2734, 2734, 2734, 2734, 2790, -1000, -1000, - -1000, 2789, 2734, 2734, 2734, 5417, 7406, 3133, -1000, 5130, - 1382, -1000, -1000, -1000, 5417, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 3605, 3602, -1000, -1000, -1000, -1000, -1000, - 3320, 4129, 325, -1000, 4647, 4615, 16341, -1000, -1000, 4127, - 2504, 2502, 2481, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 2463, 2438, 45851, -1000, - -1000, 36036, 2734, 2201, 74543, -1000, -328, -328, 4500, -1000, - 74543, 3162, 1988, 363, 4126, 4125, -1000, -1000, -1000, 4124, - -1000, -1000, 4727, -131, 4752, -157, 3599, 419, 470, -1000, - 3597, -1000, -20, 4499, 4498, -30, -1000, -1000, -1000, -1000, - -1000, 1745, -1000, -1000, -1000, 1877, 393, 393, -1000, -1000, - -1000, -1000, 3595, -1000, -1000, -1000, -1000, -1000, 74543, 3593, - -1000, -1000, 160, -1000, 2761, -1000, 74543, 848, -1000, -265, - -1000, -265, 3313, 3590, -1000, 74543, 1058, -1000, -1000, -1000, - -1000, 484, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 3588, - 3571, -1000, -1000, 992, 4726, -1000, 2225, 6379, -1000, 2734, - 814, -1000, 434, 992, -1000, 913, -1000, 2578, -1000, 3309, - -1000, 2432, 4710, -1000, 1869, 2948, 16341, 2974, 2974, -1000, - -1000, -1000, 912, -1000, 997, -1000, -1000, -1000, 2427, -1000, - -1000, 3304, 3303, -1000, -1000, 74543, 3295, 3288, 3285, 3283, - 3282, 3253, 74543, -1000, -1000, 3249, 3234, 3227, 3224, 3219, - 3185, 3081, 3077, 3181, 3151, 3129, -1000, -1000, -1000, 5130, - 1003, -1000, -1000, 1218, 4123, -1000, -1000, 3943, 16341, 4122, - 2734, 4121, 3245, -11, 45851, 4400, -1000, 4398, 3876, 3634, - 2403, -1000, 36036, 74543, -1000, -1000, -1000, -1000, 1863, -1000, - 4605, -1000, -304, 4120, 16341, 16341, 74543, 3532, -148, -1000, - -1000, 3568, -1000, 1300, 433, 470, -1000, 4725, 414, 4724, - 4720, 1856, 4496, -1000, -1000, -1000, -1000, 1525, -125, 390, - 386, 373, 346, -1000, -1000, -1000, -1000, -1000, -1000, 3016, - 3016, -265, 3559, 3556, -1000, 74543, -1000, -1000, 3552, -265, - 894, -1000, 592, -1000, -1000, -1000, 7406, -1000, 4718, 1078, - -1000, -1000, 36036, -1000, 4807, 4805, 4804, 4797, -1000, -1000, - -1000, -1000, -1000, 3128, -1000, -1000, -328, 4761, 3162, 2924, - 2841, -1000, -1000, 3096, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 2388, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 4830, -1000, -1000, -1000, -1000, + 3531, 4024, 1273, -1000, -1000, -1000, -377, 16384, -1000, -377, + 16384, -1000, -1000, 4786, 2609, 4019, 4017, 2606, 4016, 4015, + 4591, 4604, 1977, 4014, 2101, -1000, -1000, -1000, -1000, -1000, + -1000, 4010, 7167, 1680, 3778, 1680, -1000, -1000, -1000, -1000, + 74894, -1000, -1000, -1000, 74894, 4785, 38460, 1393, -400, 952, + 4176, -1000, 957, 2940, 1798, 4174, 3770, -1000, 74894, 4779, + 74894, 3370, 1047, 3370, 1145, 74894, -296, 51363, 49845, -29, + 3438, 10275, -1000, 3769, -1000, -57, 1888, 652, 1574, 24783, + 4589, 1797, 1797, -1000, 3766, 580, -1000, -1000, -1000, 885, + -1000, 3434, -1000, -1000, 3308, 2407, 597, -1000, -1000, -1000, + -1000, -1000, -1000, 3447, 74894, 54399, 3447, 3550, 2877, -401, + -1000, 4173, -1000, 2796, 2796, 2796, 1393, 917, 74894, 4003, + 2077, -1000, -1000, -1000, -1000, -1000, 1797, -1000, 4558, 74894, + 2140, 3995, -300, 3994, 1222, 2860, 2841, -1000, 3427, 2603, + 4529, 1638, -1000, 3993, 2048, -168, -1000, -1000, 1995, 2410, + -1000, -1000, -1000, 2875, 3121, -1000, -1000, 53640, 30114, 52881, + 2141, -1000, 2409, -1000, 3150, 3121, 74894, -1000, 2379, -1000, + -1000, -1000, 52122, -1000, 4752, 4750, 51363, 2575, 50604, 49845, + 2573, 49086, 1222, -1000, 1013, 3425, 20199, 4171, 20199, 4170, + 1028, 4169, -1000, -1000, -1000, -1000, -1000, 1226, 4585, -1000, + 848, -1000, -1000, -1000, -1000, 1095, 1082, -1000, 2572, -1000, + 74894, -1000, -1000, 74894, 7115, 4168, -1000, 4167, 4165, 4406, + 999, 4164, 4163, 74894, 3526, -1000, 4566, 74894, 74894, -1000, + 74894, -1000, 2454, -1000, 36183, -1000, -1000, 2571, -1000, 3765, + 3764, -1000, -1000, 3987, 3121, -1000, 2652, 734, 1443, 74894, + -1000, 580, 3759, 11038, -1000, -1000, -1000, -1000, -1000, 4554, + 3754, 3447, 74894, -1000, 74894, 2035, 2035, 4830, 30114, 74894, + 14090, -360, -1000, -1000, 4569, 2646, -1000, -1000, -1000, 74894, + 4762, 4749, -1000, 1331, 20971, -234, 740, -1000, -1000, -1000, + -179, 3753, -1000, -1000, 4747, 3750, 3581, -1000, 286, 3749, + -1000, -168, -1000, 1995, 3746, -1000, -1000, -1000, 4770, -1000, + -1000, 74894, -1000, 2040, -1000, -1000, 1835, 1152, -1000, 3985, + 2849, -1000, -1000, -1000, 3514, -1000, -1000, 3510, 3491, -366, + -1000, 4830, 431, -1000, 3980, 431, -1000, 4830, -1000, 4746, + 431, 3479, 431, 3474, -377, 4573, -1000, 3745, -1000, -1000, + -1000, 3744, -1000, -1000, -1000, 4591, -1000, 16384, -1000, 3976, + -1000, 3741, -1000, -1000, 3734, 3733, -292, -1000, -1000, 770, + 1393, -1000, 545, 74894, 972, -1000, 48327, 10275, -402, 916, + 74894, 4772, 3732, 3370, 3724, 3370, 74894, 1046, -1000, 2559, + 2558, 4641, 3721, -1000, 3974, -1000, 3716, 3715, -1000, -1000, + 652, -1000, 2740, 4826, 4826, -1000, -1000, 4739, -1000, 2351, + 781, -1000, -1000, 3217, 1060, -1000, -1000, 3703, 1053, -1000, + 2035, -1000, -1000, 2871, 3153, 3621, 46050, 36183, 36942, 3700, + -1000, 74894, -1000, 6431, 24024, -1000, 1393, 4698, 914, 4715, + 736, 4825, 6632, 1846, 2791, -1000, 3419, -1000, 3415, -1000, + -1000, 4162, 74894, -1000, -1000, 1995, 74894, 16384, 4770, 2141, + 199, -360, -1000, 2598, 284, -1000, 37701, 2554, -1000, 16384, + 2519, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 1846, 4130, 4745, -1000, 5210, 74894, 4708, + 74894, 4161, 2869, 20199, 7535, 7535, 7535, 7535, 7535, 20199, + -1000, -1000, -1000, 2865, -1000, -1000, -1000, 1244, 4528, -1000, + -1000, 7115, -1000, -1000, 3119, 3100, 20199, -1000, -1000, 3698, + 3692, 3691, 36942, 1516, 2864, 2853, 1546, 4160, -1000, 1099, + 4808, 3400, -1000, -1000, -1000, 1679, -199, 4159, 3065, 3024, + -1000, 74894, -1000, 46050, 46050, 46050, 1234, 1234, 46050, 46050, + 4157, 1304, -1000, -1000, -1000, -1000, 2796, 2443, -1000, -1000, + -1000, -1000, -1000, 74894, 2403, -1000, -1000, -1000, 3550, -1000, + -1000, 2016, -1000, 4717, 2141, -1000, -1000, -1000, -1000, -1000, + 4521, -1000, -373, 16384, 17147, -1000, -383, 74894, 74894, -181, + 3399, -1000, 3685, 496, -1000, -1000, 476, -1000, 1995, -1000, + -1000, 2658, -183, 365, 36183, 2848, -1000, 3967, 514, -68, + -1000, -1000, -1000, 431, 3940, -1000, 431, -1000, 599, 16384, + -1000, -377, -1000, -377, 431, -1000, 3892, 3884, -1000, 3467, + -1000, -1000, -1000, -1000, 74894, 74894, -1000, 74894, 3679, 3395, + -1000, -1000, 2512, -1000, -1000, -1000, 3046, 3042, 2480, 3785, + 3597, 74894, 913, 74894, -296, 3678, -296, 3676, 1041, 3370, + -1000, -1000, -254, -1000, -1000, -1000, -1000, -60, -1000, -1000, + -1000, 719, -1000, 1126, 3578, 3380, -1000, -1000, 775, -1000, + -1000, -1000, 3447, 3675, -1000, -1000, 170, -1000, 2835, 2456, + -1000, -1000, -1000, 885, 1209, -1000, 1797, 4640, 6556, -1000, + 2164, -1000, -1000, -1000, 74894, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 1835, 2796, -1000, 1209, 1136, 2963, -1000, 3377, + -1000, -1000, 16384, 1916, -1000, 3121, 4830, -360, -1000, 13327, + -1000, 3032, 74894, 74894, -1000, -1000, -1000, 47568, 1132, -1000, + 1025, -1000, 2452, -1000, 2450, 46809, 3376, 3552, -1000, 2796, + 2796, 3673, 3672, 875, -1000, -1000, 2796, 2796, 2796, 2796, + 2796, 2796, 4156, 3671, 3661, 2796, 2796, 2796, 2796, 2796, + 2796, 2822, -1000, -1000, -1000, 2820, 2796, 2796, 2796, 6047, + 7535, 3141, -1000, 5584, 1424, -1000, -1000, -1000, 6047, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 3655, 3645, -1000, + -1000, -1000, -1000, -1000, 3371, 4155, 193, -1000, 4683, 4637, + 16384, -1000, -1000, 4154, 2448, 2441, 2437, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 2381, -1000, 74543, 1433, 12541, -1000, 3236, -1000, 36036, 16341, - -165, 4414, -1000, 554, 2316, 7406, 1809, 7406, 7406, 1809, - 7406, 1809, 7406, 1809, 589, -1000, -1000, 74543, 4119, -1000, - 4118, 2294, 2270, 2197, -1000, -1000, -150, -1000, 4117, 2991, - 435, 397, 4717, -1000, 3532, 4702, 3532, 3532, -1000, 356, - 4795, 2970, -1000, 396, 381, 377, 365, -1000, -1000, -1000, - -1000, -1000, -1000, 2810, -1000, 2810, -1000, -1000, -1000, -1000, - -265, -1000, 3537, -1000, -1000, -1000, 45096, 1007, -1000, -1000, - -1000, 4116, -1000, 4115, -1000, 4109, -1000, -1000, 4643, -1000, - 4792, 4764, -1000, -1000, -1000, 1003, 6379, -1000, 12541, 2193, - -1000, 3162, -1000, 1384, -1000, 3132, -1000, -1000, -1000, -1000, - 4411, 4410, 4757, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 81335, 2157, 16341, -1000, -1000, -1000, 74543, - -1000, 4641, 35281, 417, -1000, -1000, -1000, 3535, -1000, 3532, - -1000, -1000, 2679, -26, 1525, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -208, -1000, 74543, 1000, 43586, 43586, 43586, 74543, - 3987, 3982, -1000, 6379, 2154, -1000, 12541, -1000, -165, -1000, - 4785, -1000, 4782, 1516, 1516, 7406, 7406, 7406, 7406, 3940, - -1000, 4108, 3878, -1000, -1000, 74543, -1000, 2151, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 3530, -31, -1000, -1000, -1000, - 3519, 2133, 4107, 2080, -1000, 2674, -1000, -1000, 2069, -1000, - 2624, 2056, -1000, 2614, 1831, 74543, 4026, 74543, 3988, -1000, - -1000, -1000, -1000, -1000, -1000, 3177, 1076, -1000, -1000, 16341, - -1000, 1805, -1000, 2609, -1000, 44341, -1000, -1000, -1000, -1000, - -1000, -1000, 43586, 42831, -1000, 43586, 42831, -1000, 43586, 42831, - 2043, 1821, 16341, 1981, 16341, -1000, -1000, -1000, 3534, 74543, - 11782, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 4509, 74543, 74543, 1969, 4508, 1954, -1000, -1000, -1000, 3162, - 3790, 1810, -1000, -1000, 3591, -1000, 16341, 74543, 16341, 1913, - -1000, 1874, -1000, -1000, + 2431, 2406, 46050, -1000, -1000, 36183, 2796, 2396, 74894, -1000, + -360, -360, 4516, -1000, 74894, 3121, 2026, 336, 4152, 4150, + -1000, -1000, -1000, 4149, -1000, -1000, 4744, -175, 4770, -187, + 3639, 444, 549, -1000, 3635, -1000, -63, 4510, 4506, -71, + -1000, -1000, -1000, -1000, -1000, 2047, -1000, -1000, -1000, 1977, + 431, 431, -1000, -1000, -1000, -1000, 3631, -1000, -1000, -1000, + -1000, -1000, 74894, 3630, -1000, -1000, 166, -1000, 2809, -1000, + 74894, 909, -1000, -296, -1000, -296, 3370, 3624, -1000, 74894, + 1092, -1000, -1000, -1000, -1000, 556, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 3621, 3616, -1000, -1000, 1012, 4743, -1000, + 1797, 6632, -1000, 2796, 885, -1000, 452, 1012, -1000, 945, + -1000, 2669, -1000, 3365, -1000, 2399, 4717, -1000, 1971, 2999, + 16384, 3032, 3032, -1000, -1000, -1000, 941, -1000, 1016, -1000, + -1000, -1000, 2378, -1000, -1000, 3362, 3359, -1000, -1000, 74894, + 3356, 3354, 3323, 3313, 3304, 3302, 74894, -1000, -1000, 3299, + 3286, 3281, 3278, 3272, 3263, 3116, 3105, 3229, 3223, 3166, + -1000, -1000, -1000, 5584, 1020, -1000, -1000, 1192, 4148, -1000, + -1000, 3773, 16384, 4147, 2796, 4146, 3448, -48, 46050, 4403, + -1000, 4401, 4400, 4396, 2365, -1000, 36183, 74894, -1000, -1000, + -1000, -1000, 1959, -1000, 4636, -1000, -334, 4145, 16384, 16384, + 74894, 3581, -179, -1000, -1000, 3615, -1000, 1337, 500, 549, + -1000, 4742, 491, 4741, 4738, 1927, 4505, -1000, -1000, -1000, + -1000, 1308, -169, 428, 426, 422, 376, -1000, -1000, -1000, + -1000, -1000, -1000, 3055, 3055, -296, 3597, 3592, -1000, 74894, + -1000, -1000, 3589, -296, 974, -1000, 695, -1000, -1000, -1000, + 7535, -1000, 4737, 1113, -1000, -1000, 36183, -1000, 4823, 4817, + 4816, 4815, -1000, -1000, -1000, -1000, -1000, 3152, -1000, -1000, + -360, 4783, 3121, 2997, 2986, -1000, -1000, 3149, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2304, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 2298, -1000, 74894, 1418, 12564, -1000, + 3416, -1000, 36183, 16384, -197, 4417, -1000, 608, 2296, 7535, + 1234, 7535, 7535, 1234, 7535, 1234, 7535, 1234, 689, -1000, + -1000, 74894, 4144, -1000, 4143, 2271, 2263, 2233, -1000, -1000, + -181, -1000, 4142, 3143, 506, 433, 4736, -1000, 3581, 4734, + 3581, 3581, -1000, 445, 4788, 3030, -1000, 479, 440, 435, + 432, -1000, -1000, -1000, -1000, -1000, -1000, 2940, -1000, 2940, + -1000, -1000, -1000, -1000, -296, -1000, 3588, -1000, -1000, -1000, + 45291, 1022, -1000, -1000, -1000, 4136, -1000, 4135, -1000, 4133, + -1000, -1000, 4671, -1000, 4812, 4811, -1000, -1000, -1000, 1020, + 6632, -1000, 12564, 2225, -1000, 3121, -1000, 1304, -1000, 3160, + -1000, -1000, -1000, -1000, 4416, 4415, 4776, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 81722, 2223, 16384, + -1000, -1000, -1000, 74894, -1000, 4659, 35424, 490, -1000, -1000, + -1000, 3585, -1000, 3581, -1000, -1000, 2768, -69, 1308, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -261, -1000, 74894, 1013, + 43773, 43773, 43773, 74894, 4008, 4001, -1000, 6632, 2205, -1000, + 12564, -1000, -197, -1000, 4807, -1000, 4777, 1512, 1512, 7535, + 7535, 7535, 7535, 3757, -1000, 4131, 3723, -1000, -1000, 74894, + -1000, 2193, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 3566, + -74, -1000, 1115, -1000, 3558, 2191, 4130, 2186, -1000, 2741, + -1000, -1000, 2160, -1000, 2706, 2123, -1000, 2693, 1916, 74894, + 4129, 74894, 4120, -1000, -1000, -1000, -1000, -1000, -1000, 3246, + 1111, -1000, -1000, 16384, -1000, 1876, -1000, 2677, -1000, 44532, + -1000, -1000, -1000, 655, 4504, 4411, 3098, -1000, -1000, -1000, + -1000, 43773, 43014, -1000, 43773, 43014, -1000, 43773, 43014, 2116, + 2393, 16384, 2111, 16384, -1000, -1000, -1000, 3647, 74894, 11801, + -1000, 854, -1000, -1000, 655, 3084, 4069, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 4526, 74894, 74894, 2038, 4525, + 2033, -1000, -1000, -1000, 3121, -1000, -1000, 664, 3082, 4009, + 2029, -1000, -1000, 3849, -1000, -1000, 658, 16384, 74894, 16384, + -1000, 2031, -1000, 1964, -1000, -1000, } var yyPgo = [...]int{ - 0, 227, 93, 319, 235, 5649, 145, 329, 551, 343, - 527, 5648, 326, 324, 5647, 5641, 5640, 342, 340, 5637, - 5635, 5634, 5633, 5632, 5631, 5629, 5628, 5626, 5625, 5624, - 5623, 5622, 5621, 5620, 5619, 5618, 5617, 5616, 5615, 5614, - 5613, 5611, 5610, 5609, 5607, 5606, 5605, 5604, 5603, 5602, - 5601, 5600, 5598, 5597, 5596, 321, 5595, 5594, 5593, 5592, - 5591, 5589, 5588, 5587, 5586, 5585, 5584, 5583, 5582, 5581, - 5580, 5579, 5578, 5577, 5576, 5560, 5557, 5556, 5555, 5553, - 5552, 5551, 5550, 5548, 5547, 5531, 5530, 5529, 5528, 5527, - 5526, 5525, 5524, 5523, 5522, 468, 5521, 338, 5519, 5518, - 5517, 5516, 5514, 5511, 4543, 5510, 96, 53, 70, 5509, - 5493, 5492, 5488, 5487, 5486, 5485, 5484, 318, 244, 5477, - 5476, 5475, 5465, 5464, 5460, 5459, 5448, 5436, 5435, 5432, - 5428, 5427, 288, 5425, 5424, 316, 5423, 5422, 5420, 5419, - 5418, 276, 5417, 377, 5416, 311, 225, 5413, 5412, 5411, - 5409, 5408, 5407, 5406, 141, 156, 5405, 5404, 5401, 5397, - 5389, 5382, 5379, 5378, 5377, 5375, 5374, 5373, 177, 5372, - 298, 252, 116, 5370, 77, 5369, 301, 260, 5368, 279, - 5367, 191, 5366, 189, 5365, 5364, 5363, 5362, 5360, 5359, - 5358, 5357, 5356, 5355, 5354, 5353, 5352, 5350, 5348, 5347, - 5346, 5345, 5344, 5343, 5342, 5338, 5336, 5335, 5333, 5330, - 5329, 5326, 5325, 5324, 78, 5323, 332, 5322, 112, 5321, - 104, 103, 199, 5320, 136, 5319, 231, 5318, 107, 5314, - 310, 128, 5310, 38, 47, 5309, 62, 60, 153, 5308, - 5307, 325, 4421, 302, 5306, 215, 5305, 283, 5304, 5303, - 5300, 307, 72, 44, 243, 5299, 5298, 322, 221, 5285, - 5282, 5281, 339, 5279, 287, 213, 222, 122, 169, 5278, - 196, 5277, 111, 121, 130, 55, 67, 99, 132, 198, - 172, 5275, 5273, 123, 251, 170, 246, 138, 5272, 5271, - 5270, 7, 224, 295, 5268, 219, 220, 114, 5266, 5264, - 270, 5263, 5262, 5261, 281, 195, 5259, 143, 5257, 5255, - 5254, 32, 5253, 5250, 266, 253, 5249, 5247, 140, 5246, - 5245, 98, 242, 176, 5244, 101, 168, 209, 166, 5239, - 4563, 163, 125, 5235, 160, 150, 5234, 218, 5233, 5232, - 5231, 5229, 237, 5228, 5225, 182, 5224, 85, 5219, 5218, - 5217, 100, 5214, 110, 105, 148, 142, 5211, 42, 146, - 137, 5210, 5209, 5207, 5202, 5201, 14, 5, 6, 5196, - 5194, 5193, 5192, 3, 5191, 5189, 9, 5188, 41, 5187, - 83, 5186, 5181, 5180, 5179, 5176, 5175, 5166, 5165, 5148, - 5146, 5145, 5139, 49, 5127, 5126, 5122, 5121, 11, 19, - 27, 5119, 40, 5115, 210, 5111, 5109, 207, 5107, 5106, - 245, 5103, 5102, 131, 127, 5101, 134, 5100, 205, 5098, - 71, 5094, 5093, 81, 5091, 5089, 5087, 312, 5086, 5085, - 5084, 254, 5083, 5082, 5081, 5079, 587, 5078, 5077, 5076, - 5075, 5074, 5073, 444, 299, 1, 278, 37, 5072, 179, - 187, 5071, 57, 43, 5070, 75, 152, 273, 183, 147, - 5069, 5053, 5050, 806, 162, 139, 59, 0, 144, 280, - 208, 306, 5048, 5047, 330, 5046, 317, 259, 314, 102, - 335, 241, 5045, 5044, 80, 5042, 197, 108, 66, 193, - 292, 23, 685, 5040, 2842, 16, 269, 5039, 272, 5038, - 46, 29, 22, 181, 5036, 5032, 51, 328, 5031, 5028, - 5027, 178, 5026, 5025, 230, 106, 5024, 5023, 5022, 5021, - 5020, 65, 5019, 232, 24, 5015, 175, 5014, 313, 119, - 261, 188, 238, 229, 203, 290, 289, 115, 15, 223, - 5011, 1918, 202, 165, 28, 5010, 13, 286, 274, 206, - 158, 5007, 117, 5006, 309, 334, 264, 5005, 239, 18, - 73, 54, 45, 69, 20, 84, 97, 26, 36, 5002, - 5001, 4998, 4992, 4991, 21, 63, 4990, 82, 4989, 31, - 4987, 4979, 58, 61, 4978, 90, 8, 4977, 4975, 30, - 17, 33, 4974, 52, 297, 216, 171, 135, 91, 4973, - 4972, 212, 522, 4971, 180, 194, 185, 4970, 68, 4969, - 4968, 4967, 4966, 4111, 1766, 4965, 192, 4962, 4960, 4959, - 4956, 4955, 4954, 256, 336, 186, 233, 304, 308, 333, - 4953, 109, 64, 4951, 4950, 4949, 4948, 124, 173, 4947, - 4946, 4945, 4939, 48, 113, 4938, 25, 4936, 39, 34, - 50, 4935, 79, 4934, 4933, 4932, 4, 240, 4931, 4930, - 4929, 12, 4928, 4927, 2, 4926, 4925, 161, 4922, 133, - 35, 214, 211, 4921, 4919, 126, 249, 174, 4918, 4916, - 157, 315, 4914, 257, 4913, 293, 296, 327, 4910, 277, - 4907, 4906, 4905, 4904, 4903, 1736, 4900, 4896, 291, 95, - 129, 4895, 285, 159, 4894, 4893, 120, 204, 164, 151, - 76, 118, 4892, 154, 258, 4891, 248, 4890, 282, 4889, - 4888, 4886, 4882, 217, 4881, 4880, 4879, 4878, 250, 4877, - 4875, 255, 284, 4874, 4873, 323, 320, 4872, 4855, 4854, - 4853, 4852, 4851, 4850, 4849, 4847, 4843, 331, 271, 4840, - 4831, 88, 4830, 4820, -} - -//line mysql_sql.y:16591 + 0, 225, 100, 313, 232, 5577, 129, 355, 293, 351, + 283, 5575, 352, 349, 5574, 5573, 5570, 350, 346, 5569, + 5568, 5564, 5559, 5557, 5556, 5555, 5554, 5553, 5551, 5550, + 5549, 5547, 5545, 5544, 5543, 5542, 5541, 5540, 5538, 5537, + 5536, 5535, 5534, 5532, 5531, 5530, 5529, 5525, 5523, 5522, + 5521, 5520, 5518, 5514, 5513, 337, 5512, 5511, 5510, 5509, + 5506, 5505, 5504, 5503, 5502, 5501, 5500, 5499, 5497, 5495, + 5494, 5493, 5492, 5491, 5490, 5486, 5484, 5483, 5478, 5476, + 5475, 5474, 5467, 5466, 5458, 5457, 5456, 5455, 5454, 5451, + 5450, 5449, 5448, 5447, 5446, 277, 5445, 342, 5444, 5443, + 5439, 5437, 5435, 5431, 4547, 5425, 93, 54, 70, 5424, + 5421, 5420, 5417, 5415, 5414, 5413, 5412, 333, 288, 5411, + 5410, 5409, 5408, 5407, 5405, 5404, 5403, 5402, 5401, 5400, + 5396, 5394, 244, 5393, 5392, 329, 5391, 5390, 5389, 5388, + 5387, 301, 5386, 249, 5385, 326, 230, 5384, 5380, 5378, + 5377, 5375, 5371, 5369, 144, 160, 5354, 5353, 5352, 5351, + 5350, 5348, 5347, 5346, 5345, 5344, 5343, 5342, 188, 5341, + 303, 156, 110, 5340, 72, 5339, 299, 266, 5338, 279, + 5336, 196, 5334, 197, 5333, 5332, 5330, 5329, 5325, 5323, + 5322, 5320, 5319, 5318, 5317, 5315, 5311, 5310, 5309, 5308, + 5294, 5290, 5289, 5288, 5286, 5285, 5284, 5283, 5282, 5278, + 5277, 5276, 5275, 5273, 76, 5272, 324, 5271, 108, 5270, + 127, 125, 202, 5269, 139, 5268, 236, 5267, 109, 5266, + 320, 104, 5265, 38, 48, 5263, 219, 59, 118, 5258, + 5257, 325, 4429, 321, 5256, 199, 5251, 316, 5250, 5249, + 5248, 285, 81, 45, 251, 5247, 5246, 315, 223, 5245, + 5244, 5239, 317, 5238, 282, 217, 218, 132, 163, 5237, + 203, 5236, 113, 121, 128, 52, 67, 94, 135, 198, + 175, 5235, 5234, 111, 240, 169, 248, 141, 5231, 5230, + 5227, 12, 227, 305, 5225, 221, 226, 112, 5224, 5222, + 269, 5220, 5218, 5217, 280, 189, 5216, 143, 5215, 5212, + 5211, 34, 5209, 5206, 262, 2, 1, 5205, 253, 5200, + 5198, 148, 5197, 5196, 95, 245, 179, 5194, 103, 166, + 210, 165, 5192, 3737, 168, 117, 5191, 161, 147, 5190, + 178, 5189, 5188, 5187, 5186, 238, 5182, 5181, 194, 5180, + 83, 5179, 5176, 5171, 97, 5170, 102, 105, 149, 142, + 5169, 41, 146, 134, 5167, 5166, 5165, 5164, 5163, 15, + 5, 6, 5161, 5160, 5159, 5158, 8, 5154, 5153, 9, + 5150, 46, 5147, 85, 5143, 5140, 5131, 5130, 5126, 5120, + 5119, 5116, 5114, 5113, 5111, 5109, 49, 5107, 5104, 5102, + 5101, 13, 29, 28, 5098, 36, 5096, 215, 5093, 5091, + 208, 5090, 5089, 254, 5088, 5087, 131, 126, 5086, 133, + 5085, 229, 5083, 61, 5082, 5081, 1327, 5080, 5079, 5078, + 328, 5077, 5076, 5075, 255, 5074, 5073, 5071, 5070, 559, + 5069, 5068, 5067, 5066, 5065, 5064, 444, 311, 3, 270, + 44, 5063, 182, 183, 5062, 58, 43, 5061, 75, 172, + 278, 180, 151, 5059, 5058, 5057, 792, 162, 140, 98, + 0, 145, 281, 213, 319, 5055, 5054, 327, 5052, 314, + 296, 318, 80, 339, 257, 5051, 5050, 82, 5049, 206, + 107, 66, 193, 292, 24, 345, 5048, 2842, 17, 274, + 5046, 276, 5044, 23, 32, 22, 177, 5042, 5039, 50, + 338, 5038, 5036, 5035, 176, 5034, 5032, 373, 106, 5031, + 5030, 5029, 5028, 5027, 65, 5026, 237, 78, 5024, 181, + 5021, 307, 138, 239, 192, 242, 241, 209, 284, 289, + 115, 19, 224, 5019, 2013, 204, 150, 30, 5017, 16, + 286, 273, 332, 158, 5016, 116, 5015, 312, 335, 264, + 5014, 243, 20, 71, 57, 47, 69, 21, 84, 99, + 27, 40, 5011, 5009, 5008, 5007, 5006, 25, 60, 5005, + 73, 4996, 35, 4995, 4994, 62, 63, 4991, 91, 14, + 4990, 4989, 31, 18, 33, 4988, 51, 294, 216, 171, + 137, 90, 4987, 4985, 212, 754, 4983, 222, 191, 187, + 4982, 64, 4981, 4979, 4978, 4977, 4149, 1873, 4976, 205, + 4975, 4974, 4971, 4970, 4969, 4967, 259, 340, 174, 235, + 310, 298, 334, 4966, 122, 68, 4965, 4960, 4959, 4958, + 120, 173, 4957, 4956, 4954, 4953, 53, 114, 4952, 26, + 4951, 39, 37, 55, 4950, 77, 4949, 4948, 4944, 7, + 246, 4943, 4942, 4940, 11, 4939, 4938, 4, 4937, 4936, + 164, 4935, 136, 42, 211, 214, 4934, 4933, 124, 250, + 170, 4932, 4931, 152, 304, 4930, 258, 4929, 185, 291, + 330, 4926, 271, 4925, 4923, 4921, 4920, 4918, 1897, 4915, + 4913, 297, 96, 130, 4912, 295, 154, 4911, 4910, 123, + 207, 157, 159, 79, 119, 4906, 153, 261, 4904, 260, + 4902, 287, 4901, 4899, 4898, 4897, 220, 4896, 4895, 4894, + 4893, 252, 4889, 4888, 256, 302, 4886, 4885, 323, 309, + 4884, 4883, 4882, 4881, 4878, 4877, 4876, 4875, 4874, 4873, + 322, 290, 4872, 4871, 88, 4851, 4849, +} + +//line mysql_sql.y:16643 type yySymType struct { union interface{} id int @@ -11859,6 +11909,11 @@ func (st *yySymType) propertyUnion() tree.Property { return v } +func (st *yySymType) pythonFunctionOptionsUnion() tree.PythonFunctionOptions { + v, _ := st.union.(tree.PythonFunctionOptions) + return v +} + func (st *yySymType) rankOptionUnion() *tree.RankOption { v, _ := st.union.(*tree.RankOption) return v @@ -12315,70 +12370,70 @@ func (st *yySymType) zeroFillOptUnion() bool { } var yyR1 = [...]int{ - 0, 742, 745, 5, 5, 2, 6, 6, 3, 3, + 0, 745, 748, 5, 5, 2, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 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, 4, 4, 4, 4, 4, 4, 4, 4, 4, 160, - 160, 458, 458, 459, 459, 162, 454, 454, 453, 453, - 163, 164, 165, 719, 719, 720, 720, 718, 718, 166, - 167, 205, 717, 717, 717, 717, 717, 717, 717, 717, - 207, 207, 207, 207, 207, 207, 207, 582, 161, 161, + 160, 461, 461, 462, 462, 162, 457, 457, 456, 456, + 163, 164, 165, 722, 722, 723, 723, 721, 721, 166, + 167, 205, 720, 720, 720, 720, 720, 720, 720, 720, + 207, 207, 207, 207, 207, 207, 207, 585, 161, 161, 161, 161, 288, 288, 289, 289, 176, 176, 177, 177, - 211, 211, 211, 211, 211, 211, 211, 151, 726, 726, - 726, 727, 727, 148, 188, 187, 190, 190, 189, 189, + 211, 211, 211, 211, 211, 211, 211, 151, 729, 729, + 729, 730, 730, 148, 188, 187, 190, 190, 189, 189, 186, 186, 182, 185, 185, 184, 184, 183, 178, 180, 180, 179, 181, 181, 149, 132, 134, 134, 133, 150, - 666, 666, 665, 665, 664, 664, 609, 609, 610, 610, - 445, 445, 445, 663, 663, 663, 662, 662, 661, 661, - 659, 659, 660, 660, 657, 657, 658, 656, 655, 655, - 655, 651, 651, 651, 647, 647, 649, 648, 648, 650, - 642, 642, 645, 645, 643, 643, 643, 643, 646, 641, - 641, 641, 640, 640, 131, 131, 131, 543, 543, 130, - 130, 558, 558, 558, 558, 558, 556, 556, 556, 556, - 556, 556, 555, 555, 554, 554, 559, 559, 557, 557, - 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, - 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, - 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, - 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, - 557, 557, 557, 557, 557, 557, 557, 557, 557, 119, + 669, 669, 668, 668, 667, 667, 612, 612, 613, 613, + 448, 448, 448, 666, 666, 666, 665, 665, 664, 664, + 662, 662, 663, 663, 660, 660, 661, 659, 658, 658, + 658, 654, 654, 654, 650, 650, 652, 651, 651, 653, + 645, 645, 648, 648, 646, 646, 646, 646, 649, 644, + 644, 644, 643, 643, 131, 131, 131, 546, 546, 130, + 130, 561, 561, 561, 561, 561, 559, 559, 559, 559, + 559, 559, 558, 558, 557, 557, 562, 562, 560, 560, + 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, + 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, + 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, + 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, + 560, 560, 560, 560, 560, 560, 560, 560, 560, 119, 119, 119, 119, 119, 119, 119, 126, 124, 124, 124, - 125, 732, 732, 731, 731, 733, 733, 733, 733, 734, - 734, 122, 122, 122, 123, 553, 553, 553, 120, 121, - 121, 542, 542, 548, 548, 547, 547, 547, 547, 547, - 547, 547, 547, 547, 547, 547, 547, 547, 552, 552, - 552, 550, 550, 549, 549, 551, 551, 109, 109, 109, + 125, 735, 735, 734, 734, 736, 736, 736, 736, 737, + 737, 122, 122, 122, 123, 556, 556, 556, 120, 121, + 121, 545, 545, 551, 551, 550, 550, 550, 550, 550, + 550, 550, 550, 550, 550, 550, 550, 550, 555, 555, + 555, 553, 553, 552, 552, 554, 554, 109, 109, 109, 109, 109, 109, 113, 114, 115, 115, 115, 115, 112, - 111, 541, 541, 541, 541, 541, 541, 541, 541, 541, + 111, 544, 544, 544, 544, 544, 544, 544, 544, 544, 110, 110, 110, 110, 110, 110, 96, 96, 96, 96, - 96, 95, 95, 97, 97, 97, 538, 538, 537, 127, - 127, 128, 729, 729, 728, 730, 730, 730, 730, 129, + 96, 95, 95, 97, 97, 97, 541, 541, 540, 127, + 127, 128, 732, 732, 731, 733, 733, 733, 733, 129, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 138, 138, 138, 141, 141, 141, 140, 142, 118, 118, 118, 118, 118, 118, 116, 116, 116, 116, 116, 117, 117, 117, 117, 117, 117, 117, - 117, 117, 117, 117, 117, 692, 692, 692, 692, 692, - 693, 693, 472, 473, 746, 475, 471, 471, 471, 688, - 688, 689, 690, 691, 691, 691, 691, 135, 301, 301, + 117, 117, 117, 117, 117, 695, 695, 695, 695, 695, + 696, 696, 475, 476, 749, 478, 474, 474, 474, 691, + 691, 692, 693, 694, 694, 694, 694, 135, 301, 301, 299, 299, 300, 300, 136, 302, 302, 302, 137, 303, - 303, 16, 298, 298, 581, 581, 13, 13, 13, 13, + 303, 16, 298, 298, 584, 584, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 102, 102, 103, 103, 103, 103, 15, 94, 99, 99, - 99, 101, 409, 409, 410, 408, 408, 408, 408, 408, - 403, 403, 411, 411, 210, 52, 52, 52, 52, 52, - 52, 100, 100, 100, 100, 412, 412, 412, 418, 418, - 419, 419, 404, 404, 404, 404, 404, 404, 404, 404, - 404, 404, 404, 404, 404, 404, 404, 404, 404, 404, - 404, 404, 404, 404, 388, 388, 388, 383, 383, 383, - 383, 384, 384, 385, 385, 386, 386, 386, 386, 387, - 387, 464, 464, 413, 413, 413, 415, 415, 414, 407, - 405, 405, 405, 405, 405, 405, 405, 406, 406, 406, - 406, 416, 416, 417, 417, 92, 98, 98, 98, 98, - 705, 705, 93, 93, 93, 716, 716, 613, 613, 486, - 486, 485, 485, 485, 485, 485, 485, 485, 485, 485, - 485, 485, 485, 485, 485, 485, 485, 618, 619, 482, + 99, 101, 412, 412, 413, 411, 411, 411, 411, 411, + 406, 406, 414, 414, 210, 52, 52, 52, 52, 52, + 52, 100, 100, 100, 100, 415, 415, 415, 421, 421, + 422, 422, 407, 407, 407, 407, 407, 407, 407, 407, + 407, 407, 407, 407, 407, 407, 407, 407, 407, 407, + 407, 407, 407, 407, 391, 391, 391, 386, 386, 386, + 386, 387, 387, 388, 388, 389, 389, 389, 389, 390, + 390, 467, 467, 416, 416, 416, 418, 418, 417, 410, + 408, 408, 408, 408, 408, 408, 408, 409, 409, 409, + 409, 419, 419, 420, 420, 92, 98, 98, 98, 98, + 708, 708, 93, 93, 93, 719, 719, 616, 616, 489, + 489, 488, 488, 488, 488, 488, 488, 488, 488, 488, + 488, 488, 488, 488, 488, 488, 488, 621, 622, 485, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, @@ -12386,222 +12441,223 @@ var yyR1 = [...]int{ 55, 55, 55, 55, 53, 54, 157, 157, 159, 159, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 70, 222, 89, 90, 91, 68, 62, 65, 66, 209, - 212, 212, 212, 212, 61, 61, 61, 527, 527, 60, - 747, 747, 457, 457, 78, 77, 64, 79, 80, 81, + 212, 212, 212, 212, 61, 61, 61, 530, 530, 60, + 750, 750, 460, 460, 78, 77, 64, 79, 80, 81, 82, 83, 84, 59, 76, 76, 76, 76, 76, 76, - 76, 76, 87, 636, 636, 749, 749, 749, 85, 86, - 612, 612, 612, 75, 75, 74, 74, 73, 72, 71, + 76, 76, 87, 639, 639, 752, 752, 752, 85, 86, + 615, 615, 615, 75, 75, 74, 74, 73, 72, 71, 71, 58, 58, 57, 57, 63, 194, 196, 67, 195, - 195, 197, 197, 479, 479, 479, 481, 481, 477, 748, - 748, 577, 577, 480, 480, 56, 56, 56, 56, 88, - 478, 478, 456, 476, 476, 476, 14, 14, 12, 19, + 195, 197, 197, 482, 482, 482, 484, 484, 480, 751, + 751, 580, 580, 483, 483, 56, 56, 56, 56, 88, + 481, 481, 459, 479, 479, 479, 14, 14, 12, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 51, - 28, 29, 27, 30, 32, 535, 535, 532, 31, 22, + 28, 29, 27, 30, 32, 538, 538, 535, 31, 22, 21, 24, 20, 20, 23, 25, 26, 26, 10, 10, - 10, 10, 17, 17, 18, 258, 258, 331, 331, 699, - 699, 695, 695, 696, 696, 696, 697, 697, 698, 698, - 750, 750, 750, 143, 630, 630, 630, 630, 630, 630, - 8, 8, 8, 8, 624, 624, 624, 629, 629, 628, - 627, 627, 626, 626, 625, 625, 625, 625, 9, 9, + 10, 10, 17, 17, 18, 258, 258, 334, 334, 702, + 702, 698, 698, 699, 699, 699, 700, 700, 701, 701, + 753, 753, 753, 143, 633, 633, 633, 633, 633, 633, + 8, 8, 8, 8, 627, 627, 627, 632, 632, 631, + 630, 630, 629, 629, 628, 628, 628, 628, 9, 9, 9, 9, 253, 253, 11, 11, 104, 104, 105, 105, 106, 106, 106, 106, 106, 106, 108, 107, 107, 287, - 287, 623, 623, 623, 623, 623, 623, 540, 540, 539, - 539, 676, 676, 676, 677, 292, 292, 280, 280, 280, - 291, 291, 291, 291, 631, 631, 503, 678, 678, 639, - 639, 638, 638, 637, 637, 285, 285, 293, 293, 293, - 294, 294, 286, 286, 262, 262, 171, 171, 171, 653, - 653, 654, 654, 644, 644, 644, 644, 652, 652, 608, - 608, 393, 393, 447, 447, 448, 448, 240, 236, 236, + 287, 626, 626, 626, 626, 626, 626, 543, 543, 542, + 542, 679, 679, 679, 680, 292, 292, 280, 280, 280, + 291, 291, 291, 291, 634, 634, 506, 681, 681, 642, + 642, 641, 641, 640, 640, 285, 285, 293, 293, 293, + 294, 294, 286, 286, 262, 262, 171, 171, 171, 656, + 656, 657, 657, 647, 647, 647, 647, 655, 655, 611, + 611, 396, 396, 450, 450, 451, 451, 240, 236, 236, 236, 237, 237, 238, 238, 238, 238, 238, 238, 238, - 238, 238, 238, 238, 735, 735, 736, 737, 738, 738, - 739, 739, 740, 740, 740, 741, 741, 741, 741, 741, - 685, 685, 687, 687, 686, 284, 284, 275, 275, 277, + 238, 238, 238, 238, 738, 738, 739, 740, 741, 741, + 742, 742, 743, 743, 743, 744, 744, 744, 744, 744, + 688, 688, 690, 690, 689, 284, 284, 275, 275, 277, 277, 277, 276, 276, 276, 278, 279, 279, 273, 273, 274, 274, 272, 271, 271, 270, 268, 268, 268, 269, 269, 269, 297, 297, 297, 297, 242, 242, 242, 242, 241, 241, 241, 241, 241, 241, 241, 241, 241, 244, 245, 245, 247, 246, 246, 246, 246, 248, 249, 249, - 251, 250, 250, 250, 250, 427, 427, 427, 427, 427, - 427, 427, 427, 427, 427, 427, 427, 243, 255, 255, + 251, 250, 250, 250, 250, 430, 430, 430, 430, 430, + 430, 430, 430, 430, 430, 430, 430, 243, 255, 255, 256, 256, 257, 257, 257, 257, 257, 257, 257, 257, - 257, 257, 424, 424, 425, 425, 425, 425, 425, 169, - 169, 617, 617, 423, 423, 252, 252, 254, 254, 254, - 254, 422, 422, 421, 267, 267, 266, 266, 265, 265, - 265, 259, 259, 259, 259, 259, 259, 261, 433, 433, - 432, 432, 431, 431, 431, 431, 431, 431, 434, 435, - 435, 435, 260, 260, 147, 168, 168, 170, 282, 281, - 430, 429, 429, 429, 429, 296, 296, 295, 295, 283, - 283, 264, 264, 264, 264, 428, 263, 426, 725, 725, - 724, 724, 723, 721, 721, 721, 722, 722, 722, 722, - 668, 668, 668, 668, 668, 465, 465, 465, 470, 470, - 468, 468, 468, 468, 468, 474, 7, 7, 7, 7, + 257, 257, 427, 427, 428, 428, 428, 428, 428, 169, + 169, 620, 620, 426, 426, 252, 252, 254, 254, 254, + 254, 425, 425, 424, 267, 267, 266, 266, 265, 265, + 265, 259, 259, 259, 259, 259, 259, 261, 436, 436, + 435, 435, 434, 434, 434, 434, 434, 434, 437, 438, + 438, 438, 260, 260, 147, 168, 168, 170, 282, 281, + 433, 432, 432, 432, 432, 296, 296, 295, 295, 283, + 283, 264, 264, 264, 264, 431, 263, 429, 728, 728, + 727, 727, 726, 724, 724, 724, 725, 725, 725, 725, + 671, 671, 671, 671, 671, 468, 468, 468, 473, 473, + 471, 471, 471, 471, 471, 477, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 45, 46, 50, 152, 152, 155, 155, 153, 153, 154, 154, - 158, 158, 156, 156, 42, 313, 314, 43, 315, 315, - 316, 316, 317, 317, 318, 319, 320, 320, 320, 320, - 519, 519, 41, 304, 304, 305, 305, 306, 306, 307, - 308, 308, 308, 312, 309, 310, 310, 744, 744, 743, - 40, 40, 33, 33, 215, 215, 216, 216, 216, 218, - 218, 389, 389, 389, 217, 217, 219, 219, 219, 700, - 702, 702, 704, 703, 703, 703, 706, 706, 706, 706, - 706, 707, 707, 707, 707, 708, 708, 34, 191, 191, - 191, 228, 228, 201, 711, 711, 711, 710, 710, 583, - 583, 712, 712, 713, 713, 451, 451, 452, 452, 213, - 214, 214, 203, 193, 227, 227, 227, 227, 227, 229, - 229, 333, 333, 192, 198, 199, 200, 202, 204, 206, - 206, 208, 701, 709, 709, 709, 536, 536, 533, 534, - 534, 531, 530, 530, 530, 715, 715, 714, 714, 714, - 466, 466, 35, 526, 526, 528, 529, 529, 529, 529, - 529, 529, 529, 529, 520, 520, 520, 520, 520, 39, - 524, 524, 525, 525, 525, 525, 525, 525, 525, 525, - 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, - 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, - 525, 525, 525, 525, 521, 521, 523, 523, 518, 518, - 518, 518, 518, 518, 518, 518, 518, 518, 38, 38, - 38, 226, 226, 517, 517, 514, 514, 514, 311, 311, - 512, 512, 513, 513, 511, 511, 511, 515, 515, 47, - 48, 49, 516, 516, 230, 230, 230, 230, 230, 230, - 230, 230, 230, 230, 230, 290, 290, 235, 235, 235, - 235, 235, 235, 233, 233, 233, 233, 234, 234, 231, - 231, 232, 232, 220, 220, 220, 221, 221, 37, 37, + 158, 158, 156, 156, 42, 313, 314, 43, 318, 318, + 319, 319, 320, 320, 321, 322, 323, 323, 323, 323, + 522, 522, 41, 304, 304, 305, 305, 306, 306, 307, + 308, 308, 308, 312, 309, 310, 310, 747, 747, 746, + 317, 317, 317, 317, 317, 316, 316, 315, 315, 40, + 40, 33, 33, 215, 215, 216, 216, 216, 218, 218, + 392, 392, 392, 217, 217, 219, 219, 219, 703, 705, + 705, 707, 706, 706, 706, 709, 709, 709, 709, 709, + 710, 710, 710, 710, 711, 711, 34, 191, 191, 191, + 228, 228, 201, 714, 714, 714, 713, 713, 586, 586, + 715, 715, 716, 716, 454, 454, 455, 455, 213, 214, + 214, 203, 193, 227, 227, 227, 227, 227, 229, 229, + 336, 336, 192, 198, 199, 200, 202, 204, 206, 206, + 208, 704, 712, 712, 712, 539, 539, 536, 537, 537, + 534, 533, 533, 533, 718, 718, 717, 717, 717, 469, + 469, 35, 529, 529, 531, 532, 532, 532, 532, 532, + 532, 532, 532, 523, 523, 523, 523, 523, 39, 527, + 527, 528, 528, 528, 528, 528, 528, 528, 528, 528, + 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, + 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, + 528, 528, 528, 524, 524, 526, 526, 521, 521, 521, + 521, 521, 521, 521, 521, 521, 521, 38, 38, 38, + 226, 226, 520, 520, 517, 517, 517, 311, 311, 515, + 515, 516, 516, 514, 514, 514, 518, 518, 47, 48, + 49, 519, 519, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 290, 290, 235, 235, 235, 235, + 235, 235, 233, 233, 233, 233, 234, 234, 231, 231, + 232, 232, 220, 220, 220, 221, 221, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 173, 172, 172, - 172, 172, 172, 175, 175, 450, 450, 449, 449, 174, - 390, 390, 44, 344, 344, 600, 600, 595, 595, 595, - 595, 595, 615, 615, 615, 596, 596, 596, 597, 597, - 597, 599, 599, 599, 598, 598, 598, 598, 598, 614, - 614, 616, 616, 616, 560, 560, 561, 561, 561, 564, - 564, 586, 586, 587, 587, 585, 585, 593, 593, 592, - 592, 591, 591, 589, 589, 590, 588, 588, 588, 588, - 580, 580, 579, 579, 562, 562, 562, 562, 562, 563, - 563, 563, 578, 578, 584, 584, 353, 354, 354, 355, - 355, 356, 223, 223, 224, 224, 357, 358, 358, 359, - 359, 360, 361, 361, 362, 362, 363, 364, 364, 365, - 365, 366, 369, 370, 371, 371, 372, 372, 373, 377, - 377, 374, 374, 375, 375, 376, 367, 367, 368, 368, - 351, 351, 352, 352, 352, 420, 420, 420, 420, 420, - 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, - 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, - 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, - 420, 674, 674, 675, 379, 379, 391, 391, 391, 391, - 391, 391, 378, 378, 380, 380, 332, 332, 330, 330, - 322, 322, 322, 322, 322, 322, 225, 225, 225, 321, - 321, 321, 321, 321, 321, 323, 323, 324, 324, 325, - 325, 325, 329, 329, 328, 328, 328, 328, 328, 326, - 326, 327, 327, 327, 327, 327, 327, 545, 545, 671, - 671, 672, 672, 667, 667, 667, 670, 670, 670, 670, - 670, 670, 670, 670, 670, 670, 670, 673, 673, 673, - 669, 669, 334, 444, 444, 444, 467, 467, 467, 467, - 469, 443, 443, 443, 350, 350, 349, 349, 347, 347, - 347, 347, 347, 347, 347, 347, 347, 347, 347, 347, - 347, 347, 347, 347, 347, 347, 347, 347, 347, 347, - 347, 347, 347, 347, 546, 546, 546, 544, 544, 544, - 483, 483, 484, 484, 402, 401, 401, 401, 401, 401, - 399, 400, 398, 398, 398, 398, 398, 395, 395, 394, - 394, 394, 396, 396, 396, 396, 396, 396, 522, 522, - 392, 392, 382, 382, 382, 381, 381, 381, 594, 490, - 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, - 490, 490, 490, 490, 492, 492, 492, 492, 492, 492, - 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, - 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, - 492, 492, 492, 492, 397, 397, 397, 441, 441, 441, - 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, - 441, 441, 442, 442, 442, 442, 442, 442, 442, 442, - 493, 493, 499, 499, 684, 684, 683, 335, 335, 335, - 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, - 345, 345, 345, 574, 574, 574, 574, 574, 575, 575, - 575, 575, 575, 576, 576, 576, 572, 572, 573, 573, - 504, 505, 505, 621, 621, 622, 622, 565, 565, 566, - 566, 567, 571, 571, 569, 569, 570, 570, 568, 440, - 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, + 37, 37, 37, 37, 37, 37, 173, 172, 172, 172, + 172, 172, 175, 175, 453, 453, 452, 452, 174, 393, + 393, 44, 347, 347, 603, 603, 598, 598, 598, 598, + 598, 618, 618, 618, 599, 599, 599, 600, 600, 600, + 602, 602, 602, 601, 601, 601, 601, 601, 617, 617, + 619, 619, 619, 563, 563, 564, 564, 564, 567, 567, + 589, 589, 590, 590, 588, 588, 596, 596, 595, 595, + 594, 594, 592, 592, 593, 591, 591, 591, 591, 583, + 583, 582, 582, 565, 565, 565, 565, 565, 566, 566, + 566, 581, 581, 587, 587, 356, 357, 357, 358, 358, + 359, 223, 223, 224, 224, 360, 361, 361, 362, 362, + 363, 364, 364, 365, 365, 366, 367, 367, 368, 368, + 369, 372, 373, 374, 374, 375, 375, 376, 380, 380, + 377, 377, 378, 378, 379, 370, 370, 371, 371, 354, + 354, 355, 355, 355, 423, 423, 423, 423, 423, 423, + 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, + 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, + 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, + 677, 677, 678, 382, 382, 394, 394, 394, 394, 394, + 394, 381, 381, 383, 383, 335, 335, 333, 333, 325, + 325, 325, 325, 325, 325, 225, 225, 225, 324, 324, + 324, 324, 324, 324, 326, 326, 327, 327, 328, 328, + 328, 332, 332, 331, 331, 331, 331, 331, 329, 329, + 330, 330, 330, 330, 330, 330, 548, 548, 674, 674, + 675, 675, 670, 670, 670, 673, 673, 673, 673, 673, + 673, 673, 673, 673, 673, 673, 676, 676, 676, 672, + 672, 337, 447, 447, 447, 470, 470, 470, 470, 472, + 446, 446, 446, 353, 353, 352, 352, 350, 350, 350, + 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, + 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, + 350, 350, 350, 549, 549, 549, 547, 547, 547, 486, + 486, 487, 487, 405, 404, 404, 404, 404, 404, 402, + 403, 401, 401, 401, 401, 401, 398, 398, 397, 397, + 397, 399, 399, 399, 399, 399, 399, 525, 525, 395, + 395, 385, 385, 385, 384, 384, 384, 597, 493, 493, + 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, + 493, 493, 493, 495, 495, 495, 495, 495, 495, 495, + 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + 495, 495, 495, 400, 400, 400, 444, 444, 444, 444, + 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, + 444, 445, 445, 445, 445, 445, 445, 445, 445, 496, + 496, 502, 502, 687, 687, 686, 338, 338, 338, 339, + 339, 339, 339, 339, 339, 339, 339, 339, 339, 348, + 348, 348, 577, 577, 577, 577, 577, 578, 578, 578, + 578, 578, 579, 579, 579, 575, 575, 576, 576, 507, + 508, 508, 624, 624, 625, 625, 568, 568, 569, 569, + 570, 574, 574, 572, 572, 573, 573, 571, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 638, 638, 638, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, - 440, 440, 440, 440, 440, 440, 440, 635, 635, 635, - 437, 437, 437, 437, 437, 437, 437, 437, 437, 437, - 437, 437, 437, 437, 437, 437, 437, 437, 694, 694, - 694, 679, 679, 679, 680, 680, 680, 680, 680, 680, - 680, 680, 680, 680, 680, 680, 681, 681, 681, 681, - 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, - 681, 681, 681, 682, 682, 682, 682, 439, 439, 439, - 439, 439, 438, 438, 438, 438, 438, 438, 438, 438, - 438, 438, 438, 438, 438, 438, 438, 438, 438, 438, - 506, 506, 507, 507, 632, 632, 632, 632, 632, 632, - 633, 633, 634, 634, 634, 634, 620, 620, 620, 620, - 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, - 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, - 620, 620, 620, 620, 620, 620, 491, 436, 436, 436, - 508, 500, 500, 501, 501, 502, 502, 494, 494, 494, - 494, 494, 495, 495, 497, 497, 497, 497, 497, 497, - 497, 497, 497, 497, 497, 497, 497, 497, 497, 489, - 489, 489, 489, 489, 489, 489, 489, 489, 489, 489, - 489, 489, 489, 489, 489, 489, 496, 496, 753, 753, - 498, 498, 510, 510, 510, 509, 509, 509, 509, 509, - 509, 509, 348, 348, 348, 348, 488, 488, 488, 487, - 487, 487, 487, 487, 487, 487, 487, 487, 487, 487, - 487, 337, 337, 337, 337, 337, 341, 341, 343, 343, - 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, - 343, 343, 342, 342, 342, 342, 342, 342, 340, 340, - 340, 340, 340, 338, 338, 338, 338, 338, 338, 338, - 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, - 338, 338, 338, 338, 338, 338, 338, 338, 144, 145, - 239, 239, 146, 146, 339, 346, 346, 346, 346, 346, + 440, 440, 440, 440, 440, 440, 440, 697, 697, 697, + 682, 682, 682, 683, 683, 683, 683, 683, 683, 683, + 683, 683, 683, 683, 683, 684, 684, 684, 684, 684, + 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, + 684, 684, 685, 685, 685, 685, 442, 442, 442, 442, + 442, 441, 441, 441, 441, 441, 441, 441, 441, 441, + 441, 441, 441, 441, 441, 441, 441, 441, 441, 509, + 509, 510, 510, 635, 635, 635, 635, 635, 635, 636, + 636, 637, 637, 637, 637, 623, 623, 623, 623, 623, + 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, + 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, + 623, 623, 623, 623, 623, 494, 439, 439, 439, 511, + 503, 503, 504, 504, 505, 505, 497, 497, 497, 497, + 497, 498, 498, 500, 500, 500, 500, 500, 500, 500, + 500, 500, 500, 500, 500, 500, 500, 500, 492, 492, + 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, + 492, 492, 492, 492, 492, 499, 499, 756, 756, 501, + 501, 513, 513, 513, 512, 512, 512, 512, 512, 512, + 512, 351, 351, 351, 351, 491, 491, 491, 490, 490, + 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, + 340, 340, 340, 340, 340, 344, 344, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 346, 346, 446, 446, 601, 601, 604, 604, 602, - 602, 603, 605, 605, 605, 606, 606, 606, 607, 607, - 607, 611, 611, 455, 455, 455, 463, 463, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 461, 461, 461, 461, 461, 461, 461, - 461, 461, 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, 460, 460, 460, 460, 751, 751, 752, - 752, + 346, 345, 345, 345, 345, 345, 345, 343, 343, 343, + 343, 343, 341, 341, 341, 341, 341, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 144, 145, 239, + 239, 146, 146, 342, 349, 349, 349, 349, 349, 349, + 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, + 349, 349, 449, 449, 604, 604, 607, 607, 605, 605, + 606, 608, 608, 608, 609, 609, 609, 610, 610, 610, + 614, 614, 458, 458, 458, 466, 466, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 465, 465, 465, 465, + 465, 465, 465, 465, 465, 465, 464, 464, 464, 464, + 464, 464, 464, 464, 464, 463, 463, 463, 463, 463, + 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, + 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, + 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, + 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, + 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, + 754, 754, 755, 755, } var yyR2 = [...]int{ @@ -12731,115 +12787,117 @@ var yyR2 = [...]int{ 6, 10, 0, 3, 0, 2, 0, 4, 1, 1, 0, 2, 0, 2, 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, + 0, 2, 15, 1, 3, 0, 1, 1, 3, 1, 1, 2, 4, 1, 1, 1, 1, 0, 1, 2, - 9, 9, 7, 8, 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, - 8, 2, 2, 8, 0, 3, 3, 0, 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, 5, 4, 4, 4, 6, 4, - 8, 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, 1, - 1, 1, 1, 1, 0, 1, 1, 1, 1, 11, - 0, 2, 3, 3, 2, 2, 3, 1, 1, 3, - 3, 3, 3, 3, 3, 4, 2, 2, 3, 3, - 3, 3, 3, 3, 3, 3, 1, 1, 1, 3, - 3, 3, 3, 3, 1, 3, 3, 4, 0, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 6, 8, - 10, 0, 4, 1, 1, 0, 3, 3, 0, 1, - 0, 1, 1, 2, 4, 4, 4, 0, 1, 4, - 4, 4, 0, 2, 8, 9, 5, 5, 8, 7, - 8, 12, 12, 13, 13, 0, 4, 0, 3, 3, - 3, 2, 2, 0, 3, 3, 3, 4, 4, 0, - 3, 0, 2, 0, 1, 1, 1, 1, 11, 9, - 9, 9, 9, 9, 9, 6, 11, 6, 9, 7, - 10, 8, 11, 7, 6, 9, 11, 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, 1, 0, 4, 6, 5, - 0, 2, 0, 2, 4, 5, 4, 5, 1, 5, - 6, 5, 0, 3, 0, 1, 4, 0, 4, 1, - 3, 3, 1, 1, 1, 1, 4, 0, 4, 1, - 3, 3, 1, 1, 1, 1, 4, 0, 4, 1, - 3, 3, 4, 4, 0, 4, 1, 3, 3, 1, - 1, 0, 4, 1, 3, 3, 1, 1, 1, 1, - 0, 1, 1, 3, 2, 3, 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, 3, 5, - 0, 3, 3, 6, 5, 3, 1, 1, 1, 0, - 5, 5, 5, 5, 6, 0, 1, 1, 3, 1, - 1, 1, 1, 1, 7, 9, 7, 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, 1, 1, 1, - 0, 1, 3, 1, 3, 5, 1, 1, 1, 1, - 1, 1, 3, 5, 0, 1, 1, 2, 1, 2, - 2, 2, 1, 1, 2, 2, 2, 2, 2, 3, - 3, 2, 2, 1, 5, 6, 4, 2, 1, 1, - 1, 5, 7, 5, 0, 1, 1, 1, 2, 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, 3, 0, 3, - 0, 3, 1, 1, 1, 1, 1, 1, 1, 3, + 0, 2, 1, 3, 3, 1, 1, 4, 5, 9, + 9, 7, 8, 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, 8, + 2, 2, 8, 0, 3, 3, 0, 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, 5, 4, 4, 4, 6, 4, 8, + 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, 1, 1, + 1, 1, 1, 0, 1, 1, 1, 1, 11, 0, + 2, 3, 3, 2, 2, 3, 1, 1, 3, 3, + 3, 3, 3, 3, 4, 2, 2, 3, 3, 3, + 3, 3, 3, 3, 3, 1, 1, 1, 3, 3, + 3, 3, 3, 1, 3, 3, 4, 0, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 6, 8, 10, + 0, 4, 1, 1, 0, 3, 3, 0, 1, 0, + 1, 1, 2, 4, 4, 4, 0, 1, 4, 4, + 4, 0, 2, 8, 9, 5, 5, 8, 7, 8, + 12, 12, 13, 13, 0, 4, 0, 3, 3, 3, + 2, 2, 0, 3, 3, 3, 4, 4, 0, 3, + 0, 2, 0, 1, 1, 1, 1, 11, 9, 9, + 9, 9, 9, 9, 6, 11, 6, 9, 7, 10, + 8, 11, 7, 6, 9, 11, 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, 1, 0, 4, 6, 5, 0, + 2, 0, 2, 4, 5, 4, 5, 1, 5, 6, + 5, 0, 3, 0, 1, 4, 0, 4, 1, 3, + 3, 1, 1, 1, 1, 4, 0, 4, 1, 3, + 3, 1, 1, 1, 1, 4, 0, 4, 1, 3, + 3, 4, 4, 0, 4, 1, 3, 3, 1, 1, + 0, 4, 1, 3, 3, 1, 1, 1, 1, 0, + 1, 1, 3, 2, 3, 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, 3, 5, 0, + 3, 3, 6, 5, 3, 1, 1, 1, 0, 5, + 5, 5, 5, 6, 0, 1, 1, 3, 1, 1, + 1, 1, 1, 7, 9, 7, 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, 1, 1, 1, 0, + 1, 3, 1, 3, 5, 1, 1, 1, 1, 1, + 1, 3, 5, 0, 1, 1, 2, 1, 2, 2, + 2, 1, 1, 2, 2, 2, 2, 2, 3, 3, + 2, 2, 1, 5, 6, 4, 2, 1, 1, 1, + 5, 7, 5, 0, 1, 1, 1, 2, 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, 3, 0, 3, 0, + 3, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 1, 1, 1, 1, 3, 3, 5, - 2, 2, 2, 2, 2, 4, 1, 1, 2, 5, - 6, 8, 6, 3, 6, 6, 1, 1, 1, 1, - 1, 1, 3, 9, 1, 1, 1, 4, 4, 4, - 4, 5, 4, 6, 8, 10, 6, 8, 10, 6, - 6, 9, 7, 9, 7, 7, 7, 9, 7, 7, - 0, 2, 0, 1, 1, 2, 4, 1, 2, 2, - 1, 1, 2, 2, 1, 2, 2, 2, 2, 2, - 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 1, 1, 1, 2, 5, 0, 1, - 3, 0, 1, 0, 2, 0, 2, 0, 1, 2, - 4, 4, 0, 1, 0, 2, 1, 3, 5, 9, - 6, 6, 8, 6, 6, 5, 5, 6, 6, 6, - 6, 6, 5, 6, 6, 6, 6, 6, 6, 6, - 6, 9, 6, 6, 6, 6, 8, 1, 1, 1, - 4, 6, 4, 6, 8, 6, 6, 4, 6, 4, - 4, 4, 3, 4, 6, 6, 7, 4, 1, 1, + 3, 3, 1, 1, 1, 1, 3, 3, 5, 2, + 2, 2, 2, 2, 4, 1, 1, 2, 5, 6, + 8, 6, 3, 6, 6, 1, 1, 1, 1, 1, + 1, 3, 9, 1, 1, 1, 4, 4, 4, 4, + 5, 4, 6, 8, 10, 6, 8, 10, 6, 6, + 9, 7, 9, 7, 7, 7, 9, 7, 7, 0, + 2, 0, 1, 1, 2, 4, 1, 2, 2, 1, + 1, 2, 2, 1, 2, 2, 2, 2, 2, 0, + 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 1, 1, 1, 2, 5, 0, 1, 3, + 0, 1, 0, 2, 0, 2, 0, 1, 2, 4, + 4, 0, 1, 0, 2, 1, 3, 5, 9, 6, + 6, 8, 6, 6, 5, 5, 6, 6, 6, 6, + 6, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 9, 6, 6, 6, 6, 8, 1, 1, 1, 4, + 6, 4, 6, 8, 6, 6, 4, 6, 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, + 1, 1, 1, 1, 1, 1, 2, 2, 8, 8, + 6, 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, 2, 2, 8, - 8, 6, 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, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 1, 3, 3, 3, 3, 2, + 1, 1, 1, 3, 4, 4, 3, 4, 4, 3, + 4, 4, 3, 4, 4, 3, 4, 1, 3, 4, + 4, 6, 4, 5, 5, 4, 5, 5, 3, 4, + 4, 5, 6, 6, 1, 0, 2, 0, 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, - 2, 1, 1, 1, 3, 4, 4, 3, 4, 4, - 3, 4, 4, 3, 4, 4, 3, 4, 1, 3, - 4, 4, 6, 4, 5, 5, 4, 5, 5, 3, - 4, 4, 5, 6, 6, 1, 0, 2, 0, 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, 4, 2, 1, 1, 1, 1, 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, 4, 2, 1, 1, 1, + 1, 2, 3, 2, 2, 2, 2, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, + 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 4, 4, 1, 2, 2, 7, + 8, 3, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 3, 2, 2, 2, 2, 1, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, - 2, 1, 1, 1, 2, 1, 1, 1, 1, 2, - 2, 2, 2, 2, 2, 4, 4, 1, 2, 2, - 7, 8, 3, 5, 1, 1, 1, 1, 1, 1, + 1, 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, 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, @@ -12890,545 +12948,546 @@ 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, 0, 2, 0, - 2, + 0, 2, 0, 2, } var yyChk = [...]int{ - -1000, -742, -745, -5, -1, -2, -4, -146, -109, 726, + -1000, -745, -748, -5, -1, -2, -4, -146, -109, 730, -7, -16, -148, -134, -149, -8, -143, -10, -11, -12, -204, -14, -116, -138, -140, -142, -141, -55, -13, -135, -136, -137, -95, -96, -119, -127, -130, -131, -132, -133, -150, -144, -145, -147, -236, -151, -160, -161, -211, -164, - -166, -167, -199, -200, -230, 715, -110, -111, -112, -113, + -166, -167, -199, -200, -230, 719, -110, -111, -112, -113, -114, -115, -36, -35, -34, -33, -191, -201, -205, -207, - -162, -50, 631, 721, 760, 532, -9, -685, -624, 585, - -17, -18, -104, -19, 272, 299, -471, -117, -472, -473, - -475, -746, -56, -57, -58, -71, -72, -73, -74, -75, + -162, -50, 635, 725, 764, 536, -9, -688, -627, 589, + -17, -18, -104, -19, 272, 299, -474, -117, -475, -476, + -478, -749, -56, -57, -58, -71, -72, -73, -74, -75, -85, -86, -87, -59, -60, -61, -64, -62, -78, -77, -79, -80, -81, -82, -83, -84, -63, -67, -194, -195, -196, -197, -88, -65, -66, -209, -212, -163, -89, -90, -91, -68, -53, -54, -69, -70, -93, -92, -98, -94, -99, -193, -203, -15, -210, -100, -52, -102, -103, -101, 273, 344, 292, -97, 80, -120, -121, -122, -123, -124, - -125, -126, -128, -129, 457, 463, 519, 713, 714, 65, - -238, -240, -242, 762, 763, 766, 616, 618, 317, 180, + -125, -126, -128, -129, 457, 463, 523, 717, 718, 65, + -238, -240, -242, 766, 767, 770, 620, 622, 317, 180, 181, 183, 184, 188, 191, -37, -38, -39, -40, -41, -42, -44, -43, -45, -46, -47, -48, -49, 268, 16, 14, 18, 58, -20, -23, -21, -24, -22, -31, -32, -30, -25, -27, -192, -198, -26, -202, -206, -208, -165, -51, -28, -29, 294, 293, 41, 360, 361, 362, 461, 269, 271, 17, 34, 45, 436, -241, -245, 90, -248, - -244, 617, 270, -243, -247, 15, 278, 780, -6, -3, + -244, 621, 270, -243, -247, 15, 278, 784, -6, -3, -2, -178, -182, -186, -189, -190, -187, -188, -4, -146, - 125, 284, 716, -467, 453, 717, 719, 718, 93, 101, - -460, -462, 760, 532, 299, 457, 463, 713, 714, 763, - 766, 616, 618, 317, 633, 634, 635, 636, 637, 638, - 639, 640, 642, 643, 644, 645, 646, 647, 648, 691, - 692, 658, 659, 649, 650, 651, 652, 653, 654, 655, - 656, 660, 661, 662, 663, 664, 665, 666, 667, 668, - 669, 670, 671, 672, 673, 588, 589, 693, 695, 696, - 697, 698, 641, 678, 686, 687, 688, 771, 772, 434, - 435, 624, 710, 769, 311, 335, 486, 341, 348, 415, - 180, 198, 194, 223, 213, 421, 367, 739, 740, 366, - 617, 189, 315, 353, 316, 100, 183, 571, 115, 544, - 515, 186, 373, 376, 374, 375, 330, 332, 334, 447, - 337, 336, 338, 340, 615, 371, 437, 209, 203, 329, - 313, 201, 318, 422, 43, 319, 413, 412, 228, 320, - 321, 628, 540, 433, 546, 345, 56, 513, 202, 333, - 543, 709, 236, 240, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 562, 419, 400, 401, 402, 403, - 563, 424, 171, 172, 548, 738, 745, 746, 747, 749, - 750, 751, 748, 418, 565, 423, 227, 230, 231, 232, - 233, 234, 235, 291, 409, 410, 425, 426, 427, 428, - 429, 431, 432, 46, 626, 303, 566, 238, 756, 217, - 226, 221, 574, 349, 347, 414, 225, 197, 220, 314, - 778, 761, 69, 242, 241, 243, 509, 510, 511, 512, - 322, 323, 451, 561, 741, 742, 216, 204, 438, 190, - 25, 569, 298, 545, 464, 377, 51, 378, 324, 342, - 350, 372, 237, 239, 305, 310, 365, 420, 627, 517, - 518, 309, 553, 554, 346, 567, 200, 302, 331, 297, - 570, 757, 743, 191, 777, 466, 325, 184, 339, 564, - 759, 573, 68, 166, 196, 187, 733, 734, 288, 694, - 181, 307, 312, 711, 758, 326, 327, 328, 352, 351, - 343, 188, 218, 304, 224, 207, 195, 219, 182, 306, - 572, 167, 707, 436, 496, 215, 212, 308, 281, 712, - 568, 547, 185, 500, 169, 210, 354, 701, 702, 703, - 706, 452, 408, 355, 356, 208, 295, 538, 539, 359, - 506, 395, 480, 516, 487, 481, 259, 260, 363, 550, - 552, 229, 704, 379, 380, 381, 542, 382, 384, 385, - 390, 456, 60, 62, 102, 105, 104, 764, 765, 67, - 32, 442, 445, 478, 779, 482, 397, 708, 625, 394, - 398, 399, 446, 28, 498, 468, 502, 501, 52, 53, - 54, 57, 58, 59, 61, 63, 64, 55, 614, 461, - 475, 575, 48, 50, 471, 472, 30, 448, 497, 520, - 393, 499, 531, 49, 529, 530, 551, 29, 450, 449, - 66, 47, 505, 507, 508, 357, 391, 459, 722, 576, - 454, 470, 474, 455, 396, 444, 476, 71, 467, 723, - 462, 460, 773, 774, 392, 629, 630, 404, 657, 439, - 514, 611, 610, 609, 608, 607, 606, 605, 604, 360, - 361, 362, 483, 484, 485, 495, 488, 489, 490, 491, - 492, 493, 494, 534, 535, 724, 725, 555, 557, 558, - 622, 559, 556, 276, 768, 767, 440, 441, 279, 727, - 728, 103, 729, 731, 730, 31, 732, 755, 752, 753, - 754, 632, 560, 619, 735, 621, 620, 679, 680, 681, - 682, 683, -551, -549, -467, 617, 317, 760, 713, 714, - 463, 616, 618, 457, 436, 763, 766, 58, 461, 299, - 360, 361, 362, 532, 434, -315, -467, 278, 767, -97, - -18, -17, -9, -624, -104, -241, -242, -750, 265, 267, - 472, -330, 278, -467, -476, 26, 513, -118, 514, 273, - 274, 90, 81, -467, -10, -132, -8, -143, -95, -236, - -685, 519, -474, -467, 360, 360, 622, -474, 278, 278, - 737, 518, 559, 622, 738, 745, 756, 554, 447, 104, - 105, 733, 734, 30, 278, 458, 305, 552, 550, 551, - 555, 556, 557, 558, -76, -636, -612, 547, 638, 546, - -480, 539, 545, 537, 549, 540, 435, 385, 382, 631, - 384, 389, 268, 727, 613, -455, 480, 516, 575, 576, - 459, 517, 562, 564, 541, 115, 214, 211, -469, 309, - 494, -467, -613, 284, -555, -526, 310, -554, -528, -557, - -529, 35, 268, 270, 269, 631, 306, 18, 461, 280, - 16, 15, 462, 292, 28, 29, 31, 17, 463, 465, - 32, 466, 469, 470, 471, 45, 475, 476, 299, 93, - 101, 96, 679, 680, 681, 682, 683, 317, 278, -314, - -467, -502, -494, 122, -497, -489, -490, -492, -445, -657, - -487, 90, 151, 152, 159, 123, 161, 781, -491, -594, - 39, 125, 637, 641, 678, 586, -437, -438, -439, -440, - -441, -442, 623, -467, -658, -656, 96, 106, 108, 112, - 113, 111, 109, 174, 205, 110, 97, 175, -242, 93, - -679, 647, 653, -461, 670, 695, 696, 697, 698, 669, - 65, -620, -634, 277, -632, 173, 211, 295, 207, 16, - 157, 506, 208, 686, 687, 688, 644, 666, 588, 589, - 693, 648, 771, 772, 658, 673, 639, 640, 642, 634, - 635, 636, 638, 649, 651, 665, -635, 661, 671, 672, - 657, 689, 690, 752, 691, 692, 674, 675, 676, 685, - 684, 677, 679, 680, 681, 682, 683, 731, 95, 94, - 664, 663, 650, 645, 646, 652, 633, 643, 654, 662, - 667, 668, 445, 115, 446, 447, 578, 437, 84, 448, - 284, 513, 74, 449, 450, 451, 452, 453, 585, 454, - 777, 75, 455, 444, 299, 496, 456, 210, 229, 591, - 590, 592, 582, 579, 577, 580, 581, 583, 584, 655, - 656, 660, -239, -241, -685, -242, -168, -170, 699, -735, - -278, -736, -427, 25, -737, 6, 7, 8, 9, 175, - -726, 515, 627, 96, 578, 278, 353, 434, 19, 737, - 389, 615, 737, 389, 615, 367, 185, 182, -541, 185, - 121, 191, 190, 282, 185, -541, -467, 188, 737, 187, - 733, 738, 745, 622, 363, -516, -215, 434, 496, 382, - 102, 309, -520, -517, -614, 357, 353, 279, 118, -216, - 289, 430, 288, 116, 578, 277, 473, 348, 60, 62, - 35, 48, -262, 51, 283, 42, -330, -687, 612, -686, - -467, -695, -696, 265, 266, 267, 42, 738, 745, 279, - 281, 278, 733, 622, 309, 434, 578, 496, 102, 382, - 278, -695, 756, 182, 562, 564, 515, 309, 494, 44, - -548, 506, -547, -549, 563, 574, 94, 95, 561, -455, - 115, 538, 538, -735, -427, -736, -273, -427, -272, 11, - -238, -242, -245, -249, -685, -251, 65, 615, 737, 622, - 738, 745, 279, 434, 496, 309, 280, -614, 281, 578, - 277, 360, 458, 305, 382, 389, 102, 187, 733, -255, - -256, -257, 261, 262, 263, 73, 266, 264, 70, 35, - 36, 37, -330, -1, 129, 780, -494, -494, -6, 783, - -6, -494, -467, -467, 177, -337, -341, -338, -340, -339, - 769, -343, -342, 211, 212, 173, 215, 217, 222, 218, - 219, 220, 221, 223, 224, 225, 226, 227, 230, 231, - 232, 233, 234, 235, 228, 34, 229, 295, 207, 208, - 209, 210, -346, 194, 213, 625, 254, 195, 255, 196, - 256, 197, 257, 171, 172, 258, 198, 201, 202, 203, - 204, 200, 236, 237, 238, 239, 240, 241, 242, 243, - 245, 244, 246, 247, 248, 249, 250, 251, 252, 253, - 176, -298, 96, 35, 90, 176, -330, 96, -735, -272, - -273, -278, -262, 19, -330, -321, 176, 781, -443, -467, - 515, 132, -118, 81, -118, 514, 81, -118, 514, 273, - -688, -689, -690, -692, 273, 514, 513, 274, 344, -141, - 176, 317, 19, -474, -474, -467, 87, -299, -300, -330, - -332, -330, -719, -718, 35, 622, -303, 26, 560, 740, - 742, 538, 748, 757, 758, 759, 86, -479, 140, 144, - -479, -423, 20, -423, 26, 26, 307, 307, 307, -479, - 347, -747, -748, 19, 142, -477, -748, -477, -477, -479, - -749, 280, 548, 46, 308, 307, -275, -276, 24, 90, - -275, 542, 538, -577, 543, 544, -481, -748, -480, -479, - -479, -480, -479, -479, 388, -479, 35, 383, 384, 278, - 281, 578, 382, 728, -747, -747, 34, 34, -528, 309, - -555, -526, 39, 86, 177, 282, 177, 86, 90, 459, - 434, 496, 460, 578, 278, 473, 281, 309, 474, 434, - 496, 278, 281, 578, 309, 434, 278, 281, 496, 309, - 474, 434, 537, 538, 281, 30, 464, 467, 468, 538, - -640, 574, -330, 177, 121, 118, 120, -494, 139, -509, - 132, 133, 134, 135, 136, 137, 138, 146, 145, 158, - 151, 152, 153, 154, 155, 156, 157, 147, 148, 149, - 150, 142, 122, 161, 778, 140, 144, 141, 124, 119, - 164, 163, -242, -494, -502, 65, -492, -492, -492, -492, - -492, -467, -594, -499, -494, 90, 90, 90, 90, 90, - 176, 109, 96, 90, -494, 90, 90, 90, 90, 90, - 90, 90, 90, 90, 90, 90, 90, 90, -633, 90, - 90, -506, -507, 90, 90, -487, -443, 90, 96, 96, - 90, 90, 90, 96, 90, 90, 90, -507, -507, 90, + 125, 284, 720, -470, 453, 721, 723, 722, 93, 101, + -463, -465, 764, 536, 299, 457, 463, 717, 718, 767, + 770, 620, 622, 317, 637, 638, 639, 640, 641, 642, + 643, 644, 646, 647, 648, 649, 650, 651, 652, 695, + 696, 662, 663, 653, 654, 655, 656, 657, 658, 659, + 660, 664, 665, 666, 667, 668, 669, 670, 671, 672, + 673, 674, 675, 676, 677, 592, 593, 697, 699, 700, + 701, 702, 645, 682, 690, 691, 692, 775, 776, 434, + 435, 628, 714, 773, 311, 335, 490, 341, 348, 415, + 180, 198, 194, 223, 213, 421, 477, 367, 743, 744, + 366, 621, 189, 315, 353, 316, 100, 183, 575, 115, + 548, 519, 186, 373, 376, 374, 375, 330, 332, 334, + 447, 337, 336, 338, 340, 619, 371, 437, 209, 203, + 329, 313, 201, 318, 422, 43, 319, 413, 412, 228, + 320, 321, 632, 544, 433, 550, 345, 56, 517, 202, + 333, 547, 713, 236, 240, 244, 245, 246, 247, 248, + 249, 250, 251, 252, 253, 566, 419, 400, 401, 402, + 403, 567, 424, 478, 171, 172, 552, 742, 749, 750, + 751, 753, 754, 755, 752, 418, 569, 423, 227, 230, + 231, 232, 233, 234, 235, 291, 409, 410, 425, 426, + 427, 428, 429, 431, 432, 46, 630, 303, 570, 238, + 760, 217, 226, 221, 578, 349, 347, 414, 225, 197, + 220, 314, 782, 765, 69, 242, 241, 243, 513, 514, + 515, 516, 322, 323, 451, 565, 745, 746, 216, 204, + 438, 190, 25, 573, 298, 549, 464, 377, 51, 378, + 324, 342, 350, 372, 237, 239, 305, 310, 365, 420, + 631, 521, 522, 309, 479, 557, 558, 346, 571, 200, + 302, 331, 297, 574, 761, 747, 191, 781, 466, 325, + 184, 339, 568, 763, 577, 68, 166, 196, 187, 737, + 738, 288, 698, 181, 307, 312, 715, 762, 326, 327, + 328, 352, 351, 343, 188, 218, 304, 224, 207, 195, + 219, 182, 306, 576, 167, 711, 436, 500, 215, 212, + 308, 480, 281, 716, 572, 551, 185, 504, 169, 210, + 354, 705, 706, 707, 710, 452, 408, 355, 356, 208, + 295, 542, 543, 359, 510, 395, 484, 520, 491, 485, + 259, 260, 363, 554, 556, 229, 708, 379, 380, 381, + 546, 382, 384, 385, 390, 456, 60, 62, 102, 105, + 104, 768, 769, 67, 32, 442, 445, 482, 783, 486, + 397, 712, 629, 394, 398, 399, 446, 28, 502, 468, + 506, 505, 52, 53, 54, 57, 58, 59, 61, 63, + 64, 55, 618, 461, 475, 579, 48, 50, 471, 472, + 30, 448, 501, 524, 393, 503, 535, 49, 533, 534, + 555, 29, 450, 449, 66, 47, 509, 511, 512, 357, + 391, 459, 726, 580, 454, 470, 474, 455, 396, 444, + 476, 71, 467, 727, 462, 460, 777, 778, 392, 633, + 634, 404, 661, 439, 518, 615, 614, 613, 612, 611, + 610, 609, 608, 360, 361, 362, 487, 488, 489, 499, + 492, 493, 494, 495, 496, 497, 498, 538, 539, 728, + 729, 559, 561, 562, 626, 563, 560, 276, 772, 771, + 440, 441, 279, 731, 732, 103, 733, 735, 734, 31, + 736, 759, 756, 757, 758, 636, 564, 623, 739, 625, + 624, 683, 684, 685, 686, 687, -554, -552, -470, 621, + 317, 764, 717, 718, 463, 620, 622, 457, 436, 767, + 770, 58, 461, 299, 360, 361, 362, 536, 434, -318, + -470, 278, 771, -97, -18, -17, -9, -627, -104, -241, + -242, -753, 265, 267, 472, -333, 278, -470, -479, 26, + 517, -118, 518, 273, 274, 90, 81, -470, -10, -132, + -8, -143, -95, -236, -688, 523, -477, -470, 360, 360, + 626, -477, 278, 278, 741, 522, 563, 626, 742, 749, + 760, 558, 447, 104, 105, 737, 738, 30, 278, 458, + 305, 556, 554, 555, 559, 560, 561, 562, -76, -639, + -615, 551, 642, 550, -483, 543, 549, 541, 553, 544, + 435, 385, 382, 635, 384, 389, 268, 731, 617, -458, + 484, 520, 579, 580, 459, 521, 566, 568, 545, 115, + 214, 211, -472, 309, 498, -470, -616, 284, -558, -529, + 310, -557, -531, -560, -532, 35, 268, 270, 269, 635, + 306, 18, 461, 280, 16, 15, 462, 292, 28, 29, + 31, 17, 463, 465, 32, 466, 469, 470, 471, 45, + 475, 476, 299, 93, 101, 96, 683, 684, 685, 686, + 687, 317, 278, -314, -470, -505, -497, 122, -500, -492, + -493, -495, -448, -660, -490, 90, 151, 152, 159, 123, + 161, 785, -494, -597, 39, 125, 641, 645, 682, 590, + -440, -441, -442, -443, -444, -445, 627, -470, -661, -659, + 96, 106, 108, 112, 113, 111, 109, 174, 205, 110, + 97, 175, -242, 93, -682, 651, 657, -464, 674, 699, + 700, 701, 702, 673, 65, -623, -637, 277, -635, 173, + 211, 295, 207, 16, 157, 510, 208, 690, 691, 692, + 648, 670, 592, 593, 697, 652, 775, 776, 662, 677, + 643, 644, 646, 638, 639, 640, 642, 653, 655, 669, + -638, 665, 675, 676, 661, 693, 694, 756, 695, 696, + 678, 679, 680, 689, 688, 681, 683, 684, 685, 686, + 687, 735, 95, 94, 668, 667, 654, 649, 650, 656, + 637, 647, 658, 666, 671, 672, 445, 115, 446, 447, + 582, 437, 84, 448, 284, 517, 74, 449, 450, 451, + 452, 453, 589, 454, 781, 75, 455, 444, 299, 500, + 456, 210, 229, 595, 594, 596, 586, 583, 581, 584, + 585, 587, 588, 659, 660, 664, -239, -241, -688, -242, + -168, -170, 703, -738, -278, -739, -430, 25, -740, 6, + 7, 8, 9, 175, -729, 519, 631, 96, 582, 278, + 353, 434, 19, 741, 389, 619, 741, 389, 619, 367, + 185, 182, -544, 185, 121, 191, 190, 282, 185, -544, + -470, 188, 741, 187, 737, 742, 749, 626, 363, -519, + -215, 434, 500, 382, 102, 309, -523, -520, -617, 357, + 353, 279, 118, -216, 289, 430, 288, 116, 582, 277, + 473, 348, 60, 62, 35, 48, -262, 51, 283, 42, + -333, -690, 616, -689, -470, -698, -699, 265, 266, 267, + 42, 742, 749, 279, 281, 278, 737, 626, 309, 434, + 582, 500, 102, 382, 278, -698, 760, 182, 566, 568, + 519, 309, 498, 44, -551, 510, -550, -552, 567, 578, + 94, 95, 565, -458, 115, 542, 542, -738, -430, -739, + -273, -430, -272, 11, -238, -242, -245, -249, -688, -251, + 65, 619, 741, 626, 742, 749, 279, 434, 500, 309, + 280, -617, 281, 582, 277, 360, 458, 305, 382, 389, + 102, 187, 737, -255, -256, -257, 261, 262, 263, 73, + 266, 264, 70, 35, 36, 37, -333, -1, 129, 784, + -497, -497, -6, 787, -6, -497, -470, -470, 177, -340, + -344, -341, -343, -342, 773, -346, -345, 211, 212, 173, + 215, 217, 222, 218, 219, 220, 221, 223, 224, 225, + 226, 227, 230, 231, 232, 233, 234, 235, 228, 34, + 229, 295, 207, 208, 209, 210, -349, 194, 213, 629, + 254, 195, 255, 196, 256, 197, 257, 171, 172, 258, + 198, 201, 202, 203, 204, 200, 236, 237, 238, 239, + 240, 241, 242, 243, 245, 244, 246, 247, 248, 249, + 250, 251, 252, 253, 176, -298, 96, 35, 90, 176, + -333, 96, -738, -272, -273, -278, -262, 19, -333, -324, + 176, 785, -446, -470, 519, 132, -118, 81, -118, 518, + 81, -118, 518, 273, -691, -692, -693, -695, 273, 518, + 517, 274, 344, -141, 176, 317, 19, -477, -477, -470, + 87, -299, -300, -333, -335, -333, -722, -721, 35, 626, + -303, 26, 564, 744, 746, 542, 752, 761, 762, 763, + 86, -482, 140, 144, -482, -426, 20, -426, 26, 26, + 307, 307, 307, -482, 347, -750, -751, 19, 142, -480, + -751, -480, -480, -482, -752, 280, 552, 46, 308, 307, + -275, -276, 24, 90, -275, 546, 542, -580, 547, 548, + -484, -751, -483, -482, -482, -483, -482, -482, 388, -482, + 35, 383, 384, 278, 281, 582, 382, 732, -750, -750, + 34, 34, -531, 309, -558, -529, 39, 86, 177, 282, + 177, 86, 90, 459, 434, 500, 460, 582, 278, 473, + 281, 309, 474, 434, 500, 278, 281, 582, 309, 434, + 278, 281, 500, 309, 474, 434, 541, 542, 281, 30, + 464, 467, 468, 542, -643, 578, -333, 177, 121, 118, + 120, -497, 139, -512, 132, 133, 134, 135, 136, 137, + 138, 146, 145, 158, 151, 152, 153, 154, 155, 156, + 157, 147, 148, 149, 150, 142, 122, 161, 782, 140, + 144, 141, 124, 119, 164, 163, -242, -497, -505, 65, + -495, -495, -495, -495, -495, -470, -597, -502, -497, 90, + 90, 90, 90, 90, 176, 109, 96, 90, -497, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, -636, 90, 90, -509, -510, 90, 90, -490, + -446, 90, 96, 96, 90, 90, 90, 96, 90, 90, + 90, -510, -510, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, - 90, 90, 90, 90, 90, 90, 90, 90, 90, -735, - -241, -273, 177, 90, -272, -273, -279, 23, -278, -243, - -242, -247, -251, -494, -738, 723, 35, 36, 35, 36, - 35, 36, 35, 36, 90, 106, 764, 259, -288, -467, - -289, -467, -176, 19, 781, -467, 733, -718, 383, 622, - 622, 383, 622, 268, 18, 371, 58, 372, 567, 14, - 189, 190, 191, -467, 188, 282, -467, -514, 284, -514, - -514, 739, 515, -514, -313, -467, 305, 458, 281, 281, - -216, -514, 19, -514, -514, -514, -514, 280, -514, 278, - 278, 278, -514, 585, 132, 132, 63, -626, -629, -625, - -628, 42, 126, -629, -293, 301, -262, -262, -330, 177, - -687, -284, 90, -697, 193, -265, -264, -259, -261, -426, - -428, -263, 90, -330, -242, -467, 739, 515, -613, -613, - -330, -613, -467, 284, -529, -613, 613, -456, -467, -613, - -613, -613, -409, -410, -330, -698, 283, 759, -732, -731, - 565, -734, 567, 182, -549, 182, -549, 93, -528, 309, - 309, 177, 132, 26, -550, 132, 143, -549, -549, -550, - -550, -378, 44, -466, 173, -467, 96, -378, 44, -729, - -728, -330, -273, -243, -242, -247, -251, -277, -276, -278, - -246, -243, -247, -242, 65, 23, 91, 91, -273, -273, - -427, -168, 622, -613, -613, 739, 515, -613, -613, -613, - -613, -613, 278, -613, -613, -613, -474, -613, -315, 284, - -613, 383, -613, -613, -613, -252, -254, 153, -494, -467, - -257, -3, -180, -179, 126, 127, 129, 717, 453, 716, - 720, 713, -549, 44, -607, 167, 166, 90, -601, -603, - 90, -602, 90, -602, -602, -602, 212, 215, -601, -601, - -602, -602, -602, -602, -602, -602, 90, 90, -604, 90, - -604, -604, -601, -605, 206, 90, -605, -606, 90, -606, - -605, -467, -581, 14, -500, -502, -467, 282, 42, -273, - -171, -278, 42, -276, -279, -285, 301, 102, -322, 744, - -467, 208, 187, 732, 38, 176, 106, 96, -141, -118, - 81, -141, -118, -118, 91, 177, -691, 112, 113, -693, - 96, 227, 218, -467, -139, 96, -656, -7, -13, -117, - -8, -143, -10, -12, -55, -95, 34, -145, -135, -230, - -236, -471, 292, 616, 618, -659, -657, -301, 177, 432, - 90, -302, 177, 540, 26, -467, -275, 627, -157, 26, - -479, 19, 142, -479, -479, 19, 142, -479, 309, -423, - -492, -492, -494, 434, 578, 278, -530, 309, -466, -747, - -479, -479, -457, -456, -481, -476, -481, -481, -423, -477, - -479, -479, -494, 153, -481, -477, -423, -467, 538, -423, - -423, -577, -456, -479, 96, -478, -467, -478, -514, -456, - -457, -457, 35, 505, 86, 19, -556, 278, 578, 458, - 305, 281, 434, -554, -535, -532, -530, -528, -531, -530, - -559, -443, 538, -172, 521, 520, 359, 19, -494, -494, - -494, -494, 111, 122, 161, 408, 112, 113, -489, -510, - 35, 355, 356, -490, -490, -490, -490, -490, -490, -490, - -490, -490, -490, -490, -490, -492, -492, -498, -508, -594, - 90, 142, 140, 144, 141, 124, 142, 140, 144, 141, - 124, -753, 27, -492, -492, -490, -490, -492, -335, -337, - 166, 167, -380, -466, 173, 91, 177, -494, -684, -683, - 126, -494, -494, -494, -494, -521, -523, -443, 90, -467, - -490, -680, -681, 593, 594, 595, 596, 597, 598, 599, - 600, 601, 602, 603, 449, 444, 450, 448, 437, 456, - 451, 452, 210, 610, 611, 604, 605, 606, 607, 608, - 609, -500, -500, -494, -680, -490, -500, -436, 36, 35, - -502, -502, -502, 91, -494, -694, 406, 405, 407, -444, - -467, -500, 91, 91, 91, 106, -502, -502, -500, -490, - -500, -500, -500, -500, -681, -681, -682, 295, 207, 209, - 208, -436, -494, -494, -436, -436, -436, 153, -502, -502, - -436, -436, -436, -436, 153, -436, -436, -436, -436, -436, - -436, -436, -436, 91, -436, -436, -436, -436, -436, 91, - 91, 91, 91, -494, 91, -494, -494, -494, -494, -494, - 153, -502, -273, -735, -277, -170, -638, -637, -494, 44, - -171, -278, -276, -171, 674, -279, -739, 725, 90, -443, - -727, 96, 96, 781, -176, 176, 19, 278, -176, 176, - 733, 187, -176, 578, 19, -467, 96, 106, -467, 96, - 106, 278, 578, 278, 578, -330, -330, -330, 568, 569, - 186, 190, 189, -467, 188, -467, -467, 122, 161, -467, - -467, -514, -514, -467, 38, -315, -304, -467, -514, -514, - -702, -467, 97, 96, -536, -533, -530, -467, -467, -526, - -467, -456, -514, -514, -514, -330, -389, 57, 58, 59, - -530, -217, 60, 61, -236, -625, -627, -628, 128, -330, - -494, -627, -623, 65, -236, 90, 34, 90, -293, -293, - -686, 38, -283, -467, -698, 87, -429, -430, -431, -432, - -434, -435, -433, 72, 76, 78, 82, 73, 74, 75, - 541, 79, 84, 773, 77, -465, -470, 38, -467, 96, - -465, -242, -267, -266, -265, 781, -465, 90, -467, -467, - -330, -330, -403, -411, -408, -404, -412, 301, 269, 275, - 442, 443, 271, 11, 270, -420, 348, -515, 586, -384, - -385, 81, 45, -387, 299, 482, 478, 779, 311, 315, - 100, 316, 515, 317, 280, 319, 320, 321, 336, 338, - 291, 322, 323, 324, 506, 325, 181, 337, 326, 327, - 328, 460, -379, 6, 390, 44, 55, 56, 530, 529, - 629, 14, 312, -467, 485, 618, 34, 39, 271, 275, - 270, -702, -700, 34, -467, 34, -536, -530, -467, -467, - 177, 282, -265, -267, -549, 177, 566, 568, 569, -732, - -550, -732, -550, 282, 35, 505, -553, 505, 35, -526, - -547, 562, 564, -542, 96, 506, -531, -552, 86, 173, - -637, -550, -550, -552, -552, 163, 177, -730, 567, 568, - 265, -277, -168, -271, -270, -494, -277, -277, -250, -243, - -251, -247, -242, 106, -720, -718, -467, 622, -467, -613, - -613, -332, -702, -535, -526, -467, -613, -332, -469, -469, - -304, 39, -467, -613, -467, -467, -467, -171, 177, -468, - -467, 38, 96, 176, -181, -179, 128, -494, -6, 716, - -494, -6, -6, -494, -6, -494, -611, 169, -337, 106, - 106, -446, 96, -446, 106, -605, 106, 106, 632, 91, - 96, 96, -277, -279, 700, -660, -656, -279, -171, -630, - 65, -236, 90, 34, 90, -613, 187, 208, 743, -321, - 132, 132, 132, 27, -467, 26, -141, -118, -689, 176, - -548, 514, 177, -300, -283, -330, 631, 106, -159, 24, - -467, -423, -467, 739, -423, -423, -467, 739, 741, -423, - -529, -467, -467, -467, -527, 87, -467, 784, 94, -457, - -423, -423, -481, -423, -423, 177, 25, 91, -479, -481, - -481, -321, -477, -321, 176, -321, -456, -556, -534, -531, - -558, 153, -467, -543, 177, 14, 282, -715, -714, 497, - 91, 177, -641, 283, 585, 96, 781, 513, 259, 260, - 96, 111, 408, 112, 113, 111, 408, 112, 113, -594, - -502, -498, -492, -492, -490, -490, -498, -492, -492, -490, - -490, 90, -496, 296, -496, 121, -345, 172, 171, -345, - -494, 782, -493, -683, 128, -494, 38, 177, 38, 177, - 87, 177, 91, -601, -494, 176, 177, 91, 91, 19, - 19, 142, 91, -494, 91, 91, 91, 91, 19, 19, - -494, 91, 176, 91, 91, 91, 91, 87, 91, 177, - 91, 91, 91, 91, 177, 177, 177, -502, 91, 91, - -502, -494, -502, 91, 91, 91, -494, -494, -494, -502, - 91, -494, -494, -494, -494, -494, -494, -494, -494, 770, - -494, -494, -502, -494, -494, -566, 533, -566, -566, -566, - 91, -566, 91, 177, 91, 177, 91, 91, 177, 177, - 177, -277, -273, 177, 91, -279, -279, 14, -171, -740, - 724, 90, 106, 177, 765, -450, -449, 96, -177, 282, - -467, 733, -467, -177, -467, -467, 132, -177, -467, 733, - 96, 96, -330, -456, -330, -456, 624, 42, 42, 187, - 191, 191, 190, -467, 96, 39, 39, 26, 26, 346, - -467, -467, -152, 619, -314, 90, 90, 176, -330, -330, - -704, 483, -467, -716, 177, 44, -714, 578, -213, 359, - -518, 87, -226, 366, 19, -330, -330, -330, -344, 38, - -236, -626, 65, 90, 127, -236, -540, -539, 86, -631, - -503, -678, 699, -292, 91, -280, -467, -676, -677, -280, - -286, -294, -467, -623, -623, 90, 91, 177, 19, -258, - -331, -467, -265, -264, -264, -264, -264, -264, -264, -264, - 72, 83, 72, -281, 90, 72, 77, 72, 77, 72, - 77, 72, -431, 72, 72, 74, 83, -284, -470, 177, - 91, 93, -725, -724, -723, -721, 80, 283, 81, -500, - 34, 34, 56, 55, -600, 38, -284, 177, 23, 411, - -464, -406, 286, 280, 344, 287, 301, -329, -464, -326, - -328, -484, -327, 289, 430, -672, 287, 285, 116, 290, - 344, 117, 280, -464, -464, 286, -388, 282, 38, 23, - 301, -405, 280, 117, -467, 286, 290, 287, 285, -463, - 132, -455, 163, 282, 46, 460, -463, 630, 301, -463, - -463, -463, -463, -463, -463, -463, -463, 318, 318, -463, - -463, -463, -463, -463, -463, -463, -463, -463, -463, -463, - 182, -463, -463, -463, -463, -463, -463, 90, 313, 314, - 346, 619, 126, 632, 621, -529, 282, 553, 553, -705, - 483, 34, 440, 440, 441, -716, 436, 45, 34, -227, - 434, -410, -407, -478, 34, 34, -550, -731, -733, 570, - 567, 573, -552, -552, 106, 282, 90, 132, -552, -552, - 44, -466, -728, 574, 568, -279, 177, -268, 40, 41, - 91, 91, -311, 735, -467, -467, 86, -332, -616, 339, - 340, 90, -315, 96, 19, -311, -422, -421, 19, -254, - -467, 96, -467, 153, 129, -6, 127, -185, -184, -183, - 130, 713, 720, 129, 129, 129, 91, 91, 91, 91, - 177, 91, 91, 91, 177, 91, 177, 106, 761, -644, - 543, -279, -171, 96, 177, -171, -253, 768, -631, -292, - 91, -676, -286, -467, 96, 106, 96, 38, -225, 93, - 101, 96, -322, -494, -467, 96, -494, 208, 176, 515, - -467, -657, 91, 106, -479, -467, -479, 176, -467, -222, - -224, -467, 96, -467, -526, -466, -479, -423, -494, -494, - 547, 546, -423, -479, -479, -481, -467, -321, -558, 177, - 282, 176, 176, -532, 463, -534, 23, 14, -443, 42, - -450, 132, 781, -467, 91, -496, -496, 121, -496, -496, - 121, -492, -492, -489, 91, 129, -494, 127, -335, -494, - -335, -336, -342, 227, 173, 211, 295, 210, 209, 207, - 166, 167, -378, -523, 624, -268, 91, -467, -502, -494, - -494, -490, 91, -494, -494, 19, -467, -378, -490, -494, - -494, -494, -273, -274, 770, -274, -273, 91, 91, -565, - -566, -565, -274, 91, 91, 91, 91, -565, 91, 91, - 91, 91, 91, 91, 91, 91, 21, 91, 91, 91, - 91, 177, -467, 90, -566, -751, 777, -494, -751, -494, - -751, -751, -494, 106, 108, 106, 108, -279, -277, -637, - -171, -171, 464, 90, 301, 177, 106, 96, 782, 177, - 132, 434, -467, 19, 176, 96, -467, 96, 19, 278, - -467, 19, 19, -330, -330, -330, 191, 96, -717, 353, - 434, 578, 278, 434, 353, 578, 278, -582, 106, -354, - 14, -358, 14, -153, 126, 96, 471, -316, -317, -318, - -319, -320, 142, 178, 179, -305, -306, -307, -308, -337, - -443, 769, 212, 215, 217, 218, 219, 220, 221, 223, - 224, 225, 226, 227, 230, 231, 232, 233, 234, 235, - 228, 229, 295, 207, 208, 209, 210, 194, 213, 625, - 195, 196, 197, 171, 172, 198, 201, 202, 203, 204, - 200, 236, 237, 238, 239, 240, 241, 242, 243, 245, - 244, 246, 247, 248, 249, 250, 251, 252, 253, -467, - -284, -284, -707, 545, 485, 495, -463, 382, -486, -485, - 436, 45, -618, 506, 491, 492, -533, 309, -456, 153, - -713, 103, 132, 86, 394, 398, 400, 402, 401, 399, - 395, 396, 397, -512, -513, -511, -515, -456, 96, -700, - 90, -237, -221, -220, 140, -226, 366, 19, -236, 65, - 283, 585, 90, -353, 321, 90, -595, 379, -337, 90, - -292, -626, -253, 43, 177, 90, 91, 177, 65, 176, - 177, 132, 91, 177, 91, 177, 132, -253, -253, -539, - -1, -467, -330, -258, -467, 19, 177, -699, 176, 86, - -296, -295, 86, 87, -296, -296, -295, -295, 72, -282, - 96, 72, 72, 72, 72, 77, -266, -265, -723, -722, - 26, -672, -672, -672, 91, -355, 90, -356, -223, -467, - 96, -359, 90, -360, -361, -467, 96, -595, -337, 38, - -404, 275, 269, 270, -562, 346, 347, -563, -584, 349, - -467, -443, -467, -467, -467, -586, 90, -334, -443, -327, - -671, -672, -671, -514, -467, 117, -671, 117, 90, -334, - -443, -443, -407, -415, -414, -443, -418, 35, -419, -467, - -467, -467, -467, 117, -467, 117, -383, 44, 52, 53, - 54, -463, -463, 214, -386, 44, 505, 507, 508, -418, - 106, 106, 106, 106, 106, 96, 96, 96, -463, -463, - 106, 96, -470, 96, -673, 190, 48, 49, 106, 106, - 106, 106, 44, 96, -391, 44, 329, 333, 330, 331, - 332, 96, 106, 44, 106, 44, 106, 44, -467, 90, - -674, -675, 96, -582, 96, 90, 106, 96, 271, -529, - 96, 86, -707, -463, 440, -549, 132, 132, -486, -709, - 100, 486, -709, -712, 359, -229, 578, 35, -287, 275, - 270, -700, -538, -537, -443, -538, -552, 567, 571, 572, - -534, -482, 96, -542, -171, -270, -269, 47, -330, -616, - -305, -467, -423, -267, 176, 125, -6, -181, -183, -494, - -6, -494, 716, 453, 717, 96, 106, 106, 569, -652, - 527, 522, 524, -171, -653, 513, -656, -252, 91, 65, - 91, 27, 782, 782, 782, 782, 96, -467, 106, -423, - -479, -423, -222, -479, -479, 142, -423, -321, -423, -423, - -479, 19, -531, -526, 153, 153, -467, 464, -543, 96, - 484, 96, 278, 782, 96, -450, -489, -489, 91, -494, - 91, 38, 91, 91, -602, -602, -601, -604, -601, -345, - -345, 91, 90, -268, 91, 91, 26, 91, 91, -565, - 91, 91, -494, 176, 91, 91, 177, 177, 91, -621, - 587, -565, 21, -565, -622, 659, -565, -565, -565, -565, - -565, -565, -565, -565, -565, -565, -565, -565, -565, -565, - -565, 90, -565, -565, -565, -565, -494, -567, -571, -467, - -566, 47, 91, 177, -566, 91, 177, -566, -566, 91, - 528, 730, 730, 528, 730, 730, -171, -279, -502, -741, - 67, 722, 66, 505, 111, 349, 91, -680, 177, -458, - 354, -458, -449, 96, -467, 96, 733, -467, 782, 782, - 733, -467, 96, -330, -456, -290, 544, -233, 126, -234, - 124, 46, 96, -467, 19, -467, -467, 346, -467, 346, - -467, -467, 96, 90, 90, -158, 632, 90, -155, 620, - 96, 91, 177, -443, 91, 177, -337, 38, 38, -708, - 100, -703, 96, -467, 97, -467, -709, 175, 438, 44, - 487, 488, 503, 433, 106, 106, 493, -701, -467, -228, - 278, 434, -228, -711, 56, 132, 96, -330, -511, -455, - 163, 320, -321, -467, 382, -323, -324, -325, -334, -326, - -328, -237, 38, -330, -330, 96, -168, -323, -463, -323, - -596, 381, 23, 106, 152, -502, 91, 117, -503, -639, - -638, 65, -236, -280, -631, -467, -677, -637, -467, -467, - -494, -253, 91, -285, 87, 176, -267, -331, -467, 153, - -494, -494, 90, -260, 774, 91, 72, 782, 90, 72, - 11, 21, 177, -355, 132, 177, -359, 132, -596, -236, - -579, 350, 90, -577, 90, -577, 117, 395, 398, 400, - 402, 401, 430, 34, 270, -416, 398, 392, 393, -544, - 345, 122, 161, -544, -587, -585, 301, -413, 48, 50, - -337, -669, -467, -669, -667, -669, -467, -667, -667, -514, - -494, -413, -334, 282, 177, -268, 177, -467, -378, -378, - 34, 96, 96, -332, 91, 177, 132, 96, -155, -154, - -494, -238, -242, 282, 86, 278, -708, -703, 132, -550, - 96, 96, -709, 96, 96, -713, 132, -333, 278, -456, - 177, -287, -287, -423, 19, 177, 132, -423, 91, -297, - 26, 45, 48, 49, 91, 382, -425, 21, 153, 129, - 127, 129, 129, -467, 91, 91, -608, 701, -648, -650, - 522, 23, 23, -297, -654, 706, 96, 65, -236, -631, - 208, 96, 782, -423, -479, -423, -423, 739, -423, -526, - -543, 506, -330, 177, 782, -335, -397, 96, 97, -467, - -494, 91, -467, -494, -494, 91, 96, 90, 91, 96, - -272, 91, 91, -505, -504, 301, -751, -494, -751, -494, - -752, 19, 91, 177, 91, 91, 91, 177, 91, 91, - -297, -171, 91, 177, 91, -680, -459, 208, 96, -459, - -467, -467, 19, -468, -231, 282, -321, -235, 377, 90, - 373, -233, 187, 90, 96, -467, 19, -467, -582, 346, - -582, 346, 278, -467, -311, -355, -359, -156, 621, 106, - -154, 96, -519, 626, -318, -337, 276, -307, 44, -237, - -237, 96, -706, 497, -583, 387, 106, 44, 106, 175, - 489, -619, -214, 100, -332, 35, -287, -214, -710, 100, - 132, 781, 90, -463, -463, -463, -231, 382, -467, 91, - 177, -237, -232, 54, -467, -273, 91, 738, 91, -597, - 300, 106, 152, 106, 152, 106, 91, 65, 17, 283, - 91, -631, 176, 132, -465, -267, -467, -423, -699, 176, - -105, -106, 126, -283, -491, 175, -668, -467, 285, 23, - 23, -356, 91, -224, -360, 91, -362, -467, 96, -597, - -564, 351, 106, -490, 90, -490, 90, -578, 348, 90, - -524, -524, -524, -524, -524, 44, -416, 44, -417, 417, - 345, 345, 91, 177, -467, -443, -350, -349, -347, 111, - 122, 161, 44, 478, -348, 100, 746, 747, 163, 334, - 337, 336, 312, 335, -402, -483, 86, 694, 481, 392, - 393, -515, 709, 38, 285, 116, 117, 465, -484, 90, - 90, 90, 87, 354, 90, 90, -669, 91, -413, -443, - -414, -467, 163, -378, 91, -675, 96, 91, -529, 278, - -467, -706, 96, -552, -711, 96, -214, -332, -700, -273, - -267, -537, -637, -253, 17, 68, 142, -467, -424, 22, - 23, 284, -6, 717, 453, -393, 702, 96, 23, 96, - -646, 96, -644, 96, -631, 96, -423, -467, -174, -390, - -455, 317, 91, -396, 142, 14, 91, 91, 91, -274, - -272, -565, 91, -565, -273, 23, -566, 91, -566, 91, - -751, 48, 96, 96, -297, -494, 91, 96, 96, 96, - 733, 434, -231, 38, 471, 24, 638, 378, -283, 374, - 375, 376, -467, 96, -502, -238, 781, 382, -467, 19, - 96, -582, 96, -582, -467, 346, 91, 91, 38, 96, - 91, 96, 96, -309, -337, -487, -218, 14, -218, 23, - 14, 175, 437, 44, 106, 44, 490, 96, -228, 132, - 112, 113, -451, -452, 96, -521, -378, -380, 96, -467, - -351, -237, -221, -220, -352, -420, -515, -325, -231, 30, - 382, -277, -173, -353, -357, -363, -369, -370, -172, 321, - -354, -351, -598, 181, 106, 152, 106, 106, 90, -538, - -467, -494, -423, -423, -253, 768, -106, -108, 122, 161, - -467, 91, 91, 177, -598, -586, 23, 91, -559, 91, - -559, 90, 132, -490, -525, 291, 409, 410, 100, 14, - 392, 393, 414, 413, 412, 418, 419, 423, 424, 420, - 422, 421, 425, 429, 426, 427, 428, 431, 415, 416, - 58, 417, 437, 448, 444, -490, -524, 132, -585, -588, - 65, -347, 111, 111, -490, 96, 96, 96, -380, -381, - 44, 333, 329, 132, 132, -382, 44, 313, 314, -392, - 90, 344, 17, 106, 214, 710, 90, 117, 117, -330, - -521, -521, -521, -670, 394, 395, 396, 404, 398, 399, - 397, 400, 401, 402, 403, -670, -521, -521, 90, -545, - -544, -463, 163, -467, 176, -710, -275, -423, 68, -569, - 775, -494, -502, 752, 754, 755, -467, -467, -447, 703, - 106, 96, 524, -652, -479, -609, 704, -642, -577, -378, - 132, 91, 79, 625, 403, 627, -565, 91, -565, -573, - -572, -576, 528, 346, 536, -502, -751, -751, -566, 91, - 91, 91, -467, -467, -330, 96, 106, 91, 121, 121, - 91, 91, -454, -453, 96, -467, 382, -467, -311, 96, - -311, 96, 346, -582, -2, 626, -219, 64, 574, 96, - 97, 484, 96, 97, 106, 437, -214, 96, 782, 177, - 132, 91, -583, -560, 301, -237, 38, 177, -420, -455, - -467, -174, -463, -560, -615, 190, 380, 14, 106, 152, - 106, -502, -273, -253, -252, -107, 121, -108, -108, -467, - 285, -599, 190, 380, -563, 91, 91, 91, -559, 106, - 91, -463, -463, 96, 96, 391, -463, -463, -463, -463, - -463, -463, 90, 96, 96, -463, -463, -463, -463, -463, - -463, 132, 132, -463, -463, -463, 112, 113, -593, -589, - 90, -590, -420, 303, 142, 96, 96, 106, 90, -632, - 34, 38, -494, -522, 90, 91, 91, 91, 91, 91, - -521, -378, -463, 176, -467, -253, -253, 69, -570, -568, - -467, -617, 14, 753, 90, 90, 90, 23, -608, -423, - -610, 705, 96, -651, 527, -645, -643, 522, 523, 524, - 525, 96, 626, 69, 69, 628, -575, 124, 489, 493, - -488, 97, -491, 106, 108, 205, -566, -566, 96, -467, - 96, 782, 177, 132, -467, 382, -311, -311, -582, 96, - -312, -467, 344, 506, -452, 96, -524, -561, 353, 23, - -237, -420, -463, -583, 745, 749, -377, 751, 750, 62, - -561, 380, 106, 152, 106, 91, -275, 127, -494, -107, - -107, 380, -580, 352, 91, 106, 106, -467, 106, 106, - 106, 106, 106, 106, -559, 106, 106, 106, 106, 106, - 106, 112, 113, 112, 113, 106, 106, 106, -593, -590, - -592, -591, 351, 304, 90, 91, -494, -506, -463, 90, - 91, -395, -394, 623, -521, -524, 87, -524, -524, 87, - -524, 87, -524, 87, 91, -378, -467, 177, 38, 755, - 90, -502, -502, -448, -467, -646, -393, 96, -655, 283, - -649, -650, 526, -643, 23, 524, 23, 23, -175, 177, - 69, -574, -575, 493, -488, 97, -491, 699, 534, 534, - 534, 534, -233, -234, -233, -234, -311, -453, 96, -467, - 96, -311, -310, 38, 529, 464, 23, -562, -378, -358, - -364, 14, -374, 14, -371, 14, 106, -253, 17, 18, - 127, 127, 106, 91, 91, 177, -467, 300, 90, -501, - -495, -494, 300, 91, -378, -494, -546, 712, 711, -401, - -399, -400, 86, 541, 342, 343, 91, -670, -670, -670, - -670, -402, -568, 90, -169, 90, 91, 91, 91, 177, - -447, -663, 90, 106, -648, -647, -649, 23, -646, 23, - -646, -646, 531, 14, 121, 535, 535, 535, 535, -233, - -233, -311, 96, -443, 90, -579, 90, 90, 90, 34, - 16, 16, -591, -589, -501, 91, 177, -544, 91, -400, - 86, -399, 86, 18, 17, -524, -524, -524, -524, -567, - 91, 177, -500, -467, -666, 34, 91, -662, -661, -444, - -656, 527, 528, 96, -646, 132, 627, -574, -744, -743, - 729, -559, -564, -365, -366, -367, -467, 96, -375, -376, - -367, -372, -373, -367, -538, 90, 65, 90, 65, 91, - -495, -546, -398, 339, 340, 34, 190, -398, 91, 90, - 91, -665, -664, -445, 91, 177, 96, 628, 96, 91, - -586, 91, 177, 132, 91, 177, 132, 91, 177, 132, - -291, -467, 90, -291, 90, 111, 44, 341, -500, 177, - 132, -661, -366, -368, -467, 96, -376, -368, -373, -368, - 91, 177, 176, -502, 91, -502, 91, -664, 44, -494, - 65, -467, -467, 91, 65, 91, 90, 176, 90, -502, - -467, -502, 91, 91, + 90, 90, 90, -738, -241, -273, 177, 90, -272, -273, + -279, 23, -278, -243, -242, -247, -251, -497, -741, 727, + 35, 36, 35, 36, 35, 36, 35, 36, 90, 106, + 768, 259, -288, -470, -289, -470, -176, 19, 785, -470, + 737, -721, 383, 626, 626, 383, 626, 268, 18, 371, + 58, 372, 571, 14, 189, 190, 191, -470, 188, 282, + -470, -517, 284, -517, -517, 743, 519, -517, -313, -470, + 305, 458, 281, 281, -216, -517, 19, -517, -517, -517, + -517, 280, -517, 278, 278, 278, -517, 589, 132, 132, + 63, -629, -632, -628, -631, 42, 126, -632, -293, 301, + -262, -262, -333, 177, -690, -284, 90, -700, 193, -265, + -264, -259, -261, -429, -431, -263, 90, -333, -242, -470, + 743, 519, -616, -616, -333, -616, -470, 284, -532, -616, + 617, -459, -470, -616, -616, -616, -412, -413, -333, -701, + 283, 763, -735, -734, 569, -737, 571, 182, -552, 182, + -552, 93, -531, 309, 309, 177, 132, 26, -553, 132, + 143, -552, -552, -553, -553, -381, 44, -469, 173, -470, + 96, -381, 44, -732, -731, -333, -273, -243, -242, -247, + -251, -277, -276, -278, -246, -243, -247, -242, 65, 23, + 91, 91, -273, -273, -430, -168, 626, -616, -616, 743, + 519, -616, -616, -616, -616, -616, 278, -616, -616, -616, + -477, -616, -318, 284, -616, 383, -616, -616, -616, -252, + -254, 153, -497, -470, -257, -3, -180, -179, 126, 127, + 129, 721, 453, 720, 724, 717, -552, 44, -610, 167, + 166, 90, -604, -606, 90, -605, 90, -605, -605, -605, + 212, 215, -604, -604, -605, -605, -605, -605, -605, -605, + 90, 90, -607, 90, -607, -607, -604, -608, 206, 90, + -608, -609, 90, -609, -608, -470, -584, 14, -503, -505, + -470, 282, 42, -273, -171, -278, 42, -276, -279, -285, + 301, 102, -325, 748, -470, 208, 187, 736, 38, 176, + 106, 96, -141, -118, 81, -141, -118, -118, 91, 177, + -694, 112, 113, -696, 96, 227, 218, -470, -139, 96, + -659, -7, -13, -117, -8, -143, -10, -12, -55, -95, + 34, -145, -135, -230, -236, -474, 292, 620, 622, -662, + -660, -301, 177, 432, 90, -302, 177, 544, 26, -470, + -275, 631, -157, 26, -482, 19, 142, -482, -482, 19, + 142, -482, 309, -426, -495, -495, -497, 434, 582, 278, + -533, 309, -469, -750, -482, -482, -460, -459, -484, -479, + -484, -484, -426, -480, -482, -482, -497, 153, -484, -480, + -426, -470, 542, -426, -426, -580, -459, -482, 96, -481, + -470, -481, -517, -459, -460, -460, 35, 509, 86, 19, + -559, 278, 582, 458, 305, 281, 434, -557, -538, -535, + -533, -531, -534, -533, -562, -446, 542, -172, 525, 524, + 359, 19, -497, -497, -497, -497, 111, 122, 161, 408, + 112, 113, -492, -513, 35, 355, 356, -493, -493, -493, + -493, -493, -493, -493, -493, -493, -493, -493, -493, -495, + -495, -501, -511, -597, 90, 142, 140, 144, 141, 124, + 142, 140, 144, 141, 124, -756, 27, -495, -495, -493, + -493, -495, -338, -340, 166, 167, -383, -469, 173, 91, + 177, -497, -687, -686, 126, -497, -497, -497, -497, -524, + -526, -446, 90, -470, -493, -683, -684, 597, 598, 599, + 600, 601, 602, 603, 604, 605, 606, 607, 449, 444, + 450, 448, 437, 456, 451, 452, 210, 614, 615, 608, + 609, 610, 611, 612, 613, -503, -503, -497, -683, -493, + -503, -439, 36, 35, -505, -505, -505, 91, -497, -697, + 406, 405, 407, -447, -470, -503, 91, 91, 91, 106, + -505, -505, -503, -493, -503, -503, -503, -503, -684, -684, + -685, 295, 207, 209, 208, -439, -497, -497, -439, -439, + -439, 153, -505, -505, -439, -439, -439, -439, 153, -439, + -439, -439, -439, -439, -439, -439, -439, 91, -439, -439, + -439, -439, -439, 91, 91, 91, 91, -497, 91, -497, + -497, -497, -497, -497, 153, -505, -273, -738, -277, -170, + -641, -640, -497, 44, -171, -278, -276, -171, 678, -279, + -742, 729, 90, -446, -730, 96, 96, 785, -176, 176, + 19, 278, -176, 176, 737, 187, -176, 582, 19, -470, + 96, 106, -470, 96, 106, 278, 582, 278, 582, -333, + -333, -333, 572, 573, 186, 190, 189, -470, 188, -470, + -470, 122, 161, -470, -470, -517, -517, -470, 38, -318, + -304, -470, -517, -517, -705, -470, 97, 96, -539, -536, + -533, -470, -470, -529, -470, -459, -517, -517, -517, -333, + -392, 57, 58, 59, -533, -217, 60, 61, -236, -628, + -630, -631, 128, -333, -497, -630, -626, 65, -236, 90, + 34, 90, -293, -293, -689, 38, -283, -470, -701, 87, + -432, -433, -434, -435, -437, -438, -436, 72, 76, 78, + 82, 73, 74, 75, 545, 79, 84, 777, 77, -468, + -473, 38, -470, 96, -468, -242, -267, -266, -265, 785, + -468, 90, -470, -470, -333, -333, -406, -414, -411, -407, + -415, 301, 269, 275, 442, 443, 271, 11, 270, -423, + 348, -518, 590, -387, -388, 81, 45, -390, 299, 486, + 482, 783, 311, 315, 100, 316, 519, 317, 280, 319, + 320, 321, 336, 338, 291, 322, 323, 324, 510, 325, + 181, 337, 326, 327, 328, 460, -382, 6, 390, 44, + 55, 56, 534, 533, 633, 14, 312, -470, 489, 622, + 34, 39, 271, 275, 270, -705, -703, 34, -470, 34, + -539, -533, -470, -470, 177, 282, -265, -267, -552, 177, + 570, 572, 573, -735, -553, -735, -553, 282, 35, 509, + -556, 509, 35, -529, -550, 566, 568, -545, 96, 510, + -534, -555, 86, 173, -640, -553, -553, -555, -555, 163, + 177, -733, 571, 572, 265, -277, -168, -271, -270, -497, + -277, -277, -250, -243, -251, -247, -242, 106, -723, -721, + -470, 626, -470, -616, -616, -335, -705, -538, -529, -470, + -616, -335, -472, -472, -304, 39, -470, -616, -470, -470, + -470, -171, 177, -471, -470, 38, 96, 176, -181, -179, + 128, -497, -6, 720, -497, -6, -6, -497, -6, -497, + -614, 169, -340, 106, 106, -449, 96, -449, 106, -608, + 106, 106, 636, 91, 96, 96, -277, -279, 704, -663, + -659, -279, -171, -633, 65, -236, 90, 34, 90, -616, + 187, 208, 747, -324, 132, 132, 132, 27, -470, 26, + -141, -118, -692, 176, -551, 518, 177, -300, -283, -333, + 635, 106, -159, 24, -470, -426, -470, 743, -426, -426, + -470, 743, 745, -426, -532, -470, -470, -470, -530, 87, + -470, 788, 94, -460, -426, -426, -484, -426, -426, 177, + 25, 91, -482, -484, -484, -324, -480, -324, 176, -324, + -459, -559, -537, -534, -561, 153, -470, -546, 177, 14, + 282, -718, -717, 501, 91, 177, -644, 283, 589, 96, + 785, 517, 259, 260, 96, 111, 408, 112, 113, 111, + 408, 112, 113, -597, -505, -501, -495, -495, -493, -493, + -501, -495, -495, -493, -493, 90, -499, 296, -499, 121, + -348, 172, 171, -348, -497, 786, -496, -686, 128, -497, + 38, 177, 38, 177, 87, 177, 91, -604, -497, 176, + 177, 91, 91, 19, 19, 142, 91, -497, 91, 91, + 91, 91, 19, 19, -497, 91, 176, 91, 91, 91, + 91, 87, 91, 177, 91, 91, 91, 91, 177, 177, + 177, -505, 91, 91, -505, -497, -505, 91, 91, 91, + -497, -497, -497, -505, 91, -497, -497, -497, -497, -497, + -497, -497, -497, 774, -497, -497, -505, -497, -497, -569, + 537, -569, -569, -569, 91, -569, 91, 177, 91, 177, + 91, 91, 177, 177, 177, -277, -273, 177, 91, -279, + -279, 14, -171, -743, 728, 90, 106, 177, 769, -453, + -452, 96, -177, 282, -470, 737, -470, -177, -470, -470, + 132, -177, -470, 737, 96, 96, -333, -459, -333, -459, + 628, 42, 42, 187, 191, 191, 190, -470, 96, 39, + 39, 26, 26, 346, -470, -470, -152, 623, -314, 90, + 90, 176, -333, -333, -707, 487, -470, -719, 177, 44, + -717, 582, -213, 359, -521, 87, -226, 366, 19, -333, + -333, -333, -347, 38, -236, -629, 65, 90, 127, -236, + -543, -542, 86, -634, -506, -681, 703, -292, 91, -280, + -470, -679, -680, -280, -286, -294, -470, -626, -626, 90, + 91, 177, 19, -258, -334, -470, -265, -264, -264, -264, + -264, -264, -264, -264, 72, 83, 72, -281, 90, 72, + 77, 72, 77, 72, 77, 72, -434, 72, 72, 74, + 83, -284, -473, 177, 91, 93, -728, -727, -726, -724, + 80, 283, 81, -503, 34, 34, 56, 55, -603, 38, + -284, 177, 23, 411, -467, -409, 286, 280, 344, 287, + 301, -332, -467, -329, -331, -487, -330, 289, 430, -675, + 287, 285, 116, 290, 344, 117, 280, -467, -467, 286, + -391, 282, 38, 23, 301, -408, 280, 117, -470, 286, + 290, 287, 285, -466, 132, -458, 163, 282, 46, 460, + -466, 634, 301, -466, -466, -466, -466, -466, -466, -466, + -466, 318, 318, -466, -466, -466, -466, -466, -466, -466, + -466, -466, -466, -466, 182, -466, -466, -466, -466, -466, + -466, 90, 313, 314, 346, 623, 126, 636, 625, -532, + 282, 557, 557, -708, 487, 34, 440, 440, 441, -719, + 436, 45, 34, -227, 434, -413, -410, -481, 34, 34, + -553, -734, -736, 574, 571, 577, -555, -555, 106, 282, + 90, 132, -555, -555, 44, -469, -731, 578, 572, -279, + 177, -268, 40, 41, 91, 91, -311, 739, -470, -470, + 86, -335, -619, 339, 340, 90, -318, 96, 19, -311, + -425, -424, 19, -254, -470, 96, -470, 153, 129, -6, + 127, -185, -184, -183, 130, 717, 724, 129, 129, 129, + 91, 91, 91, 91, 177, 91, 91, 91, 177, 91, + 177, 106, 765, -647, 547, -279, -171, 96, 177, -171, + -253, 772, -634, -292, 91, -679, -286, -470, 96, 106, + 96, 38, -225, 93, 101, 96, -325, -497, -470, 96, + -497, 208, 176, 519, -470, -660, 91, 106, -482, -470, + -482, 176, -470, -222, -224, -470, 96, -470, -529, -469, + -482, -426, -497, -497, 551, 550, -426, -482, -482, -484, + -470, -324, -561, 177, 282, 176, 176, -535, 463, -537, + 23, 14, -446, 42, -453, 132, 785, -470, 91, -499, + -499, 121, -499, -499, 121, -495, -495, -492, 91, 129, + -497, 127, -338, -497, -338, -339, -345, 227, 173, 211, + 295, 210, 209, 207, 166, 167, -381, -526, 628, -268, + 91, -470, -505, -497, -497, -493, 91, -497, -497, 19, + -470, -381, -493, -497, -497, -497, -273, -274, 774, -274, + -273, 91, 91, -568, -569, -568, -274, 91, 91, 91, + 91, -568, 91, 91, 91, 91, 91, 91, 91, 91, + 21, 91, 91, 91, 91, 177, -470, 90, -569, -754, + 781, -497, -754, -497, -754, -754, -497, 106, 108, 106, + 108, -279, -277, -640, -171, -171, 464, 90, 301, 177, + 106, 96, 786, 177, 132, 434, -470, 19, 176, 96, + -470, 96, 19, 278, -470, 19, 19, -333, -333, -333, + 191, 96, -720, 353, 434, 582, 278, 434, 353, 582, + 278, -585, 106, -357, 14, -361, 14, -153, 126, 96, + 471, -319, -320, -321, -322, -323, 142, 178, 179, -305, + -306, -307, -308, -340, -446, 773, 212, 215, 217, 218, + 219, 220, 221, 223, 224, 225, 226, 227, 230, 231, + 232, 233, 234, 235, 228, 229, 295, 207, 208, 209, + 210, 194, 213, 629, 195, 196, 197, 171, 172, 198, + 201, 202, 203, 204, 200, 236, 237, 238, 239, 240, + 241, 242, 243, 245, 244, 246, 247, 248, 249, 250, + 251, 252, 253, -470, -284, -284, -710, 549, 489, 499, + -466, 382, -489, -488, 436, 45, -621, 510, 495, 496, + -536, 309, -459, 153, -716, 103, 132, 86, 394, 398, + 400, 402, 401, 399, 395, 396, 397, -515, -516, -514, + -518, -459, 96, -703, 90, -237, -221, -220, 140, -226, + 366, 19, -236, 65, 283, 589, 90, -356, 321, 90, + -598, 379, -340, 90, -292, -629, -253, 43, 177, 90, + 91, 177, 65, 176, 177, 132, 91, 177, 91, 177, + 132, -253, -253, -542, -1, -470, -333, -258, -470, 19, + 177, -702, 176, 86, -296, -295, 86, 87, -296, -296, + -295, -295, 72, -282, 96, 72, 72, 72, 72, 77, + -266, -265, -726, -725, 26, -675, -675, -675, 91, -358, + 90, -359, -223, -470, 96, -362, 90, -363, -364, -470, + 96, -598, -340, 38, -407, 275, 269, 270, -565, 346, + 347, -566, -587, 349, -470, -446, -470, -470, -470, -589, + 90, -337, -446, -330, -674, -675, -674, -517, -470, 117, + -674, 117, 90, -337, -446, -446, -410, -418, -417, -446, + -421, 35, -422, -470, -470, -470, -470, 117, -470, 117, + -386, 44, 52, 53, 54, -466, -466, 214, -389, 44, + 509, 511, 512, -421, 106, 106, 106, 106, 106, 96, + 96, 96, -466, -466, 106, 96, -473, 96, -676, 190, + 48, 49, 106, 106, 106, 106, 44, 96, -394, 44, + 329, 333, 330, 331, 332, 96, 106, 44, 106, 44, + 106, 44, -470, 90, -677, -678, 96, -585, 96, 90, + 106, 96, 271, -532, 96, 86, -710, -466, 440, -552, + 132, 132, -489, -712, 100, 490, -712, -715, 359, -229, + 582, 35, -287, 275, 270, -703, -541, -540, -446, -541, + -555, 571, 575, 576, -537, -485, 96, -545, -171, -270, + -269, 47, -333, -619, -305, -470, -426, -267, 176, 125, + -6, -181, -183, -497, -6, -497, 720, 453, 721, 96, + 106, 106, 573, -655, 531, 526, 528, -171, -656, 517, + -659, -252, 91, 65, 91, 27, 786, 786, 786, 786, + 96, -470, 106, -426, -482, -426, -222, -482, -482, 142, + -426, -324, -426, -426, -482, 19, -534, -529, 153, 153, + -470, 464, -546, 96, 488, 96, 278, 786, 96, -453, + -492, -492, 91, -497, 91, 38, 91, 91, -605, -605, + -604, -607, -604, -348, -348, 91, 90, -268, 91, 91, + 26, 91, 91, -568, 91, 91, -497, 176, 91, 91, + 177, 177, 91, -624, 591, -568, 21, -568, -625, 663, + -568, -568, -568, -568, -568, -568, -568, -568, -568, -568, + -568, -568, -568, -568, -568, 90, -568, -568, -568, -568, + -497, -570, -574, -470, -569, 47, 91, 177, -569, 91, + 177, -569, -569, 91, 532, 734, 734, 532, 734, 734, + -171, -279, -505, -744, 67, 726, 66, 509, 111, 349, + 91, -683, 177, -461, 354, -461, -452, 96, -470, 96, + 737, -470, 786, 786, 737, -470, 96, -333, -459, -290, + 548, -233, 126, -234, 124, 46, 96, -470, 19, -470, + -470, 346, -470, 346, -470, -470, 96, 90, 90, -158, + 636, 90, -155, 624, 96, 91, 177, -446, 91, 177, + -340, 38, 38, -711, 100, -706, 96, -470, 97, -470, + -712, 175, 438, 44, 491, 492, 507, 433, 106, 106, + 497, -704, -470, -228, 278, 434, -228, -714, 56, 132, + 96, -333, -514, -458, 163, 320, -324, -470, 382, -326, + -327, -328, -337, -329, -331, -237, 38, -333, -333, 96, + -168, -326, -466, -326, -599, 381, 23, 106, 152, -505, + 91, 117, -506, -642, -641, 65, -236, -280, -634, -470, + -680, -640, -470, -470, -497, -253, 91, -285, 87, 176, + -267, -334, -470, 153, -497, -497, 90, -260, 778, 91, + 72, 786, 90, 72, 11, 21, 177, -358, 132, 177, + -362, 132, -599, -236, -582, 350, 90, -580, 90, -580, + 117, 395, 398, 400, 402, 401, 430, 34, 270, -419, + 398, 392, 393, -547, 345, 122, 161, -547, -590, -588, + 301, -416, 48, 50, -340, -672, -470, -672, -670, -672, + -470, -670, -670, -517, -497, -416, -337, 282, 177, -268, + 177, -470, -381, -381, 34, 96, 96, -335, 91, 177, + 132, 96, -155, -154, -497, -238, -242, 282, 86, 278, + -711, -706, 132, -553, 96, 96, -712, 96, 96, -716, + 132, -336, 278, -459, 177, -287, -287, -426, 19, 177, + 132, -426, 91, -297, 26, 45, 48, 49, 91, 382, + -428, 21, 153, 129, 127, 129, 129, -470, 91, 91, + -611, 705, -651, -653, 526, 23, 23, -297, -657, 710, + 96, 65, -236, -634, 208, 96, 786, -426, -482, -426, + -426, 743, -426, -529, -546, 510, -333, 177, 786, -338, + -400, 96, 97, -470, -497, 91, -470, -497, -497, 91, + 96, 90, 91, 96, -272, 91, 91, -508, -507, 301, + -754, -497, -754, -497, -755, 19, 91, 177, 91, 91, + 91, 177, 91, 91, -297, -171, 91, 177, 91, -683, + -462, 208, 96, -462, -470, -470, 19, -471, -231, 282, + -324, -235, 377, 90, 373, -233, 187, 90, 96, -470, + 19, -470, -585, 346, -585, 346, 278, -470, -311, -358, + -362, -156, 625, 106, -154, 96, -522, 630, -321, -340, + 276, -307, 44, -237, -237, 96, -709, 501, -586, 387, + 106, 44, 106, 175, 493, -622, -214, 100, -335, 35, + -287, -214, -713, 100, 132, 785, 90, -466, -466, -466, + -231, 382, -470, 91, 177, -237, -232, 54, -470, -273, + 91, 742, 91, -600, 300, 106, 152, 106, 152, 106, + 91, 65, 17, 283, 91, -634, 176, 132, -468, -267, + -470, -426, -702, 176, -105, -106, 126, -283, -494, 175, + -671, -470, 285, 23, 23, -359, 91, -224, -363, 91, + -365, -470, 96, -600, -567, 351, 106, -493, 90, -493, + 90, -581, 348, 90, -527, -527, -527, -527, -527, 44, + -419, 44, -420, 417, 345, 345, 91, 177, -470, -446, + -353, -352, -350, 111, 122, 161, 44, 482, -351, 100, + 750, 751, 163, 334, 337, 336, 312, 335, -405, -486, + 86, 698, 485, 392, 393, -518, 713, 38, 285, 116, + 117, 465, -487, 90, 90, 90, 87, 354, 90, 90, + -672, 91, -416, -446, -417, -470, 163, -381, 91, -678, + 96, 91, -532, 278, -470, -709, 96, -555, -714, 96, + -214, -335, -703, -273, -267, -540, -640, -253, 17, 68, + 142, -470, -427, 22, 23, 284, -6, 721, 453, -396, + 706, 96, 23, 96, -649, 96, -647, 96, -634, 96, + -426, -470, -174, -393, -458, 317, 91, -399, 142, 14, + 91, 91, 91, -274, -272, -568, 91, -568, -273, 23, + -569, 91, -569, 91, -754, 48, 96, 96, -297, -497, + 91, 96, 96, 96, 737, 434, -231, 38, 471, 24, + 642, 378, -283, 374, 375, 376, -470, 96, -505, -238, + 785, 382, -470, 19, 96, -585, 96, -585, -470, 346, + 91, 91, 38, 96, 91, 96, 96, -309, -340, -490, + -218, 14, -218, 23, 14, 175, 437, 44, 106, 44, + 494, 96, -228, 132, 112, 113, -454, -455, 96, -524, + -381, -383, 96, -470, -354, -237, -221, -220, -355, -423, + -518, -328, -231, 30, 382, -277, -173, -356, -360, -366, + -372, -373, -172, 321, -357, -354, -601, 181, 106, 152, + 106, 106, 90, -541, -470, -497, -426, -426, -253, 772, + -106, -108, 122, 161, -470, 91, 91, 177, -601, -589, + 23, 91, -562, 91, -562, 90, 132, -493, -528, 291, + 409, 410, 100, 14, 392, 393, 414, 413, 412, 418, + 419, 423, 424, 420, 422, 421, 425, 429, 426, 427, + 428, 431, 415, 416, 58, 417, 437, 448, 444, -493, + -527, 132, -588, -591, 65, -350, 111, 111, -493, 96, + 96, 96, -383, -384, 44, 333, 329, 132, 132, -385, + 44, 313, 314, -395, 90, 344, 17, 106, 214, 714, + 90, 117, 117, -333, -524, -524, -524, -673, 394, 395, + 396, 404, 398, 399, 397, 400, 401, 402, 403, -673, + -524, -524, 90, -548, -547, -466, 163, -470, 176, -713, + -275, -426, 68, -572, 779, -497, -505, 756, 758, 759, + -470, -470, -450, 707, 106, 96, 528, -655, -482, -612, + 708, -645, -580, -381, 132, 91, 79, 629, 403, 631, + -568, 91, -568, -576, -575, -579, 532, 346, 540, -505, + -754, -754, -569, 91, 91, 91, -470, -470, -333, 96, + 106, 91, 121, 121, 91, 91, -457, -456, 96, -470, + 382, -470, -311, 96, -311, 96, 346, -585, -2, 630, + -219, 64, 578, 96, 97, 488, 96, 97, 106, 437, + -214, 96, 786, 177, 132, 91, -586, -563, 301, -237, + 38, 177, -423, -458, -470, -174, -466, -563, -618, 190, + 380, 14, 106, 152, 106, -505, -273, -253, -252, -107, + 121, -108, -108, -470, 285, -602, 190, 380, -566, 91, + 91, 91, -562, 106, 91, -466, -466, 96, 96, 391, + -466, -466, -466, -466, -466, -466, 90, 96, 96, -466, + -466, -466, -466, -466, -466, 132, 132, -466, -466, -466, + 112, 113, -596, -592, 90, -593, -423, 303, 142, 96, + 96, 106, 90, -635, 34, 38, -497, -525, 90, 91, + 91, 91, 91, 91, -524, -381, -466, 176, -470, -253, + -253, 69, -573, -571, -470, -620, 14, 757, 90, 90, + 90, 23, -611, -426, -613, 709, 96, -654, 531, -648, + -646, 526, 527, 528, 529, 96, 630, 69, 69, 632, + -578, 124, 493, 497, -491, 97, -494, 106, 108, 205, + -569, -569, 96, -470, 96, 786, 177, 132, -470, 382, + -311, -311, -585, 96, -312, -470, 344, 510, -455, 96, + -527, -564, 353, 23, -237, -423, -466, -586, 749, 753, + -380, 755, 754, 62, -564, 380, 106, 152, 106, 91, + -275, 127, -497, -107, -107, 380, -583, 352, 91, 106, + 106, -470, 106, 106, 106, 106, 106, 106, -562, 106, + 106, 106, 106, 106, 106, 112, 113, 112, 113, 106, + 106, 106, -596, -593, -595, -594, 351, 304, 90, 91, + -497, -509, -466, 90, 91, -398, -397, 627, -524, -527, + 87, -527, -527, 87, -527, 87, -527, 87, 91, -381, + -470, 177, 38, 759, 90, -505, -505, -451, -470, -649, + -396, 96, -658, 283, -652, -653, 530, -646, 23, 528, + 23, 23, -175, 177, 69, -577, -578, 497, -491, 97, + -494, 703, 538, 538, 538, 538, -233, -234, -233, -234, + -311, -456, 96, -470, 96, -311, -310, 38, 533, 464, + 23, -565, -381, -361, -367, 14, -377, 14, -374, 14, + 106, -253, 17, 18, 127, 127, 106, 91, 91, 177, + -470, 300, 90, -504, -498, -497, 300, 91, -381, -497, + -549, 716, 715, -404, -402, -403, 86, 545, 342, 343, + 91, -673, -673, -673, -673, -405, -571, 90, -169, 90, + 91, 91, 91, 177, -450, -666, 90, 106, -651, -650, + -652, 23, -649, 23, -649, -649, 535, 14, 121, 539, + 539, 539, 539, -233, -233, -311, 96, -446, 90, -582, + 90, 90, 90, 34, 16, 16, -594, -592, -504, 91, + 177, -547, 91, -403, 86, -402, 86, 18, 17, -527, + -527, -527, -527, -570, 91, 177, -503, -470, -669, 34, + 91, -665, -664, -447, -659, 531, 532, 96, -649, 132, + 631, -577, -747, -746, 733, -562, -567, -368, -369, -370, + -470, 96, -378, -379, -370, -375, -376, -370, -541, 90, + 65, 90, 65, 91, -498, -549, -401, 339, 340, 34, + 190, -401, 91, 90, 91, -668, -667, -448, 91, 177, + 96, 632, -317, 69, -315, 477, 276, 96, 91, -589, + 91, 177, 132, 91, 177, 132, 91, 177, 132, -291, + -470, 90, -291, 90, 111, 44, 341, -503, 177, 132, + -664, -316, 479, 480, 69, 86, 111, -369, -371, -470, + 96, -379, -371, -376, -371, 91, 177, 176, -505, 91, + -505, 91, -667, 44, -497, -315, -316, 111, 86, 65, + -470, -470, 91, 65, 91, 478, 111, 90, 176, 90, + 478, -505, -470, -505, 91, 91, } var yyDef = [...]int{ @@ -13456,516 +13515,518 @@ var yyDef = [...]int{ 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 456, 457, 458, 452, 453, 455, 454, 0, 0, 851, 0, 0, 0, 994, 1028, 0, 1048, - 1049, 0, 1569, 1050, 1060, 1088, 0, 23, 0, 6, + 1049, 0, 1578, 1050, 1060, 1088, 0, 23, 0, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 0, 0, 18, 0, 18, 0, 0, 0, 1786, 1787, - 1788, 1789, 2401, 2753, 2721, -2, 2444, 2402, 2403, 2644, - 2645, 2533, 2549, 2394, 2802, 2803, 2804, 2805, 2806, 2807, - 2808, 2809, 2810, 2811, 2812, 2813, 2814, 2815, 2816, 2817, - 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826, 2827, - 2828, 2829, 2830, 2831, 2832, 2833, 2834, 2835, 2836, 2837, - 2838, 2839, 2840, 2841, 2842, 2843, 2844, 2845, 2846, 2847, - 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, 2856, 2348, - 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, - 2359, 2360, 2361, 2362, 2363, 2364, 2365, 2366, 2367, 2368, - 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, 2378, - 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, 2388, - 2389, 2390, 2391, 2392, 2393, 2395, 2396, 2397, 2398, 2399, - 2400, 2404, 2405, 2406, 2407, 2408, 2409, 2410, 2411, 2412, - 2413, 2414, 2415, 2416, 2417, 2418, 2419, 2420, 2421, 2422, - 2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, 2431, 2432, - 2433, 2434, 2435, 2436, 2437, 2438, 2439, 2440, 2441, 2442, - 2443, 2445, 2446, 2447, 2448, 2449, 2450, 2451, 2452, 2453, - 2454, 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462, 2463, - 2464, 2465, 2466, 2467, 2468, 2469, 2470, 2471, 2472, 2473, - 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481, 2482, 2483, - 2484, 2485, 2486, 2487, 2488, 2489, 2490, 2491, 2492, 2493, - 2494, 2495, 2496, 2497, 2498, 2499, 2500, 2501, 2502, 2503, - 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513, - 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, - 2524, 2525, 2526, 2527, 2528, 2529, 2530, 2531, 2532, 2534, - 2535, 2536, 2537, 2538, 2539, 2540, 2541, 2542, 2543, 2544, - 2545, 2546, 2547, 2548, 2550, 2552, 2553, 2554, 2555, 2556, - 2557, 2558, 2559, 2560, 2561, 2562, 2563, 2564, 2565, 2566, - 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, - 2577, 2578, 2579, 2580, 2581, 2582, 2583, 2584, 2585, 2586, - 2587, 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, 2596, - 2597, 2598, 2599, 2600, 2601, 2602, 2603, 2604, 2605, 2606, - 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616, - 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, - 2627, 2628, 2629, 2630, 2631, 2632, 2633, 2634, 2635, 2636, - 2637, 2638, 2639, 2640, 2641, 2642, 2643, 2646, 2647, 2648, - 2649, 2650, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, - 2659, 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, 2668, - 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, 2677, -2, - 2679, 2680, 2681, 2682, 2683, 2684, 2685, 2686, 2687, 2688, - 2689, 2690, 2691, 2692, 2693, 2694, 2695, 2696, 2697, 2698, - 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, - 2709, 2710, 2711, 2712, 2713, 2714, 2715, 2716, 2717, 2718, - 2719, 2720, 2722, 2723, 2724, 2725, 2726, 2727, 2728, 2729, - 2730, 2731, 2732, 2733, 2734, 2735, 2736, 2737, 2738, -2, - -2, -2, 2742, 2743, 2744, 2745, 2746, 2747, 2748, 2749, - 2750, 2751, 2752, 2754, 2755, 2756, 2757, 2758, 2759, 2760, - 2761, 2762, 2763, 2764, 2765, 2766, 2767, 2768, 2769, 2770, - 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, 2779, 2780, - 2781, 2782, 2783, 2784, 2785, 2786, 2787, 2788, 2789, 2790, - 2791, 2792, 0, 345, 343, 2369, 2394, 2401, 2402, 2403, - 2444, 2533, 2549, 2551, 2590, 2644, 2645, 2671, 2678, 2721, - 2739, 2740, 2741, 2753, 0, 0, 1248, 0, 0, 382, - 840, 841, 871, 873, 895, 994, 1028, 0, 861, 862, - 0, 796, 0, 1729, 428, 0, 2420, 433, 2730, 0, - 0, 0, 0, 793, 422, 423, 424, 425, 426, 427, - 0, 0, 0, 1205, 0, 0, 2761, 418, 0, 0, - 83, 479, 684, 0, 0, 0, 0, 0, 773, 773, - 1113, 1113, 0, 714, 0, 0, 0, 773, 0, 728, - 720, 0, 0, 0, 773, 0, 0, 1017, 0, 1017, - 0, 776, 783, 773, 773, -2, 773, 773, 0, 768, - 773, 0, 0, 0, 734, 735, 736, 720, 720, 739, - 740, 741, 751, 752, 784, 2343, 0, 0, 376, 2536, - 2752, 1790, 0, 0, 0, 0, 0, 232, 1383, 234, - 1385, 238, 246, 0, 0, 0, 251, 252, 255, 256, - 257, 258, 259, 0, 263, 0, 265, 268, 0, 270, - 271, 0, 274, 275, 276, 0, 286, 287, 288, 1386, - 1387, 1388, 1389, 1390, 1391, 1392, 1393, -2, 0, 159, - 1246, 2298, 2165, 0, 2171, 2188, 2205, 1883, 1884, 1885, - 1886, 0, 0, 0, 0, 0, 0, 0, 1896, 1897, - 0, 1942, 2806, 2850, 2851, 0, 1906, 1907, 1908, 1909, - 1910, 1911, 0, 170, 184, 185, 2229, 2230, 2231, 2232, - 2233, 2234, 2235, 0, 2237, 2238, 2239, 0, 1868, 1786, - 0, 2815, 2825, 0, 2839, 2846, 2847, 2848, 2849, 2838, - 0, 0, 2120, 0, 2110, 0, 0, -2, -2, 0, - 0, 2617, -2, 2852, 2853, 2854, 2812, 2835, 2843, 2844, - 2845, 2816, 2855, 2856, 2819, 2842, 2808, 2809, 2810, 2803, - 2804, 2805, 2807, 2821, 2823, 2834, 0, 2830, 2840, 2841, - 2728, 0, 0, 2779, 2817, 2818, 0, 0, 0, 0, - 0, 0, 2788, 2789, 2790, 2791, 2792, 2774, 186, 187, + 0, 0, 18, 0, 18, 0, 0, 0, 1795, 1796, + 1797, 1798, 2411, 2766, 2734, -2, 2454, 2412, 2413, 2657, + 2658, 2544, 2561, 2404, 2815, 2816, 2817, 2818, 2819, 2820, + 2821, 2822, 2823, 2824, 2825, 2826, 2827, 2828, 2829, 2830, + 2831, 2832, 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2840, + 2841, 2842, 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, + 2851, 2852, 2853, 2854, 2855, 2856, 2857, 2858, 2859, 2860, + 2861, 2862, 2863, 2864, 2865, 2866, 2867, 2868, 2869, 2357, + 2358, 2359, 2360, 2361, 2362, 2363, 2364, 2365, 2366, 2367, + 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, + 2378, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, + 2388, 2389, 2390, 2391, 2392, 2393, 2394, 2395, 2396, 2397, + 2398, 2399, 2400, 2401, 2402, 2403, 2405, 2406, 2407, 2408, + 2409, 2410, 2414, 2415, 2416, 2417, 2418, 2419, 2420, 2421, + 2422, 2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, 2431, + 2432, 2433, 2434, 2435, 2436, 2437, 2438, 2439, 2440, 2441, + 2442, 2443, 2444, 2445, 2446, 2447, 2448, 2449, 2450, 2451, + 2452, 2453, 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462, + 2463, 2464, 2465, 2466, 2467, 2468, 2469, 2470, 2471, 2472, + 2473, 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481, 2482, + 2483, 2484, 2485, 2486, 2487, 2488, 2489, 2490, 2491, 2492, + 2493, 2494, 2495, 2496, 2497, 2498, 2499, 2500, 2501, 2502, + 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, + 2513, 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, + 2523, 2524, 2525, 2526, 2527, 2528, 2529, 2530, 2531, 2532, + 2533, 2534, 2535, 2536, 2537, 2538, 2539, 2540, 2541, 2542, + 2543, 2545, 2546, 2547, 2548, 2549, 2550, 2551, 2552, 2553, + 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2562, 2564, 2565, + 2566, 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, + 2576, 2577, 2578, 2579, 2580, 2581, 2582, 2583, 2584, 2585, + 2586, 2587, 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, + 2596, 2597, 2598, 2599, 2600, 2601, 2602, 2603, 2604, 2605, + 2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, + 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, + 2626, 2627, 2628, 2629, 2630, 2631, 2632, 2633, 2634, 2635, + 2636, 2637, 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645, + 2646, 2647, 2648, 2649, 2650, 2651, 2652, 2653, 2654, 2655, + 2656, 2659, 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, + 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, 2677, + 2678, 2679, 2680, 2681, 2682, 2683, 2684, 2685, 2686, 2687, + 2688, 2689, 2690, -2, 2692, 2693, 2694, 2695, 2696, 2697, + 2698, 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, + 2708, 2709, 2710, 2711, 2712, 2713, 2714, 2715, 2716, 2717, + 2718, 2719, 2720, 2721, 2722, 2723, 2724, 2725, 2726, 2727, + 2728, 2729, 2730, 2731, 2732, 2733, 2735, 2736, 2737, 2738, + 2739, 2740, 2741, 2742, 2743, 2744, 2745, 2746, 2747, 2748, + 2749, 2750, 2751, -2, -2, -2, 2755, 2756, 2757, 2758, + 2759, 2760, 2761, 2762, 2763, 2764, 2765, 2767, 2768, 2769, + 2770, 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, 2779, + 2780, 2781, 2782, 2783, 2784, 2785, 2786, 2787, 2788, 2789, + 2790, 2791, 2792, 2793, 2794, 2795, 2796, 2797, 2798, 2799, + 2800, 2801, 2802, 2803, 2804, 2805, 0, 345, 343, 2379, + 2404, 2411, 2412, 2413, 2454, 2544, 2561, 2563, 2602, 2657, + 2658, 2684, 2691, 2734, 2752, 2753, 2754, 2766, 0, 0, + 1248, 0, 0, 382, 840, 841, 871, 873, 895, 994, + 1028, 0, 861, 862, 0, 796, 0, 1738, 428, 0, + 2430, 433, 2743, 0, 0, 0, 0, 793, 422, 423, + 424, 425, 426, 427, 0, 0, 0, 1205, 0, 0, + 2774, 418, 0, 0, 83, 479, 684, 0, 0, 0, + 0, 0, 773, 773, 1113, 1113, 0, 714, 0, 0, + 0, 773, 0, 728, 720, 0, 0, 0, 773, 0, + 0, 1017, 0, 1017, 0, 776, 783, 773, 773, -2, + 773, 773, 0, 768, 773, 0, 0, 0, 734, 735, + 736, 720, 720, 739, 740, 741, 751, 752, 784, 2352, + 0, 0, 376, 2547, 2765, 1799, 0, 0, 0, 0, + 0, 232, 1392, 234, 1394, 238, 246, 0, 0, 0, + 251, 252, 255, 256, 257, 258, 259, 0, 263, 0, + 265, 268, 0, 270, 271, 0, 274, 275, 276, 0, + 286, 287, 288, 1395, 1396, 1397, 1398, 1399, 1400, 1401, + 1402, -2, 0, 159, 1246, 2307, 2174, 0, 2180, 2197, + 2214, 1892, 1893, 1894, 1895, 0, 0, 0, 0, 0, + 0, 0, 1905, 1906, 0, 1951, 2819, 2863, 2864, 0, + 1915, 1916, 1917, 1918, 1919, 1920, 0, 170, 184, 185, + 2238, 2239, 2240, 2241, 2242, 2243, 2244, 0, 2246, 2247, + 2248, 0, 1877, 1795, 0, 2828, 2838, 0, 2852, 2859, + 2860, 2861, 2862, 2851, 0, 0, 2129, 0, 2119, 0, + 0, -2, -2, 0, 0, 2630, -2, 2865, 2866, 2867, + 2825, 2848, 2856, 2857, 2858, 2829, 2868, 2869, 2832, 2855, + 2821, 2822, 2823, 2816, 2817, 2818, 2820, 2834, 2836, 2847, + 0, 2843, 2853, 2854, 2741, 0, 0, 2792, 2830, 2831, + 0, 0, 0, 0, 0, 0, 2801, 2802, 2803, 2804, + 2805, 2787, 186, 187, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + 2140, -2, 2142, -2, 2144, -2, 2146, -2, -2, -2, + -2, 2151, 2152, -2, -2, 2155, -2, -2, -2, -2, + -2, -2, -2, 2131, 2132, 2133, 2134, 2123, 2124, 2125, + 2126, 2127, 2128, -2, -2, -2, 2308, 994, 0, 0, + 1028, 1155, 0, 1028, 1026, 995, 0, 0, 998, 1075, + 1078, 1081, 1084, 0, 0, 129, 130, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 371, 372, 360, 362, 0, 366, 0, 0, 362, 359, + 353, 0, 1464, 1464, 1464, 0, 0, 1464, 0, 0, + 0, 1464, 1464, 1464, 1464, 1464, 0, 1464, 0, 0, + 0, 1464, 0, 1293, 1404, 1405, 1406, 1407, 1462, 1463, + 1579, 0, 0, 0, 0, 2694, 947, 2531, 0, 0, + 955, 1010, 0, 1012, 1015, 856, 852, 853, 854, 855, + 0, 0, 0, 617, 617, 0, 617, 0, 0, 617, + 0, 617, 617, 617, 0, 858, 2493, 2597, 2447, 2568, + 2389, 2547, 2765, 0, 318, 2630, 323, 0, 2453, 2497, + 0, 0, 2518, 0, -2, 0, 399, 1028, 0, 995, + 1019, 0, 1029, 0, 0, 994, 1028, 1028, 0, 1068, + 0, 0, 617, 617, 0, 0, 617, 617, 617, 617, + 617, 0, 617, 617, 617, 0, 617, 0, 617, 0, + 617, 617, 617, 0, 1089, 1090, 1092, 1093, 1094, 1095, + 1096, 1097, 1098, 1099, 1100, 1101, 1062, 4, 5, 18, + 0, 0, 0, 0, 0, 0, 135, 134, 0, 2311, + 2347, 2251, 2252, 2253, 0, 2334, 2256, 2338, 2338, 2338, + 2338, 0, 2288, 2334, 2290, 2291, 2292, 2334, 2294, 2295, + 2296, 2297, 2338, 2338, 2338, 2338, 2338, 2338, 0, 0, + 2306, 2277, 2336, 2336, 2336, 2334, 2313, 2257, 2258, 2259, + 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, + 2270, 2341, 2341, 2344, 2344, 2341, 2314, 2315, 2316, 2317, + 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, + 2328, 2329, 2330, 2331, 0, 484, 482, 483, 2170, 0, + 0, 0, 1028, -2, 0, 1026, 945, 0, 797, 1729, + 0, 0, 429, 1800, 0, 0, 434, 0, 435, 0, + 0, 437, 0, 0, 0, 459, 0, 462, 445, 446, + 447, 448, 449, 441, 0, 212, 0, 420, 421, 417, + 0, 468, 470, 472, 475, 1725, 80, 84, 87, 0, + 1017, 0, 686, 773, 773, 773, 773, 702, 703, 704, + 0, 1113, 0, 0, 707, 708, 0, 709, 0, 0, + 720, 773, 773, 726, 727, 722, 721, 779, 780, 776, + 0, 776, 776, 1113, 0, 745, 746, 747, 773, 773, + 753, 1018, 0, 0, 755, 757, 776, 0, 781, 782, + 1113, 0, 0, 1113, 1113, 0, 765, 766, 0, 769, + 773, 0, 772, 0, 0, 1464, 0, 789, 722, 722, + 2353, 2354, 378, 0, 0, 0, 618, 0, 0, 0, + 0, 0, 0, 243, 239, 247, 250, 260, 267, 0, + 279, 281, 284, 240, 248, 253, 254, 261, 282, 241, + 244, 245, 249, 283, 285, 242, 262, 266, 280, 264, + 269, 272, 273, 278, 0, 213, 0, 0, 0, 0, + 0, 2179, 0, 0, 2224, 2225, 2226, 2227, 2228, 2229, + 2230, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2217, 0, + 0, 0, 0, 0, 0, 0, -2, 2174, 0, 0, + 1899, 1900, 1901, 1902, 1903, 0, 1907, 0, 1952, 0, + 0, 0, 0, 0, 0, 2245, 2249, 0, 0, 2170, + 2170, 0, 0, 2170, 2166, 0, 0, 0, 0, 0, + 0, 2170, 2102, 0, 0, 2104, 2120, 0, 0, 2106, + 2107, 0, 2110, 2111, 2170, 0, 2170, 2115, 2170, 2170, + 2170, 2096, 2097, 0, 0, 0, 2166, 0, 0, 2166, + 2166, 2166, 0, 0, 2166, 2166, 2166, 2166, 2166, 2166, + 2166, 2166, 2166, 2166, 2166, 2166, 2166, 2166, 2166, 2166, + 2166, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1028, 994, 1019, 0, 0, -2, 0, + 956, 0, 1026, 1052, 1054, 1056, 1058, 1025, 1000, 0, + 1076, 1077, 1079, 1080, 1082, 1083, 1085, 1086, 0, 131, + 0, 0, 0, 112, 0, 0, 110, 0, 0, 0, + 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 364, 0, 369, 355, 2590, 0, + 354, 0, 0, 0, 0, 1464, 1464, 0, 0, 1245, + 0, 0, 1464, 1464, 1294, 0, 0, 0, 0, 0, + 0, 0, 0, 1464, 1464, 1464, 0, 1482, 0, 0, + 0, 0, 880, 882, 877, 0, 0, 880, 0, 0, + 947, 947, 954, 0, 1011, 0, 0, 858, 857, 0, + 1128, 1129, 1130, 1171, 1195, 1195, 0, 1195, 1175, 1738, + 0, 0, 0, 0, 1476, 0, 0, 0, 0, 0, + 0, 0, 792, 0, 0, 0, 511, 512, 0, 0, + 859, 0, 297, 301, 0, 304, 0, 2597, 0, 2597, + 0, 0, 311, 0, 0, 0, 0, 0, 0, 341, + 342, 0, 0, 0, 0, 332, 335, 1721, 1722, 1389, + 1390, 336, 337, 391, 392, 0, 1019, 1051, 1053, 1055, + 1057, 977, 1020, 1021, 1061, 1063, 1064, 1065, 0, 0, + 1046, 1047, 1019, 1019, 0, 1070, 0, 0, 0, 617, + 617, 0, 0, 0, 0, 0, 617, 0, 0, 0, + 834, 0, 836, 0, 0, 617, 0, 0, 0, 956, + 1115, 1117, 1200, 170, 1091, 7, 152, 149, 0, 18, + 0, 0, 18, 18, 0, 18, 346, 0, 2350, 2348, + 2349, 0, 2255, 2335, 0, 2282, 0, 2283, 2284, 2285, + 2286, 2287, 2289, 2293, 2298, 2299, 2300, 2301, 2302, 2303, + 0, 0, 2278, 0, 2279, 2280, 2281, 2271, 2341, 0, + 2273, 2274, 0, 2275, 2276, 344, 481, 0, 0, 2171, + 1249, 0, 0, 1019, 990, 1026, 0, 1026, 956, 0, + 0, 617, 1727, 0, 1738, 0, 0, 0, 0, 0, + 430, 0, 442, 436, 0, 443, 438, 439, 0, 0, + 461, 463, 464, 465, 466, 450, 451, 794, 414, 415, + 416, 400, 401, 402, 403, 404, 405, 406, 407, 408, + 0, 410, 411, 412, 413, 0, -2, 0, 0, 419, + 180, 467, 0, 469, 0, 474, 0, 476, 0, 88, + 478, 0, 688, 0, 1113, 0, 0, 1113, 1113, 0, + 0, 1113, 0, 706, 774, 775, 1114, 710, 0, 0, + 717, 2547, 1381, 722, 1113, 1113, 729, 723, 730, 778, + 731, 732, 733, 776, 1113, 1113, 1022, 0, 773, 776, + 758, 777, 776, 1738, 762, 0, 767, 770, 771, 1738, + 790, 1738, 0, 788, 737, 738, 379, 380, 0, 0, + 0, 226, 227, 228, 229, 230, 231, 233, 217, 825, + 827, 1393, 0, 1384, 0, 236, 277, 209, 0, 0, + 0, 0, 2175, 2176, 2177, 2178, 2183, 0, 0, 2186, + 2189, 2192, 2195, 0, 2221, -2, -2, 1878, 1879, 1880, + 1881, 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, + 1891, 2198, 2219, 2220, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2218, 2215, 2215, 2208, + 0, 1896, 1912, 1956, 1969, 1969, 1921, 1723, 1724, 1897, + 0, 0, 1949, 1953, 0, 0, 0, 0, 0, 0, + 1443, 2334, 0, 171, 2214, 2165, 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, 0, 0, 2174, 0, 0, + 0, 0, 2167, 2168, 0, 0, 0, 2051, 0, 0, + 2057, 2058, 2059, 0, 1792, 0, 2130, 2103, 2121, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2092, 2093, 2094, 2095, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1019, 1028, 1154, 1156, + 0, 941, 943, 944, 984, 1026, 1026, 986, 0, 956, + 1002, 0, 0, 0, 127, 132, 0, 1546, 118, 0, + 0, 0, 118, 0, 0, 0, 118, 0, 0, 0, + 1365, 1478, 89, 1364, 1480, 0, 0, 0, 0, 0, + 0, 0, 373, 374, 0, 0, 368, 356, 2590, 358, + 0, 0, 0, 0, 0, 0, 0, 1232, 0, 0, + 0, 1263, 0, 0, 0, 1309, 1310, 0, 615, 1375, + 0, 0, 0, 1391, 1447, 1460, 0, 0, 0, 1552, + 1295, 1300, 1301, 1302, 1296, 1297, 1303, 1304, 874, 883, + 0, 878, 0, 884, 0, 0, 917, 937, 912, 0, + 921, 0, 0, 0, 1013, 0, 0, 1169, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1161, 0, 0, + 0, 1160, 0, 0, 0, 0, 0, 0, 0, 1015, + 1196, 0, 1198, 1199, 1173, -2, 0, 1124, 1126, 0, + 1178, 2170, 0, 0, 1554, 1015, 508, 509, 510, 520, + 522, 0, 581, 581, 581, 581, 564, 0, 0, 552, + 2355, 0, 0, 0, 0, 561, 2355, 0, 0, 2355, + 2355, 2355, 2355, 2355, 2355, 2355, 2355, 0, 0, 2355, + 2355, 2355, 2355, 2355, 2355, 2355, 2355, 2355, 2355, 2355, + 0, 2355, 2355, 2355, 2355, 2355, 1707, 2355, 0, 1477, + 571, 572, 573, 574, 579, 580, 0, 0, 525, 526, + 0, 0, 0, 0, 0, 610, 0, 0, 1308, 0, + 615, 0, 0, 1353, 0, 0, 1126, 0, 0, 0, + 0, 309, 310, 298, 0, 299, 0, 0, 312, 313, + 0, 315, 316, 317, 324, 2447, 2568, 319, 321, 0, + 0, 325, 338, 339, 340, 0, 0, 330, 331, 0, + 0, 394, 395, 397, 0, 1026, 1066, 1032, 1033, 1036, + 0, 0, 1069, 1071, 1072, 1073, 1074, 1479, 1467, 85, + 86, 2774, 819, 0, 0, 822, 823, 824, 828, 0, + 0, 1580, 832, 833, 0, 0, 1362, 0, 1366, 1368, + 1467, 1121, 0, 1118, 1201, 0, 1203, 0, 0, 150, + 18, 0, 143, 140, 0, 0, 0, 0, 0, 2312, + 2250, 2351, 0, 0, 0, 0, 2332, 0, 0, 2272, + 0, 0, 0, 133, 156, 963, 1026, 956, 0, 958, + 182, 956, 992, 892, 937, 865, 0, 921, 0, 0, + 0, 0, 0, 1729, 0, 0, 0, 0, 1801, 0, + 444, 440, 460, 0, 409, 0, 0, 471, 0, 1726, + 477, 480, 685, 0, 687, 690, 773, 0, 693, 694, + 773, 0, 0, 700, 705, 713, 711, 0, 715, 0, + 716, 0, 1383, 773, 724, 725, 1113, 748, 749, 0, + 0, 0, 1113, 773, 773, 761, 776, 785, 0, 786, + 1738, 0, 220, 1378, 0, 221, 225, 215, 0, 0, + 0, 1380, 1385, 0, 235, 0, 0, 210, 211, 1537, + 1546, 0, 0, 0, 158, 2184, 2187, 2190, 2193, 2185, + 2188, 2191, 2194, 2196, 0, 2199, 2215, 2215, 2209, 0, + 2200, 2215, 2215, 2210, 0, 0, 2202, 0, 2205, 0, + 1957, 1970, 1971, 1958, 2175, 1904, 0, 1954, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1036, 0, 0, + 0, 2039, 2041, 0, 0, 0, 2046, 0, 2048, 2049, + 2050, 2052, 0, 0, 0, 2056, 0, 2101, 2122, 2105, + 2108, 0, 2112, 0, 2114, 2116, 2117, 2118, 0, 0, + 0, 1028, 1030, 1030, 1028, 0, 0, 1996, 1996, 1030, + 0, 0, 0, 0, 1996, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1926, + 0, 1927, 1928, 1929, 0, 1931, 2870, 0, 2870, 0, + 2870, 2870, 0, 0, 0, 1026, 1019, 0, 1157, 956, + 956, 0, 987, 996, 0, 0, 0, 0, 0, 0, + 1544, 0, 108, 0, 113, 0, 0, 109, 114, 0, + 0, 111, 0, 0, 120, 90, 0, 0, 1485, 1486, + 0, 0, 0, 375, 363, 365, 0, 357, 0, 1465, + 1466, 0, 0, 0, 1626, 1636, 1236, 0, 0, -2, + 1265, 0, 1015, 1015, 1320, 2355, 0, 619, 0, 0, + 1377, 0, 1342, 0, 0, 0, -2, 0, 0, -2, + 0, 0, 1556, 0, 875, 881, 0, 0, 0, 876, + 892, 918, 0, 911, 934, 0, 938, 0, 0, 925, + 927, 916, 922, 0, 0, 0, 952, 892, 892, 23, + 1016, 0, 0, 0, 845, 849, 0, 1165, 1165, 1165, + 1134, 0, 0, 1137, 1162, 1138, 1163, 0, 0, 1142, + 0, 1144, 0, 1146, 0, 1140, 1141, 1148, 1149, 0, + 1139, 1172, 1197, 0, 1174, 0, 1177, 1179, 1180, 1186, + 0, 0, 0, 0, 0, 0, 504, 505, 1556, 0, + 0, 1476, 1623, 0, 0, 551, 582, 0, 0, 0, + 1590, 542, 0, 1751, 1752, 0, 1759, 1768, 1768, 1464, + 1841, 0, 1768, 0, 0, 1770, 1771, 0, 0, 0, + 0, 565, 566, 0, 0, 550, 0, 0, 592, 0, + 0, 0, 0, 0, 2356, 2355, 2355, 0, 559, 560, + 0, 563, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2355, 2355, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1698, 0, 0, 0, 0, 0, + 0, 0, 1713, 1714, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1320, 2355, 0, 0, 0, 0, 619, + 1372, 1372, 1340, 1358, 0, 513, 514, 589, 0, 0, + 0, 302, 303, 0, 0, 308, 326, 328, 300, 0, + 0, 0, 327, 329, 333, 334, 393, 396, 398, 956, + 0, 1039, 1037, 1038, 1059, 1067, 82, 1468, 820, 821, + 0, 1580, 831, 1581, 1582, 1265, 837, 1363, 0, 1370, + 1113, 1122, 0, 1116, 1202, 1204, 171, 1119, 0, 153, + 18, 152, 144, 145, 0, 18, 0, 0, 0, 0, + 2254, 2340, 2339, 2304, 0, 2305, 2337, 2342, 0, 2345, + 0, 485, 0, 967, 0, 956, 993, 959, 0, 991, + 863, 0, 864, 0, 0, 869, 0, 952, 1367, 1730, + 1731, 0, 1734, 1735, 1736, 1737, 1728, 0, 0, 0, + 0, 0, 0, 0, 795, 181, 473, 689, 1113, 773, + 1113, 0, 773, 773, 701, 1633, 1634, 712, 718, 1382, + 1113, 742, 1023, 1024, 754, 756, 1738, 1113, 1113, 773, + 791, 787, 0, 0, 0, 0, 0, 826, 0, 217, + 0, 0, 237, 0, 0, 0, 1546, 1541, 2169, 2203, + 2206, 0, 2204, 2207, 0, 0, 2216, 2211, 1898, 1908, + 1950, 0, 0, 0, 0, 0, 1959, 1960, 2338, 2338, + 1963, 2334, 2336, 2334, 1969, 1969, 0, 1444, 0, 1445, + 1036, 172, 0, 0, 0, 0, 1996, 0, 0, 0, + 1793, 0, 0, 0, 0, 0, 1992, 1996, 0, 1996, + 1994, 1996, 1996, 2014, 1997, 2015, 1996, 1996, 1996, 1996, + 1996, 2021, 1996, 1996, 1996, 1996, 1996, 1996, 1996, 1996, + 0, 1996, 1996, 1996, 1996, 0, 1998, 2001, 1930, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2239, + 2240, 956, 1026, 942, 988, 985, 0, 0, 0, 0, + 0, 71, 71, 1546, 0, 0, 0, 0, 0, 126, + 0, 0, 0, 0, 0, 0, 0, 1494, 1502, 0, + 367, 0, 91, 92, 94, 0, 0, 0, 0, 0, + 0, 0, 107, 1229, 0, 1230, 0, 1240, 0, 1234, + 0, 0, 1251, 1252, 1254, 0, 1257, 1258, 1259, 0, + 1266, 1267, 1269, 1270, 0, 2361, -2, -2, 2494, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, - -2, -2, -2, -2, -2, -2, 2131, -2, 2133, -2, - 2135, -2, 2137, -2, -2, -2, -2, 2142, 2143, -2, - -2, 2146, -2, -2, -2, -2, -2, -2, -2, 2122, - 2123, 2124, 2125, 2114, 2115, 2116, 2117, 2118, 2119, -2, - -2, -2, 2299, 994, 0, 0, 1028, 1155, 0, 1028, - 1026, 995, 0, 0, 998, 1075, 1078, 1081, 1084, 0, - 0, 129, 130, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 371, 372, 360, 362, - 0, 366, 0, 0, 362, 359, 353, 0, 1455, 1455, - 1455, 0, 0, 1455, 0, 0, 0, 1455, 1455, 1455, - 1455, 1455, 0, 1455, 0, 0, 0, 1455, 0, 1284, - 1395, 1396, 1397, 1398, 1453, 1454, 1570, 0, 0, 0, - 0, 2681, 947, 2520, 0, 0, 955, 1010, 0, 1012, - 1015, 856, 852, 853, 854, 855, 0, 0, 0, 617, - 617, 0, 617, 0, 0, 617, 0, 617, 617, 617, - 0, 858, 2482, 2585, 2437, 2556, 2379, 2536, 2752, 0, - 318, 2617, 323, 0, 2443, 2486, 0, 0, 2507, 0, - -2, 0, 399, 1028, 0, 995, 1019, 0, 1029, 0, - 0, 994, 1028, 1028, 0, 1068, 0, 0, 617, 617, - 0, 0, 617, 617, 617, 617, 617, 0, 617, 617, - 617, 0, 617, 0, 617, 0, 617, 617, 617, 0, - 1089, 1090, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, - 1100, 1101, 1062, 4, 5, 18, 0, 0, 0, 0, - 0, 0, 135, 134, 0, 2302, 2338, 2242, 2243, 2244, - 0, 2325, 2247, 2329, 2329, 2329, 2329, 0, 2279, 2325, - 2281, 2282, 2283, 2325, 2285, 2286, 2287, 2288, 2329, 2329, - 2329, 2329, 2329, 2329, 0, 0, 2297, 2268, 2327, 2327, - 2327, 2325, 2304, 2248, 2249, 2250, 2251, 2252, 2253, 2254, - 2255, 2256, 2257, 2258, 2259, 2260, 2261, 2332, 2332, 2335, - 2335, 2332, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, - 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, - 0, 484, 482, 483, 2161, 0, 0, 0, 1028, -2, - 0, 1026, 945, 0, 797, 1720, 0, 0, 429, 1791, - 0, 0, 434, 0, 435, 0, 0, 437, 0, 0, - 0, 459, 0, 462, 445, 446, 447, 448, 449, 441, - 0, 212, 0, 420, 421, 417, 0, 468, 470, 472, - 475, 1716, 80, 84, 87, 0, 1017, 0, 686, 773, - 773, 773, 773, 702, 703, 704, 0, 1113, 0, 0, - 707, 708, 0, 709, 0, 0, 720, 773, 773, 726, - 727, 722, 721, 779, 780, 776, 0, 776, 776, 1113, - 0, 745, 746, 747, 773, 773, 753, 1018, 0, 0, - 755, 757, 776, 0, 781, 782, 1113, 0, 0, 1113, - 1113, 0, 765, 766, 0, 769, 773, 0, 772, 0, - 0, 1455, 0, 789, 722, 722, 2344, 2345, 378, 0, - 0, 0, 618, 0, 0, 0, 0, 0, 0, 243, - 239, 247, 250, 260, 267, 0, 279, 281, 284, 240, - 248, 253, 254, 261, 282, 241, 244, 245, 249, 283, - 285, 242, 262, 266, 280, 264, 269, 272, 273, 278, - 0, 213, 0, 0, 0, 0, 0, 2170, 0, 0, - 2215, 2216, 2217, 2218, 2219, 2220, 2221, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2208, 0, 0, 0, 0, 0, - 0, 0, -2, 2165, 0, 0, 1890, 1891, 1892, 1893, - 1894, 0, 1898, 0, 1943, 0, 0, 0, 0, 0, - 0, 2236, 2240, 0, 0, 2161, 2161, 0, 0, 2161, - 2157, 0, 0, 0, 0, 0, 0, 2161, 2093, 0, - 0, 2095, 2111, 0, 0, 2097, 2098, 0, 2101, 2102, - 2161, 0, 2161, 2106, 2161, 2161, 2161, 2087, 2088, 0, - 0, 0, 2157, 0, 0, 2157, 2157, 2157, 0, 0, - 2157, 2157, 2157, 2157, 2157, 2157, 2157, 2157, 2157, 2157, - 2157, 2157, 2157, 2157, 2157, 2157, 2157, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1028, - 994, 1019, 0, 0, -2, 0, 956, 0, 1026, 1052, - 1054, 1056, 1058, 1025, 1000, 0, 1076, 1077, 1079, 1080, - 1082, 1083, 1085, 1086, 0, 131, 0, 0, 0, 112, - 0, 0, 110, 0, 0, 0, 0, 81, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 364, 0, 369, 355, 2578, 0, 354, 0, 0, 0, - 0, 1455, 1455, 0, 0, 1245, 0, 0, 1455, 1455, - 1285, 0, 0, 0, 0, 0, 0, 0, 0, 1455, - 1455, 1455, 0, 1473, 0, 0, 0, 0, 880, 882, - 877, 0, 0, 880, 0, 0, 947, 947, 954, 0, - 1011, 0, 0, 858, 857, 0, 1128, 1129, 1130, 1171, - 1195, 1195, 0, 1195, 1175, 1729, 0, 0, 0, 0, - 1467, 0, 0, 0, 0, 0, 0, 0, 792, 0, - 0, 0, 511, 512, 0, 0, 859, 0, 297, 301, - 0, 304, 0, 2585, 0, 2585, 0, 0, 311, 0, - 0, 0, 0, 0, 0, 341, 342, 0, 0, 0, - 0, 332, 335, 1712, 1713, 1380, 1381, 336, 337, 391, - 392, 0, 1019, 1051, 1053, 1055, 1057, 977, 1020, 1021, - 1061, 1063, 1064, 1065, 0, 0, 1046, 1047, 1019, 1019, - 0, 1070, 0, 0, 0, 617, 617, 0, 0, 0, - 0, 0, 617, 0, 0, 0, 834, 0, 836, 0, - 0, 617, 0, 0, 0, 956, 1115, 1117, 1200, 170, - 1091, 7, 152, 149, 0, 18, 0, 0, 18, 18, - 0, 18, 346, 0, 2341, 2339, 2340, 0, 2246, 2326, - 0, 2273, 0, 2274, 2275, 2276, 2277, 2278, 2280, 2284, - 2289, 2290, 2291, 2292, 2293, 2294, 0, 0, 2269, 0, - 2270, 2271, 2272, 2262, 2332, 0, 2264, 2265, 0, 2266, - 2267, 344, 481, 0, 0, 2162, 1249, 0, 0, 1019, - 990, 1026, 0, 1026, 956, 0, 0, 617, 1718, 0, - 1729, 0, 0, 0, 0, 0, 430, 0, 442, 436, - 0, 443, 438, 439, 0, 0, 461, 463, 464, 465, - 466, 450, 451, 794, 414, 415, 416, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 0, 410, 411, 412, - 413, 0, -2, 0, 0, 419, 180, 467, 0, 469, - 0, 474, 0, 476, 0, 88, 478, 0, 688, 0, - 1113, 0, 0, 1113, 1113, 0, 0, 1113, 0, 706, - 774, 775, 1114, 710, 0, 0, 717, 2536, 1372, 722, - 1113, 1113, 729, 723, 730, 778, 731, 732, 733, 776, - 1113, 1113, 1022, 0, 773, 776, 758, 777, 776, 1729, - 762, 0, 767, 770, 771, 1729, 790, 1729, 0, 788, - 737, 738, 379, 380, 0, 0, 0, 226, 227, 228, - 229, 230, 231, 233, 217, 825, 827, 1384, 0, 1375, - 0, 236, 277, 209, 0, 0, 0, 0, 2166, 2167, - 2168, 2169, 2174, 0, 0, 2177, 2180, 2183, 2186, 0, - 2212, -2, -2, 1869, 1870, 1871, 1872, 1873, 1874, 1875, - 1876, 1877, 1878, 1879, 1880, 1881, 1882, 2189, 2210, 2211, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2209, 2206, 2206, 2199, 0, 1887, 1903, 1947, - 1960, 1960, 1912, 1714, 1715, 1888, 0, 0, 1940, 1944, - 0, 0, 0, 0, 0, 0, 1434, 2325, 0, 171, - 2205, 2156, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, - 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, - 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, - 2082, 0, 0, 2165, 0, 0, 0, 0, 2158, 2159, - 0, 0, 0, 2042, 0, 0, 2048, 2049, 2050, 0, - 1783, 0, 2121, 2094, 2112, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2083, 2084, 2085, - 2086, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1019, 1028, 1154, 1156, 0, 941, 943, 944, - 984, 1026, 1026, 986, 0, 956, 1002, 0, 0, 0, - 127, 132, 0, 1537, 118, 0, 0, 0, 118, 0, - 0, 0, 118, 0, 0, 0, 1356, 1469, 89, 1355, - 1471, 0, 0, 0, 0, 0, 0, 0, 373, 374, - 0, 0, 368, 356, 2578, 358, 0, 0, 0, 0, - 0, 0, 0, 1232, 0, 0, 0, 1263, 0, 0, - 0, 1300, 1301, 0, 615, 1366, 0, 0, 0, 1382, - 1438, 1451, 0, 0, 0, 1543, 1286, 1291, 1292, 1293, - 1287, 1288, 1294, 1295, 874, 883, 0, 878, 0, 884, - 0, 0, 917, 937, 912, 0, 921, 0, 0, 0, - 1013, 0, 0, 1169, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1161, 0, 0, 0, 1160, 0, 0, - 0, 0, 0, 0, 0, 1015, 1196, 0, 1198, 1199, - 1173, -2, 0, 1124, 1126, 0, 1178, 2161, 0, 0, - 1545, 1015, 508, 509, 510, 520, 522, 0, 581, 581, - 581, 581, 564, 0, 0, 552, 2346, 0, 0, 0, - 0, 561, 2346, 0, 0, 2346, 2346, 2346, 2346, 2346, - 2346, 2346, 2346, 0, 0, 2346, 2346, 2346, 2346, 2346, - 2346, 2346, 2346, 2346, 2346, 2346, 0, 2346, 2346, 2346, - 2346, 2346, 1698, 2346, 0, 1468, 571, 572, 573, 574, - 579, 580, 0, 0, 525, 526, 0, 0, 0, 0, - 0, 610, 0, 0, 1299, 0, 615, 0, 0, 1344, - 0, 0, 1126, 0, 0, 0, 0, 309, 310, 298, - 0, 299, 0, 0, 312, 313, 0, 315, 316, 317, - 324, 2437, 2556, 319, 321, 0, 0, 325, 338, 339, - 340, 0, 0, 330, 331, 0, 0, 394, 395, 397, - 0, 1026, 1066, 1032, 1033, 1036, 0, 0, 1069, 1071, - 1072, 1073, 1074, 1470, 1458, 85, 86, 2761, 819, 0, - 0, 822, 823, 824, 828, 0, 0, 1571, 832, 833, - 0, 0, 1353, 0, 1357, 1359, 1458, 1121, 0, 1118, - 1201, 0, 1203, 0, 0, 150, 18, 0, 143, 140, - 0, 0, 0, 0, 0, 2303, 2241, 2342, 0, 0, - 0, 0, 2323, 0, 0, 2263, 0, 0, 0, 133, - 156, 963, 1026, 956, 0, 958, 182, 956, 992, 892, - 937, 865, 0, 921, 0, 0, 0, 0, 0, 1720, - 0, 0, 0, 0, 1792, 0, 444, 440, 460, 0, - 409, 0, 0, 471, 0, 1717, 477, 480, 685, 0, - 687, 690, 773, 0, 693, 694, 773, 0, 0, 700, - 705, 713, 711, 0, 715, 0, 716, 0, 1374, 773, - 724, 725, 1113, 748, 749, 0, 0, 0, 1113, 773, - 773, 761, 776, 785, 0, 786, 1729, 0, 220, 1369, - 0, 221, 225, 215, 0, 0, 0, 1371, 1376, 0, - 235, 0, 0, 210, 211, 1528, 1537, 0, 0, 0, - 158, 2175, 2178, 2181, 2184, 2176, 2179, 2182, 2185, 2187, - 0, 2190, 2206, 2206, 2200, 0, 2191, 2206, 2206, 2201, - 0, 0, 2193, 0, 2196, 0, 1948, 1961, 1962, 1949, - 2166, 1895, 0, 1945, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1036, 0, 0, 0, 2030, 2032, 0, - 0, 0, 2037, 0, 2039, 2040, 2041, 2043, 0, 0, - 0, 2047, 0, 2092, 2113, 2096, 2099, 0, 2103, 0, - 2105, 2107, 2108, 2109, 0, 0, 0, 1028, 1030, 1030, - 1028, 0, 0, 1987, 1987, 1030, 0, 0, 0, 0, - 1987, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1917, 0, 1918, 1919, 1920, - 0, 1922, 2857, 0, 2857, 0, 2857, 2857, 0, 0, - 0, 1026, 1019, 0, 1157, 956, 956, 0, 987, 996, - 0, 0, 0, 0, 0, 0, 1535, 0, 108, 0, - 113, 0, 0, 109, 114, 0, 0, 111, 0, 0, - 120, 90, 0, 0, 1476, 1477, 0, 0, 0, 375, - 363, 365, 0, 357, 0, 1456, 1457, 0, 0, 0, - 1617, 1627, 1236, 0, 0, -2, 1265, 0, 1015, 1015, - 1311, 2346, 0, 619, 0, 0, 1368, 0, 1333, 0, - 0, 0, -2, 0, 0, -2, 0, 0, 1547, 0, - 875, 881, 0, 0, 0, 876, 892, 918, 0, 911, - 934, 0, 938, 0, 0, 925, 927, 916, 922, 0, - 0, 0, 952, 892, 892, 23, 1016, 0, 0, 0, - 845, 849, 0, 1165, 1165, 1165, 1134, 0, 0, 1137, - 1162, 1138, 1163, 0, 0, 1142, 0, 1144, 0, 1146, - 0, 1140, 1141, 1148, 1149, 0, 1139, 1172, 1197, 0, - 1174, 0, 1177, 1179, 1180, 1186, 0, 0, 0, 0, - 0, 0, 504, 505, 1547, 0, 0, 1467, 1614, 0, - 0, 551, 582, 0, 0, 0, 1581, 542, 0, 1742, - 1743, 0, 1750, 1759, 1759, 1455, 1832, 0, 1759, 0, - 0, 1761, 1762, 0, 0, 0, 0, 565, 566, 0, - 0, 550, 0, 0, 592, 0, 0, 0, 0, 0, - 2347, 2346, 2346, 0, 559, 560, 0, 563, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2346, 2346, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1689, 0, 0, 0, 0, 0, 0, 0, 1704, 1705, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1311, - 2346, 0, 0, 0, 0, 619, 1363, 1363, 1331, 1349, - 0, 513, 514, 589, 0, 0, 0, 302, 303, 0, - 0, 308, 326, 328, 300, 0, 0, 0, 327, 329, - 333, 334, 393, 396, 398, 956, 0, 1039, 1037, 1038, - 1059, 1067, 82, 1459, 820, 821, 0, 1571, 831, 1572, - 1573, 1265, 837, 1354, 0, 1361, 1113, 1122, 0, 1116, - 1202, 1204, 171, 1119, 0, 153, 18, 152, 144, 145, - 0, 18, 0, 0, 0, 0, 2245, 2331, 2330, 2295, - 0, 2296, 2328, 2333, 0, 2336, 0, 485, 0, 967, - 0, 956, 993, 959, 0, 991, 863, 0, 864, 0, - 0, 869, 0, 952, 1358, 1721, 1722, 0, 1725, 1726, - 1727, 1728, 1719, 0, 0, 0, 0, 0, 0, 0, - 795, 181, 473, 689, 1113, 773, 1113, 0, 773, 773, - 701, 1624, 1625, 712, 718, 1373, 1113, 742, 1023, 1024, - 754, 756, 1729, 1113, 1113, 773, 791, 787, 0, 0, - 0, 0, 0, 826, 0, 217, 0, 0, 237, 0, - 0, 0, 1537, 1532, 2160, 2194, 2197, 0, 2195, 2198, - 0, 0, 2207, 2202, 1889, 1899, 1941, 0, 0, 0, - 0, 0, 1950, 1951, 2329, 2329, 1954, 2325, 2327, 2325, - 1960, 1960, 0, 1435, 0, 1436, 1036, 172, 0, 0, - 0, 0, 1987, 0, 0, 0, 1784, 0, 0, 0, - 0, 0, 1983, 1987, 0, 1987, 1985, 1987, 1987, 2005, - 1988, 2006, 1987, 1987, 1987, 1987, 1987, 2012, 1987, 1987, - 1987, 1987, 1987, 1987, 1987, 1987, 0, 1987, 1987, 1987, - 1987, 0, 1989, 1992, 1921, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2230, 2231, 956, 1026, 942, - 988, 985, 0, 0, 0, 0, 0, 71, 71, 1537, - 0, 0, 0, 0, 0, 126, 0, 0, 0, 0, - 0, 0, 0, 1485, 1493, 0, 367, 0, 91, 92, - 94, 0, 0, 0, 0, 0, 0, 0, 107, 1229, - 0, 1230, 0, 1240, 0, 1234, 0, 0, 1251, 1252, - 1254, 0, 1257, 1258, 1259, 0, 1266, 1267, 1269, 1270, - 0, 2352, -2, -2, 2483, -2, -2, -2, -2, -2, + -2, -2, -2, -2, 2421, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, - 2411, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, - -2, -2, -2, -2, -2, -2, -2, -2, -2, 1264, - 0, 0, 1315, 1312, 1313, 1314, 0, 0, 1363, 620, - 621, 622, 623, 0, 0, 0, 1367, 0, 0, 0, - 1324, 0, 0, 0, 1439, 1440, 1441, 1442, 1443, 1444, - 1445, 1446, 1447, 1448, -2, 1462, 0, 1729, 0, 0, - 1735, 1517, 0, 0, 0, 1524, 0, 0, 981, 0, - -2, -2, 1735, 1515, 2346, 1735, 1555, 0, 1544, 0, - 0, 879, 888, 0, 937, 939, 0, 0, 937, 0, - 0, 0, 948, 0, 949, 0, 0, 889, 890, 892, - 0, 1170, 945, 0, -2, 0, 0, 847, 0, 0, - 1131, 1166, 0, 0, 1132, 1133, 1135, 1152, 1164, 0, - 1158, 1143, 1145, 1147, 1150, 0, 1125, 0, 1181, 0, - 0, 1183, 1184, 1185, 1176, 500, 0, 1619, 0, 1622, - 1623, 502, 0, 1629, 0, 1632, 1633, 1555, 1546, 0, - 521, 581, 581, 0, 1602, 0, 0, 1608, 0, 1615, - 0, 0, 0, 0, 0, 535, 0, 583, 0, 1749, - 1780, 1760, 1780, 1780, 1833, 1780, 1780, 1455, 0, 583, - 0, 0, 553, 549, 586, 1036, 536, 538, 539, 540, - 590, 591, 593, 0, 595, 596, 555, 567, 568, 569, - 570, 0, 0, 0, 562, 575, 576, 577, 578, 537, - 1665, 1666, 1667, 1668, 1671, 1672, 1673, 1674, 0, 0, - 1677, 1678, 1679, 1680, 1681, 1777, 1778, 1779, 1682, 1683, - 1684, 1685, 1686, 1687, 1688, 1706, 1707, 1708, 1709, 1710, - 1711, 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 0, - 0, 1701, 0, 0, 1234, 0, 529, 530, 0, 532, - 0, 0, 1315, 0, 0, 0, 0, 0, 1363, 613, - 0, 0, 614, 1333, 0, 1351, 0, 1345, 1346, 0, - 0, 909, 1113, 386, 0, 1113, 296, 305, 306, 307, - 314, 0, 639, 320, 1042, 1034, 1035, 0, 829, 830, - 0, 0, 1104, 1123, 0, 148, 151, 0, 146, 0, - 0, 0, 0, 138, 136, 2324, 0, 0, 157, 969, - 197, 0, 0, 1042, 961, 0, 183, 893, 0, 937, - 946, 0, 1730, 1731, 1732, 1733, 0, 1793, 431, 691, - 1113, 695, 773, 1113, 1113, 0, 719, 759, 763, 760, - 1113, 0, 1370, 217, 222, 223, 224, 218, 216, 1377, - 0, 1379, 0, 1530, 0, 0, 2203, 2204, 2192, 1946, - 1900, 0, 1902, 1904, 1952, 1953, 1955, 1956, 1957, 1958, - 1959, 1905, 0, 1437, 2031, 2033, 0, 2035, 2036, 2038, - 2044, 2045, 0, 0, 2100, 2104, 0, 0, 2091, 0, - 0, 2000, 0, 2001, 0, 0, 2003, 2004, 2007, 2008, - 2009, 2010, 2011, 2013, 2014, 2015, 2016, 2017, 2018, 2019, - 2020, 0, 2022, 2023, 2024, 2025, 0, 0, 1981, 1993, - 1923, 2858, 2857, 0, 1926, 2857, 0, 1929, 1930, 2859, - 0, 0, 0, 0, 0, 0, 1042, 956, 1027, 0, - 0, 1005, 1006, 1007, 1008, 1009, 1001, 0, 0, 73, - 0, 73, 1536, 1538, 119, 121, 0, 115, 116, 117, - 0, 0, 1200, 1499, 1729, 1487, 0, 1479, 0, 1493, - 0, 0, 0, 93, 0, 95, 0, 2539, 0, 0, - 0, 0, 1458, 0, 0, 1242, 0, 0, 1233, 0, - 1244, 1260, 1256, 0, 0, 0, 1271, 0, 0, 1282, - 0, 0, 1303, 1304, 1305, 1329, 1317, 0, 625, 626, - 0, 0, 0, 638, 634, 635, 636, 616, 1362, 1340, - 0, 0, 1340, 1327, 0, 0, 1339, 0, 1463, 2346, - 2346, 2346, 1499, 0, 0, 0, 1736, 1737, 1739, 1740, - 1741, 1519, 0, 1523, 1501, 0, 1028, 0, 0, 0, - 1558, 0, 0, 1549, 0, 0, 886, 0, 935, 0, - 940, 937, 915, 926, 914, 928, 923, 924, 953, 0, - 950, 891, 1014, 1195, 0, 0, 1113, 846, 849, 850, - 0, 1167, 0, 1136, 0, 1159, 1151, 1127, 1190, 1187, - 0, 0, 0, 0, 0, 0, 0, 0, 1558, 507, - 1579, 0, 0, 0, 0, 0, 1612, 0, 1400, 1400, - 1400, 1400, 1400, 0, 0, 597, 0, 601, 602, 599, - 1827, 0, 0, 600, 0, 1583, 0, 554, 584, 0, - -2, 0, 1781, 0, 0, 1763, 1781, 0, 0, 1780, - 0, 543, 583, 0, 0, 588, 0, 594, 1669, 1670, - 0, 1675, 1676, 0, 1700, 0, 0, 524, 527, 0, - 1238, 1239, -2, 0, 0, 0, 605, 0, 0, 0, - 606, 607, 612, 1364, 1365, 1324, 0, 1340, 0, 1350, - 0, 1347, 1348, 1028, 0, 0, 0, 892, 322, 983, - 0, 0, 1040, 1041, 835, 0, 1102, 0, 1120, 0, - 18, 0, 0, 141, 2334, 2337, 971, 0, 968, 198, - 0, 0, 0, 989, 963, 0, 960, 937, 868, 867, - 0, 1724, 1734, 692, 1113, 697, 698, 0, 764, 219, - 214, 1378, 1540, 0, 1531, 0, 1852, 1914, 1915, 1916, - 0, 2046, 1785, 0, 0, 1030, 1984, 0, 1987, 1986, - 0, 1987, 1990, 1028, 1982, 0, 0, 0, 0, 0, - 2857, 0, 1932, 0, 1934, 1935, 1936, 0, 1938, 1939, - 2300, 1042, 1003, 0, 999, 0, 69, 0, 72, 70, - 0, 0, 0, 125, 1474, 0, 1499, 1478, 0, 0, - 0, 1480, 0, 0, 0, 0, 0, 96, 0, 0, - 0, 0, 0, 0, 105, 0, 0, 0, 0, 1241, - 0, 1235, 0, 0, 1253, 1255, 0, 1268, 0, 1289, - 1289, 1316, 1302, 0, 1283, 0, 0, 627, 628, 0, - 631, 637, 1318, 0, 0, 1321, 1322, 1320, 1323, 0, - 0, 1337, 0, 0, 0, 0, 1449, 0, 1452, -2, - 0, 1521, 1499, 0, 0, 1019, 0, 1617, -2, 1564, - 0, 1556, 0, 1548, 0, 1551, 885, 0, 0, 920, - 936, 913, 0, 0, 1113, 1113, -2, 892, 848, 0, - 896, 898, 0, 0, 1153, 0, 0, 1191, 1193, 1188, - 1189, 1620, 501, 1621, 1630, 503, 1631, 1634, 1635, 1564, - 1581, 0, 1603, 0, 0, 0, 0, 0, 0, 0, - 515, 516, 517, 518, 519, 0, 547, 548, 1400, 0, - 1828, 1829, 1582, 0, 1596, 585, 1782, -2, 1796, 1798, - 0, 0, 1468, 1802, 1803, 0, 0, 0, 0, 0, - 0, 0, 0, 1860, 1813, 0, 0, 0, 1818, 1819, - 1820, 0, 0, 0, 0, 2224, 2225, 0, 1831, 0, - 0, 0, 0, 0, 0, 0, 0, 1757, 544, 545, - 587, 541, 2346, 557, 1699, 1702, 1703, 528, 531, 0, - 0, 611, 608, 609, 1327, 1332, 1343, 1352, 910, 1017, - 1113, 387, 388, 384, 1043, 1044, 0, 1360, 1994, 0, - 0, 142, 147, 0, 0, 973, 0, 970, 0, 964, - 966, 208, 967, 962, 866, 1723, 696, 773, 166, 200, - 0, 0, 1901, 0, 0, 0, 2034, 2089, 2090, 1987, - 0, 2002, 1987, 2026, 1978, 0, 1924, 2857, 1927, 2857, - 0, 2860, 0, 0, 2301, 0, 997, 74, 123, 122, - 0, 0, 1475, 0, 0, 0, 1491, 1492, 0, 1494, - 1495, 1496, 0, 0, 0, 0, 78, 0, 0, 0, - 1458, 0, 1458, 0, 0, 0, 1618, 1628, 0, 1243, - 1237, 1247, 1261, 0, 1274, 1272, 1281, 1296, 1280, 0, - 0, 0, 624, 629, 0, 632, 633, 1341, 1340, 0, - 1325, 1326, 0, 1335, 0, 0, 1464, 1465, 1466, 1329, - 1574, 1518, 0, 0, -2, 1662, 0, 1738, 1525, 1502, - 0, 982, 1509, 1510, 1511, 1512, 1513, 1514, 1540, 2346, - 1616, 1574, 1552, 0, 1559, 0, 1557, 1550, 0, 919, - 929, 951, 1028, 892, 843, 0, 899, 907, 0, 0, - 906, 1168, 1182, 0, 1561, 523, 1614, 1604, 0, 1606, - 0, 0, 0, 0, 1401, 2346, 2346, 0, 0, 0, - 1407, 1408, 2346, 2346, 2346, 2346, 2346, 2346, 0, 0, - 0, 2346, 2346, 2346, 2346, 2346, 2346, 0, 1426, 1427, - 1428, 0, 2346, 2346, 2346, 546, 598, 0, 1584, -2, - 0, 1797, 1799, 1800, 1801, 1804, 1805, 1806, 1807, 1808, - 1865, 1866, 1867, 0, 0, 1811, 1862, 1863, 1864, 1812, - 0, 0, 0, 1817, 0, 0, 0, 2222, 2223, 1858, - 0, 0, 0, 1764, 1766, 1767, 1768, 1769, 1770, 1771, - 1772, 1773, 1774, 1775, 1776, 1765, 0, 0, 0, 1756, - 1758, 0, 2346, 0, 0, 1342, 892, 892, 0, 1087, - 0, 1103, 1111, 2779, 2781, 2778, 137, 139, 154, 0, - 972, 199, 0, 969, 1113, 168, 0, 191, 0, 1541, - 0, 1913, 0, 0, 0, 0, 1999, 1031, 2021, 1991, - 1979, 0, 1973, 1974, 1975, 1980, 0, 0, 1931, 1933, - 1937, 1004, 0, 1500, 1488, 1489, 1490, 1486, 0, 0, - 1497, 1498, 0, 76, 0, 99, 0, 0, 100, 1458, - 101, 1458, 0, 0, 1231, 0, 0, 1297, 1298, 1306, - 1307, 0, 1309, 1310, 1330, 630, 1319, 1328, 1334, 1337, - 0, 1400, 1450, 1576, 0, 1520, 0, 1467, 1664, 2346, - 1329, 1527, 0, 1576, 1542, 0, 1554, 0, 1566, 0, - 1560, 0, 1017, 844, 897, 0, 0, 907, 907, 1192, - 1194, 506, 0, 1563, 1600, 1605, 1607, 1609, 0, 1613, - 1611, 0, 0, 1404, 1405, 0, 0, 0, 0, 0, - 0, 0, 0, 1416, 1417, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 603, 604, 1585, -2, - 0, 1593, 1595, 0, 0, 1809, 1810, 0, 0, 2110, - 2346, 0, 0, 1847, 0, 1400, 1400, 1400, 1400, 1400, - 0, 556, 0, 0, 534, 383, 385, 1045, 1995, 1996, - 0, 1105, 0, 0, 0, 0, 0, 0, 971, 699, - 155, 0, 167, 188, 0, 201, 202, 0, 0, 0, - 0, 1533, 0, 1855, 1857, 1856, 1976, 0, 0, 0, - 0, 0, 0, 2226, 2227, 2228, 1925, 1928, 124, 1493, - 1493, 1458, 78, 0, 98, 0, 102, 103, 0, 1458, - 0, 1273, 0, 1308, 1336, 1338, 1399, 1508, 0, 1614, - 1522, 1663, 0, 1526, 1627, 1637, 1651, 1644, 1649, 1650, - 1516, 1553, 1565, 0, 1568, 887, 892, 0, 908, 0, - 0, 1562, 1580, 0, 1610, 1402, 1403, 1406, 1409, 1410, - 1411, 1412, 1413, 1414, 0, 1418, 1419, 1420, 1421, 1422, - 1423, 1424, 1425, 1429, 1430, 1431, 1432, 1433, 1586, 1594, - 0, 1589, 0, 0, 0, 1861, 0, 1816, 0, 0, - 1824, 1835, 1848, 0, 0, 1744, 0, 1746, 1747, 0, - 1751, 0, 1753, 0, 0, 558, 533, 0, 0, 1112, - 0, 0, 0, 0, 975, 965, 973, 169, 173, 0, - 197, 194, 0, 203, 0, 0, 0, 0, 1529, 0, - 1853, 0, 1963, 0, 0, 0, 0, 1968, 1969, 1970, - 1971, 1972, 1481, 1493, 1482, 1493, 75, 77, 79, 97, - 1458, 104, 0, 1275, 1276, 1290, 0, 1602, 1669, 1626, - 1636, 0, 1642, 0, 1643, 0, 1567, 842, 0, 901, - 0, 0, 1601, 1415, 1588, 0, -2, 1597, 0, 0, - 2163, 2172, 2173, 1814, 1821, 0, 1823, 1825, 1826, 1834, - 1836, 1837, 0, 1849, 1850, 1851, 1859, 1400, 1400, 1400, - 1400, 1755, 1997, 1992, 0, 2161, 1107, 1108, 974, 0, - 957, 160, 0, 0, 192, 193, 195, 0, 204, 0, - 206, 207, 0, 0, 0, 1964, 1965, 1966, 1967, 1483, - 1484, 106, 1277, 1577, 0, 1579, 0, 0, 0, 0, - 0, 0, 1590, -2, 0, 1599, 0, 1815, 1824, 1838, - 0, 1839, 0, 0, 0, 1745, 1748, 1752, 1754, 0, - 1106, 0, 0, 976, 1539, 0, 174, 0, 176, 178, - 179, 189, 190, 196, 205, 0, 0, 1977, 1262, 1278, - 0, 0, 1581, 0, 1639, 0, 1656, 1657, 0, 1653, - 0, 0, 1646, 0, 900, 0, 0, 0, 0, 1598, - 2164, 1822, 1840, 1842, 1843, 0, 0, 1841, 1998, 2161, - 1109, 161, 162, 0, 175, 0, 1534, 1854, 1279, 1578, - 1575, 1638, 0, 0, 1652, 0, 0, 1645, 0, 0, - 0, 930, 0, 0, 0, 1844, 1846, 1845, 0, 0, - 0, 177, 1640, 1641, 1658, 1659, 1654, 1655, 1647, 1648, - 0, 0, 0, 0, 0, 0, 1110, 163, 164, 165, - 0, 932, 931, 904, 0, 905, 0, 0, 0, 0, - 933, 0, 902, 903, + -2, -2, -2, 1264, 0, 0, 1324, 1321, 1322, 1323, + 0, 0, 1372, 620, 621, 622, 623, 0, 0, 0, + 1376, 0, 0, 0, 1333, 0, 0, 0, 1448, 1449, + 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, -2, 1471, + 0, 1738, 0, 0, 1744, 1526, 0, 0, 0, 1533, + 0, 0, 981, 0, -2, -2, 1744, 1524, 2355, 1744, + 1564, 0, 1553, 0, 0, 879, 888, 0, 937, 939, + 0, 0, 937, 0, 0, 0, 948, 0, 949, 0, + 0, 889, 890, 892, 0, 1170, 945, 0, -2, 0, + 0, 847, 0, 0, 1131, 1166, 0, 0, 1132, 1133, + 1135, 1152, 1164, 0, 1158, 1143, 1145, 1147, 1150, 0, + 1125, 0, 1181, 0, 0, 1183, 1184, 1185, 1176, 500, + 0, 1628, 0, 1631, 1632, 502, 0, 1638, 0, 1641, + 1642, 1564, 1555, 0, 521, 581, 581, 0, 1611, 0, + 0, 1617, 0, 1624, 0, 0, 0, 0, 0, 535, + 0, 583, 0, 1758, 1789, 1769, 1789, 1789, 1842, 1789, + 1789, 1464, 0, 583, 0, 0, 553, 549, 586, 1036, + 536, 538, 539, 540, 590, 591, 593, 0, 595, 596, + 555, 567, 568, 569, 570, 0, 0, 0, 562, 575, + 576, 577, 578, 537, 1674, 1675, 1676, 1677, 1680, 1681, + 1682, 1683, 0, 0, 1686, 1687, 1688, 1689, 1690, 1786, + 1787, 1788, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1715, + 1716, 1717, 1718, 1719, 1720, 1699, 1700, 1701, 1702, 1703, + 1704, 1705, 1706, 0, 0, 1710, 0, 0, 1234, 0, + 529, 530, 0, 532, 0, 0, 1324, 0, 0, 0, + 0, 0, 1372, 613, 0, 0, 614, 1342, 0, 1360, + 0, 1354, 1355, 0, 0, 909, 1113, 386, 0, 1113, + 296, 305, 306, 307, 314, 0, 639, 320, 1042, 1034, + 1035, 0, 829, 830, 0, 0, 1104, 1123, 0, 148, + 151, 0, 146, 0, 0, 0, 0, 138, 136, 2333, + 0, 0, 157, 969, 197, 0, 0, 1042, 961, 0, + 183, 893, 0, 937, 946, 0, 1739, 1740, 1741, 1742, + 0, 1802, 431, 691, 1113, 695, 773, 1113, 1113, 0, + 719, 759, 763, 760, 1113, 0, 1379, 217, 222, 223, + 224, 218, 216, 1386, 0, 1388, 0, 1539, 0, 0, + 2212, 2213, 2201, 1955, 1909, 0, 1911, 1913, 1961, 1962, + 1964, 1965, 1966, 1967, 1968, 1914, 0, 1446, 2040, 2042, + 0, 2044, 2045, 2047, 2053, 2054, 0, 0, 2109, 2113, + 0, 0, 2100, 0, 0, 2009, 0, 2010, 0, 0, + 2012, 2013, 2016, 2017, 2018, 2019, 2020, 2022, 2023, 2024, + 2025, 2026, 2027, 2028, 2029, 0, 2031, 2032, 2033, 2034, + 0, 0, 1990, 2002, 1932, 2871, 2870, 0, 1935, 2870, + 0, 1938, 1939, 2872, 0, 0, 0, 0, 0, 0, + 1042, 956, 1027, 0, 0, 1005, 1006, 1007, 1008, 1009, + 1001, 0, 0, 73, 0, 73, 1545, 1547, 119, 121, + 0, 115, 116, 117, 0, 0, 1200, 1508, 1738, 1496, + 0, 1488, 0, 1502, 0, 0, 0, 93, 0, 95, + 0, 2551, 0, 0, 0, 0, 1467, 0, 0, 1242, + 0, 0, 1233, 0, 1244, 1260, 1256, 0, 0, 0, + 1271, 0, 0, 1291, 0, 0, 1312, 1313, 1314, 1338, + 1326, 0, 625, 626, 0, 0, 0, 638, 634, 635, + 636, 616, 1371, 1349, 0, 0, 1349, 1336, 0, 0, + 1348, 0, 1472, 2355, 2355, 2355, 1508, 0, 0, 0, + 1745, 1746, 1748, 1749, 1750, 1528, 0, 1532, 1510, 0, + 1028, 0, 0, 0, 1567, 0, 0, 1558, 0, 0, + 886, 0, 935, 0, 940, 937, 915, 926, 914, 928, + 923, 924, 953, 0, 950, 891, 1014, 1195, 0, 0, + 1113, 846, 849, 850, 0, 1167, 0, 1136, 0, 1159, + 1151, 1127, 1190, 1187, 0, 0, 0, 0, 0, 0, + 0, 0, 1567, 507, 1588, 0, 0, 0, 0, 0, + 1621, 0, 1409, 1409, 1409, 1409, 1409, 0, 0, 597, + 0, 601, 602, 599, 1836, 0, 0, 600, 0, 1592, + 0, 554, 584, 0, -2, 0, 1790, 0, 0, 1772, + 1790, 0, 0, 1789, 0, 543, 583, 0, 0, 588, + 0, 594, 1678, 1679, 0, 1684, 1685, 0, 1709, 0, + 0, 524, 527, 0, 1238, 1239, -2, 0, 0, 0, + 605, 0, 0, 0, 606, 607, 612, 1373, 1374, 1333, + 0, 1349, 0, 1359, 0, 1356, 1357, 1028, 0, 0, + 0, 892, 322, 983, 0, 0, 1040, 1041, 835, 0, + 1102, 0, 1120, 0, 18, 0, 0, 141, 2343, 2346, + 971, 0, 968, 198, 0, 0, 0, 989, 963, 0, + 960, 937, 868, 867, 0, 1733, 1743, 692, 1113, 697, + 698, 0, 764, 219, 214, 1387, 1549, 0, 1540, 0, + 1861, 1923, 1924, 1925, 0, 2055, 1794, 0, 0, 1030, + 1993, 0, 1996, 1995, 0, 1996, 1999, 1028, 1991, 0, + 0, 0, 0, 0, 2870, 0, 1941, 0, 1943, 1944, + 1945, 0, 1947, 1948, 2309, 1042, 1003, 0, 999, 0, + 69, 0, 72, 70, 0, 0, 0, 125, 1483, 0, + 1508, 1487, 0, 0, 0, 1489, 0, 0, 0, 0, + 0, 96, 0, 0, 0, 0, 0, 0, 105, 0, + 0, 0, 0, 1241, 0, 1235, 0, 0, 1253, 1255, + 0, 1268, 0, 1298, 1298, 1325, 1311, 0, 1292, 0, + 0, 627, 628, 0, 631, 637, 1327, 0, 0, 1330, + 1331, 1329, 1332, 0, 0, 1346, 0, 0, 0, 0, + 1458, 0, 1461, -2, 0, 1530, 1508, 0, 0, 1019, + 0, 1626, -2, 1573, 0, 1565, 0, 1557, 0, 1560, + 885, 0, 0, 920, 936, 913, 0, 0, 1113, 1113, + -2, 892, 848, 0, 896, 898, 0, 0, 1153, 0, + 0, 1191, 1193, 1188, 1189, 1629, 501, 1630, 1639, 503, + 1640, 1643, 1644, 1573, 1590, 0, 1612, 0, 0, 0, + 0, 0, 0, 0, 515, 516, 517, 518, 519, 0, + 547, 548, 1409, 0, 1837, 1838, 1591, 0, 1605, 585, + 1791, -2, 1805, 1807, 0, 0, 1477, 1811, 1812, 0, + 0, 0, 0, 0, 0, 0, 0, 1869, 1822, 0, + 0, 0, 1827, 1828, 1829, 0, 0, 0, 0, 2233, + 2234, 0, 1840, 0, 0, 0, 0, 0, 0, 0, + 0, 1766, 544, 545, 587, 541, 2355, 557, 1708, 1711, + 1712, 528, 531, 0, 0, 611, 608, 609, 1336, 1341, + 1352, 1361, 910, 1017, 1113, 387, 388, 384, 1043, 1044, + 0, 1369, 2003, 0, 0, 142, 147, 0, 0, 973, + 0, 970, 0, 964, 966, 208, 967, 962, 866, 1732, + 696, 773, 166, 200, 0, 0, 1910, 0, 0, 0, + 2043, 2098, 2099, 1996, 0, 2011, 1996, 2035, 1987, 0, + 1933, 2870, 1936, 2870, 0, 2873, 0, 0, 2310, 0, + 997, 74, 123, 122, 0, 0, 1484, 0, 0, 0, + 1500, 1501, 0, 1503, 1504, 1505, 0, 0, 0, 0, + 78, 0, 0, 0, 1467, 0, 1467, 0, 0, 0, + 1627, 1637, 0, 1243, 1237, 1247, 1261, 0, 1274, 1272, + 1290, 1305, 1289, 0, 0, 0, 624, 629, 0, 632, + 633, 1350, 1349, 0, 1334, 1335, 0, 1344, 0, 0, + 1473, 1474, 1475, 1338, 1583, 1527, 0, 0, -2, 1671, + 0, 1747, 1534, 1511, 0, 982, 1518, 1519, 1520, 1521, + 1522, 1523, 1549, 2355, 1625, 1583, 1561, 0, 1568, 0, + 1566, 1559, 0, 919, 929, 951, 1028, 892, 843, 0, + 899, 907, 0, 0, 906, 1168, 1182, 0, 1570, 523, + 1623, 1613, 0, 1615, 0, 0, 0, 0, 1410, 2355, + 2355, 0, 0, 0, 1416, 1417, 2355, 2355, 2355, 2355, + 2355, 2355, 0, 0, 0, 2355, 2355, 2355, 2355, 2355, + 2355, 0, 1435, 1436, 1437, 0, 2355, 2355, 2355, 546, + 598, 0, 1593, -2, 0, 1806, 1808, 1809, 1810, 1813, + 1814, 1815, 1816, 1817, 1874, 1875, 1876, 0, 0, 1820, + 1871, 1872, 1873, 1821, 0, 0, 0, 1826, 0, 0, + 0, 2231, 2232, 1867, 0, 0, 0, 1773, 1775, 1776, + 1777, 1778, 1779, 1780, 1781, 1782, 1783, 1784, 1785, 1774, + 0, 0, 0, 1765, 1767, 0, 2355, 0, 0, 1351, + 892, 892, 0, 1087, 0, 1103, 1111, 2792, 2794, 2791, + 137, 139, 154, 0, 972, 199, 0, 969, 1113, 168, + 0, 191, 0, 1550, 0, 1922, 0, 0, 0, 0, + 2008, 1031, 2030, 2000, 1988, 0, 1982, 1983, 1984, 1989, + 0, 0, 1940, 1942, 1946, 1004, 0, 1509, 1497, 1498, + 1499, 1495, 0, 0, 1506, 1507, 0, 76, 0, 99, + 0, 0, 100, 1467, 101, 1467, 0, 0, 1231, 0, + 0, 1306, 1307, 1315, 1316, 0, 1318, 1319, 1339, 630, + 1328, 1337, 1343, 1346, 0, 1409, 1459, 1585, 0, 1529, + 0, 1476, 1673, 2355, 1338, 1536, 0, 1585, 1551, 0, + 1563, 0, 1575, 0, 1569, 0, 1017, 844, 897, 0, + 0, 907, 907, 1192, 1194, 506, 0, 1572, 1609, 1614, + 1616, 1618, 0, 1622, 1620, 0, 0, 1413, 1414, 0, + 0, 0, 0, 0, 0, 0, 0, 1425, 1426, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 603, 604, 1594, -2, 0, 1602, 1604, 0, 0, 1818, + 1819, 0, 0, 2119, 2355, 0, 0, 1856, 0, 1409, + 1409, 1409, 1409, 1409, 0, 556, 0, 0, 534, 383, + 385, 1045, 2004, 2005, 0, 1105, 0, 0, 0, 0, + 0, 0, 971, 699, 155, 0, 167, 188, 0, 201, + 202, 0, 0, 0, 0, 1542, 0, 1864, 1866, 1865, + 1985, 0, 0, 0, 0, 0, 0, 2235, 2236, 2237, + 1934, 1937, 124, 1502, 1502, 1467, 78, 0, 98, 0, + 102, 103, 0, 1467, 0, 1273, 0, 1317, 1345, 1347, + 1408, 1517, 0, 1623, 1531, 1672, 0, 1535, 1636, 1646, + 1660, 1653, 1658, 1659, 1525, 1562, 1574, 0, 1577, 887, + 892, 0, 908, 0, 0, 1571, 1589, 0, 1619, 1411, + 1412, 1415, 1418, 1419, 1420, 1421, 1422, 1423, 0, 1427, + 1428, 1429, 1430, 1431, 1432, 1433, 1434, 1438, 1439, 1440, + 1441, 1442, 1595, 1603, 0, 1598, 0, 0, 0, 1870, + 0, 1825, 0, 0, 1833, 1844, 1857, 0, 0, 1753, + 0, 1755, 1756, 0, 1760, 0, 1762, 0, 0, 558, + 533, 0, 0, 1112, 0, 0, 0, 0, 975, 965, + 973, 169, 173, 0, 197, 194, 0, 203, 0, 0, + 0, 0, 1538, 0, 1862, 0, 1972, 0, 0, 0, + 0, 1977, 1978, 1979, 1980, 1981, 1490, 1502, 1491, 1502, + 75, 77, 79, 97, 1467, 104, 0, 1275, 1276, 1299, + 0, 1611, 1678, 1635, 1645, 0, 1651, 0, 1652, 0, + 1576, 842, 0, 901, 0, 0, 1610, 1424, 1597, 0, + -2, 1606, 0, 0, 2172, 2181, 2182, 1823, 1830, 0, + 1832, 1834, 1835, 1843, 1845, 1846, 0, 1858, 1859, 1860, + 1868, 1409, 1409, 1409, 1409, 1764, 2006, 2001, 0, 2170, + 1107, 1108, 974, 0, 957, 160, 0, 0, 192, 193, + 195, 0, 204, 0, 206, 207, 0, 0, 0, 1973, + 1974, 1975, 1976, 1492, 1493, 106, 1277, 1586, 0, 1588, + 0, 0, 0, 0, 0, 0, 1599, -2, 0, 1608, + 0, 1824, 1833, 1847, 0, 1848, 0, 0, 0, 1754, + 1757, 1761, 1763, 0, 1106, 0, 0, 976, 1548, 0, + 174, 0, 176, 178, 179, 189, 190, 196, 205, 0, + 0, 1986, 1280, 1278, 0, 0, 1590, 0, 1648, 0, + 1665, 1666, 0, 1662, 0, 0, 1655, 0, 900, 0, + 0, 0, 0, 1607, 2173, 1831, 1849, 1851, 1852, 0, + 0, 1850, 2007, 2170, 1109, 161, 162, 0, 175, 0, + 1543, 1863, 1262, 0, 1282, 0, 0, 1279, 1587, 1584, + 1647, 0, 0, 1661, 0, 0, 1654, 0, 0, 0, + 930, 0, 0, 0, 1853, 1855, 1854, 0, 0, 0, + 177, 1281, 1285, 1286, 0, 0, 0, 1649, 1650, 1667, + 1668, 1663, 1664, 1656, 1657, 0, 0, 0, 0, 0, + 0, 1110, 163, 164, 165, 1283, 1284, 0, 0, 0, + 932, 931, 904, 0, 905, 1287, 0, 0, 0, 0, + 1288, 0, 933, 0, 902, 903, } var yyTok1 = [...]int{ @@ -13974,14 +14035,14 @@ var yyTok1 = [...]int{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 123, 3, 3, 3, 156, 146, 3, 90, 91, 153, 151, 177, 152, 176, 154, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 783, 780, - 133, 132, 134, 3, 784, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 787, 784, + 133, 132, 134, 3, 788, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 158, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 781, 145, 782, 159, + 3, 3, 3, 785, 145, 786, 159, } var yyTok2 = [...]int{ @@ -14115,7 +14176,7 @@ var yyTok3 = [...]int{ 58090, 765, 58091, 766, 58092, 767, 58093, 768, 58094, 769, 58095, 770, 58096, 771, 58097, 772, 58098, 773, 58099, 774, 58100, 775, 58101, 776, 58102, 777, 58103, 778, 58104, 779, - 0, + 58105, 780, 58106, 781, 58107, 782, 58108, 783, 0, } var yyErrorMessages = [...]struct { @@ -14465,7 +14526,7 @@ yydefault: case 3: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:1074 +//line mysql_sql.y:1077 { if yyDollar[1].statementUnion() != nil { yylex.(*Lexer).AppendStmt(yyDollar[1].statementUnion()) @@ -14473,7 +14534,7 @@ yydefault: } case 4: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:1080 +//line mysql_sql.y:1083 { yylex.(*Lexer).AppendTopLevelSemicolon(yyDollar[2].pos) if yyDollar[3].statementUnion() != nil { @@ -14483,7 +14544,7 @@ yydefault: case 5: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1089 +//line mysql_sql.y:1092 { yyLOCAL = tree.NewCompoundStmt(yyDollar[2].statementsUnion()) } @@ -14491,7 +14552,7 @@ yydefault: case 6: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.Statement -//line mysql_sql.y:1095 +//line mysql_sql.y:1098 { yyLOCAL = []tree.Statement{yyDollar[1].statementUnion()} } @@ -14499,7 +14560,7 @@ yydefault: case 7: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.Statement -//line mysql_sql.y:1099 +//line mysql_sql.y:1102 { yyLOCAL = append(yyDollar[1].statementsUnion(), yyDollar[3].statementUnion()) } @@ -14507,7 +14568,7 @@ yydefault: case 17: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1114 +//line mysql_sql.y:1117 { yyLOCAL = yyDollar[1].statementUnion() } @@ -14515,7 +14576,7 @@ yydefault: case 18: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1118 +//line mysql_sql.y:1121 { yyLOCAL = tree.Statement(nil) } @@ -14523,7 +14584,7 @@ yydefault: case 19: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1124 +//line mysql_sql.y:1127 { yyLOCAL = yyDollar[1].statementUnion() } @@ -14531,7 +14592,7 @@ yydefault: case 20: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1128 +//line mysql_sql.y:1131 { yyLOCAL = yyDollar[1].statementUnion() } @@ -14539,7 +14600,7 @@ yydefault: case 22: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1133 +//line mysql_sql.y:1136 { yyLOCAL = yyDollar[1].statementUnion() } @@ -14547,7 +14608,7 @@ yydefault: case 23: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1137 +//line mysql_sql.y:1140 { yyLOCAL = tree.Statement(nil) } @@ -14555,7 +14616,7 @@ yydefault: case 58: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1177 +//line mysql_sql.y:1180 { yyLOCAL = yyDollar[1].selectUnion() } @@ -14563,7 +14624,7 @@ yydefault: case 69: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1193 +//line mysql_sql.y:1196 { var timestamp = yyDollar[2].str var isS3 = false @@ -14578,7 +14639,7 @@ yydefault: case 70: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1204 +//line mysql_sql.y:1207 { var timestamp = yyDollar[2].str var isS3 = true @@ -14592,32 +14653,32 @@ yydefault: yyVAL.union = yyLOCAL case 71: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:1216 +//line mysql_sql.y:1219 { yyVAL.str = "" } case 72: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:1220 +//line mysql_sql.y:1223 { yyVAL.str = yyDollar[2].str } case 73: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:1225 +//line mysql_sql.y:1228 { yyVAL.str = "" } case 74: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:1229 +//line mysql_sql.y:1232 { yyVAL.str = yyDollar[2].str } case 75: yyDollar = yyS[yypt-12 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1235 +//line mysql_sql.y:1238 { yyLOCAL = &tree.CreateCDC{ IfNotExists: yyDollar[3].ifNotExistsUnion(), @@ -14634,7 +14695,7 @@ yydefault: case 76: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:1250 +//line mysql_sql.y:1253 { yyLOCAL = yyDollar[1].strsUnion() } @@ -14642,7 +14703,7 @@ yydefault: case 77: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:1254 +//line mysql_sql.y:1257 { yyLOCAL = append(yyDollar[1].strsUnion(), yyDollar[3].strsUnion()...) } @@ -14650,7 +14711,7 @@ yydefault: case 78: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:1258 +//line mysql_sql.y:1261 { yyLOCAL = []string{} } @@ -14658,7 +14719,7 @@ yydefault: case 79: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:1262 +//line mysql_sql.y:1265 { yyLOCAL = append(yyLOCAL, yyDollar[1].str) yyLOCAL = append(yyLOCAL, yyDollar[3].str) @@ -14667,7 +14728,7 @@ yydefault: case 80: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1269 +//line mysql_sql.y:1272 { yyLOCAL = &tree.ShowCDC{ Option: yyDollar[3].allCDCOptionUnion(), @@ -14677,7 +14738,7 @@ yydefault: case 81: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1277 +//line mysql_sql.y:1280 { yyLOCAL = &tree.PauseCDC{ Option: yyDollar[3].allCDCOptionUnion(), @@ -14687,7 +14748,7 @@ yydefault: case 82: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1285 +//line mysql_sql.y:1288 { yyLOCAL = tree.NewDropCDC(yyDollar[4].allCDCOptionUnion(), yyDollar[3].boolValUnion(), yyDollar[5].boolValUnion()) } @@ -14695,7 +14756,7 @@ yydefault: case 83: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.AllOrNotCDC -//line mysql_sql.y:1290 +//line mysql_sql.y:1293 { yyLOCAL = &tree.AllOrNotCDC{ All: true, @@ -14706,7 +14767,7 @@ yydefault: case 84: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.AllOrNotCDC -//line mysql_sql.y:1297 +//line mysql_sql.y:1300 { yyLOCAL = yyDollar[1].allCDCOptionUnion() } @@ -14714,7 +14775,7 @@ yydefault: case 85: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.AllOrNotCDC -//line mysql_sql.y:1303 +//line mysql_sql.y:1306 { yyLOCAL = yyDollar[1].allCDCOptionUnion() } @@ -14722,7 +14783,7 @@ yydefault: case 86: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.AllOrNotCDC -//line mysql_sql.y:1308 +//line mysql_sql.y:1311 { yyLOCAL = &tree.AllOrNotCDC{ All: false, @@ -14733,7 +14794,7 @@ yydefault: case 87: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.AllOrNotCDC -//line mysql_sql.y:1317 +//line mysql_sql.y:1320 { yyLOCAL = &tree.AllOrNotCDC{ All: true, @@ -14744,7 +14805,7 @@ yydefault: case 88: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.AllOrNotCDC -//line mysql_sql.y:1324 +//line mysql_sql.y:1327 { yyLOCAL = &tree.AllOrNotCDC{ All: false, @@ -14755,7 +14816,7 @@ yydefault: case 89: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1333 +//line mysql_sql.y:1336 { yyLOCAL = &tree.ResumeCDC{ TaskName: tree.Identifier(yyDollar[4].cstrUnion().Compare()), @@ -14765,7 +14826,7 @@ yydefault: case 90: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1341 +//line mysql_sql.y:1344 { yyLOCAL = &tree.RestartCDC{ TaskName: tree.Identifier(yyDollar[4].cstrUnion().Compare()), @@ -14775,7 +14836,7 @@ yydefault: case 91: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1349 +//line mysql_sql.y:1352 { yyLOCAL = &tree.CreateSnapShot{ IfNotExists: yyDollar[3].ifNotExistsUnion(), @@ -14787,7 +14848,7 @@ yydefault: case 92: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ObjectInfo -//line mysql_sql.y:1359 +//line mysql_sql.y:1362 { spLevel := tree.SnapshotLevelType{ Level: tree.SNAPSHOTLEVELCLUSTER, @@ -14801,7 +14862,7 @@ yydefault: case 93: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ObjectInfo -//line mysql_sql.y:1369 +//line mysql_sql.y:1372 { spLevel := tree.SnapshotLevelType{ Level: tree.SNAPSHOTLEVELACCOUNT, @@ -14815,7 +14876,7 @@ yydefault: case 94: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ObjectInfo -//line mysql_sql.y:1379 +//line mysql_sql.y:1382 { spLevel := tree.SnapshotLevelType{ Level: tree.SNAPSHOTLEVELACCOUNT, @@ -14829,7 +14890,7 @@ yydefault: case 95: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ObjectInfo -//line mysql_sql.y:1389 +//line mysql_sql.y:1392 { spLevel := tree.SnapshotLevelType{ Level: tree.SNAPSHOTLEVELDATABASE, @@ -14843,7 +14904,7 @@ yydefault: case 96: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.ObjectInfo -//line mysql_sql.y:1399 +//line mysql_sql.y:1402 { spLevel := tree.SnapshotLevelType{ Level: tree.SNAPSHOTLEVELTABLE, @@ -14857,7 +14918,7 @@ yydefault: case 97: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.ObjectInfo -//line mysql_sql.y:1409 +//line mysql_sql.y:1412 { spLevel := tree.SnapshotLevelType{ Level: tree.SNAPSHOTLEVELTABLE, @@ -14873,7 +14934,7 @@ yydefault: case 98: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.ObjectInfo -//line mysql_sql.y:1421 +//line mysql_sql.y:1424 { spLevel := tree.SnapshotLevelType{ Level: tree.SNAPSHOTLEVELDATABASE, @@ -14889,7 +14950,7 @@ yydefault: case 99: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.ObjectInfo -//line mysql_sql.y:1433 +//line mysql_sql.y:1436 { spLevel := tree.SnapshotLevelType{ Level: tree.SNAPSHOTLEVELACCOUNT, @@ -14904,7 +14965,7 @@ yydefault: case 100: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1446 +//line mysql_sql.y:1449 { yyLOCAL = &tree.CreatePitr{ IfNotExists: yyDollar[3].ifNotExistsUnion(), @@ -14919,7 +14980,7 @@ yydefault: case 101: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1457 +//line mysql_sql.y:1460 { yyLOCAL = &tree.CreatePitr{ IfNotExists: yyDollar[3].ifNotExistsUnion(), @@ -14934,7 +14995,7 @@ yydefault: case 102: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1468 +//line mysql_sql.y:1471 { yyLOCAL = &tree.CreatePitr{ IfNotExists: yyDollar[3].ifNotExistsUnion(), @@ -14950,7 +15011,7 @@ yydefault: case 103: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1480 +//line mysql_sql.y:1483 { yyLOCAL = &tree.CreatePitr{ IfNotExists: yyDollar[3].ifNotExistsUnion(), @@ -14966,7 +15027,7 @@ yydefault: case 104: yyDollar = yyS[yypt-12 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1492 +//line mysql_sql.y:1495 { yyLOCAL = &tree.CreatePitr{ IfNotExists: yyDollar[3].ifNotExistsUnion(), @@ -14983,7 +15044,7 @@ yydefault: case 105: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1505 +//line mysql_sql.y:1508 { yyLOCAL = &tree.CreatePitr{ IfNotExists: yyDollar[3].ifNotExistsUnion(), @@ -14998,7 +15059,7 @@ yydefault: case 106: yyDollar = yyS[yypt-13 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1516 +//line mysql_sql.y:1519 { yyLOCAL = &tree.CreatePitr{ IfNotExists: yyDollar[3].ifNotExistsUnion(), @@ -15015,7 +15076,7 @@ yydefault: case 107: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:1531 +//line mysql_sql.y:1534 { yyLOCAL = yyDollar[1].item.(int64) } @@ -15023,7 +15084,7 @@ yydefault: case 108: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1538 +//line mysql_sql.y:1541 { var account tree.Identifier var database tree.Identifier @@ -15059,7 +15120,7 @@ yydefault: case 109: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1570 +//line mysql_sql.y:1573 { var account tree.Identifier var database tree.Identifier @@ -15100,7 +15161,7 @@ yydefault: case 110: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1607 +//line mysql_sql.y:1610 { yyLOCAL = &tree.RestoreSnapShot{ Level: tree.RESTORELEVELCLUSTER, @@ -15111,7 +15172,7 @@ yydefault: case 111: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1614 +//line mysql_sql.y:1617 { result := &tree.RestoreSnapShot{ Level: tree.RESTORELEVELACCOUNT, @@ -15129,7 +15190,7 @@ yydefault: case 112: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:1630 +//line mysql_sql.y:1633 { yyLOCAL = tree.IdentifierList{tree.Identifier(yyDollar[1].cstrUnion().Compare())} } @@ -15137,7 +15198,7 @@ yydefault: case 113: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:1634 +//line mysql_sql.y:1637 { yyLOCAL = tree.IdentifierList{ tree.Identifier(yyDollar[1].cstrUnion().Compare()), @@ -15148,7 +15209,7 @@ yydefault: case 114: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:1643 +//line mysql_sql.y:1646 { yyLOCAL = tree.IdentifierList{ tree.Identifier(yyDollar[1].cstrUnion().Compare()), @@ -15159,7 +15220,7 @@ yydefault: case 115: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:1650 +//line mysql_sql.y:1653 { yyLOCAL = tree.IdentifierList{ tree.Identifier(yyDollar[1].cstrUnion().Compare()), @@ -15170,32 +15231,32 @@ yydefault: yyVAL.union = yyLOCAL case 116: yyDollar = yyS[yypt-5 : yypt+1] -//line mysql_sql.y:1660 +//line mysql_sql.y:1663 { yyVAL.str = yyDollar[4].cstrUnion().Compare() } case 117: yyDollar = yyS[yypt-5 : yypt+1] -//line mysql_sql.y:1664 +//line mysql_sql.y:1667 { yyVAL.str = strings.ToLower(yyDollar[4].str) } case 118: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:1669 +//line mysql_sql.y:1672 { yyVAL.str = "" } case 119: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:1673 +//line mysql_sql.y:1676 { yyVAL.str = yyDollar[3].cstrUnion().Compare() } case 120: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1679 +//line mysql_sql.y:1682 { yyLOCAL = &tree.RestorePitr{ Level: tree.RESTORELEVELACCOUNT, @@ -15207,7 +15268,7 @@ yydefault: case 121: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1687 +//line mysql_sql.y:1690 { yyLOCAL = &tree.RestorePitr{ Level: tree.RESTORELEVELDATABASE, @@ -15220,7 +15281,7 @@ yydefault: case 122: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1696 +//line mysql_sql.y:1699 { yyLOCAL = &tree.RestorePitr{ Level: tree.RESTORELEVELDATABASE, @@ -15234,7 +15295,7 @@ yydefault: case 123: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1706 +//line mysql_sql.y:1709 { yyLOCAL = &tree.RestorePitr{ Level: tree.RESTORELEVELTABLE, @@ -15248,7 +15309,7 @@ yydefault: case 124: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1716 +//line mysql_sql.y:1719 { yyLOCAL = &tree.RestorePitr{ Level: tree.RESTORELEVELTABLE, @@ -15263,7 +15324,7 @@ yydefault: case 125: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1727 +//line mysql_sql.y:1730 { yyLOCAL = &tree.RestorePitr{ Level: tree.RESTORELEVELACCOUNT, @@ -15277,7 +15338,7 @@ yydefault: case 126: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1737 +//line mysql_sql.y:1740 { yyLOCAL = &tree.RestorePitr{ Level: tree.RESTORELEVELCLUSTER, @@ -15289,7 +15350,7 @@ yydefault: case 127: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1747 +//line mysql_sql.y:1750 { var connectionId uint64 switch v := yyDollar[3].item.(type) { @@ -15312,7 +15373,7 @@ yydefault: case 128: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.KillOption -//line mysql_sql.y:1767 +//line mysql_sql.y:1770 { yyLOCAL = tree.KillOption{ Exist: false, @@ -15322,7 +15383,7 @@ yydefault: case 129: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.KillOption -//line mysql_sql.y:1773 +//line mysql_sql.y:1776 { yyLOCAL = tree.KillOption{ Exist: true, @@ -15333,7 +15394,7 @@ yydefault: case 130: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.KillOption -//line mysql_sql.y:1780 +//line mysql_sql.y:1783 { yyLOCAL = tree.KillOption{ Exist: true, @@ -15344,7 +15405,7 @@ yydefault: case 131: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.StatementOption -//line mysql_sql.y:1788 +//line mysql_sql.y:1791 { yyLOCAL = tree.StatementOption{ Exist: false, @@ -15354,7 +15415,7 @@ yydefault: case 132: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.StatementOption -//line mysql_sql.y:1794 +//line mysql_sql.y:1797 { yyLOCAL = tree.StatementOption{ Exist: true, @@ -15365,7 +15426,7 @@ yydefault: case 133: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1803 +//line mysql_sql.y:1806 { yyLOCAL = &tree.CallStmt{ Name: yyDollar[2].procNameUnion(), @@ -15376,7 +15437,7 @@ yydefault: case 134: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1812 +//line mysql_sql.y:1815 { yyLOCAL = &tree.LeaveStmt{ Name: tree.Identifier(yyDollar[2].cstrUnion().Compare()), @@ -15386,7 +15447,7 @@ yydefault: case 135: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1820 +//line mysql_sql.y:1823 { yyLOCAL = &tree.IterateStmt{ Name: tree.Identifier(yyDollar[2].cstrUnion().Compare()), @@ -15396,7 +15457,7 @@ yydefault: case 136: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1828 +//line mysql_sql.y:1831 { yyLOCAL = &tree.WhileStmt{ Name: "", @@ -15408,7 +15469,7 @@ yydefault: case 137: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1836 +//line mysql_sql.y:1839 { yyLOCAL = &tree.WhileStmt{ Name: tree.Identifier(yyDollar[1].cstrUnion().Compare()), @@ -15420,7 +15481,7 @@ yydefault: case 138: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1846 +//line mysql_sql.y:1849 { yyLOCAL = &tree.RepeatStmt{ Name: "", @@ -15432,7 +15493,7 @@ yydefault: case 139: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1854 +//line mysql_sql.y:1857 { yyLOCAL = &tree.RepeatStmt{ Name: tree.Identifier(yyDollar[1].cstrUnion().Compare()), @@ -15444,7 +15505,7 @@ yydefault: case 140: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1864 +//line mysql_sql.y:1867 { yyLOCAL = &tree.LoopStmt{ Name: "", @@ -15455,7 +15516,7 @@ yydefault: case 141: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1871 +//line mysql_sql.y:1874 { yyLOCAL = &tree.LoopStmt{ Name: tree.Identifier(yyDollar[1].cstrUnion().Compare()), @@ -15466,7 +15527,7 @@ yydefault: case 142: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1880 +//line mysql_sql.y:1883 { yyLOCAL = &tree.IfStmt{ Cond: yyDollar[2].exprUnion(), @@ -15479,7 +15540,7 @@ yydefault: case 143: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*tree.ElseIfStmt -//line mysql_sql.y:1890 +//line mysql_sql.y:1893 { yyLOCAL = nil } @@ -15487,7 +15548,7 @@ yydefault: case 144: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.ElseIfStmt -//line mysql_sql.y:1894 +//line mysql_sql.y:1897 { yyLOCAL = yyDollar[1].elseIfClauseListUnion() } @@ -15495,7 +15556,7 @@ yydefault: case 145: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.ElseIfStmt -//line mysql_sql.y:1900 +//line mysql_sql.y:1903 { yyLOCAL = []*tree.ElseIfStmt{yyDollar[1].elseIfClauseUnion()} } @@ -15503,7 +15564,7 @@ yydefault: case 146: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*tree.ElseIfStmt -//line mysql_sql.y:1904 +//line mysql_sql.y:1907 { yyLOCAL = append(yyDollar[1].elseIfClauseListUnion(), yyDollar[2].elseIfClauseUnion()) } @@ -15511,7 +15572,7 @@ yydefault: case 147: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.ElseIfStmt -//line mysql_sql.y:1910 +//line mysql_sql.y:1913 { yyLOCAL = &tree.ElseIfStmt{ Cond: yyDollar[2].exprUnion(), @@ -15522,7 +15583,7 @@ yydefault: case 148: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1919 +//line mysql_sql.y:1922 { yyLOCAL = &tree.CaseStmt{ Expr: yyDollar[2].exprUnion(), @@ -15534,7 +15595,7 @@ yydefault: case 149: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.WhenStmt -//line mysql_sql.y:1929 +//line mysql_sql.y:1932 { yyLOCAL = []*tree.WhenStmt{yyDollar[1].whenClause2Union()} } @@ -15542,7 +15603,7 @@ yydefault: case 150: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*tree.WhenStmt -//line mysql_sql.y:1933 +//line mysql_sql.y:1936 { yyLOCAL = append(yyDollar[1].whenClauseList2Union(), yyDollar[2].whenClause2Union()) } @@ -15550,7 +15611,7 @@ yydefault: case 151: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.WhenStmt -//line mysql_sql.y:1939 +//line mysql_sql.y:1942 { yyLOCAL = &tree.WhenStmt{ Cond: yyDollar[2].exprUnion(), @@ -15561,7 +15622,7 @@ yydefault: case 152: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []tree.Statement -//line mysql_sql.y:1948 +//line mysql_sql.y:1951 { yyLOCAL = nil } @@ -15569,7 +15630,7 @@ yydefault: case 153: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []tree.Statement -//line mysql_sql.y:1952 +//line mysql_sql.y:1955 { yyLOCAL = yyDollar[2].statementsUnion() } @@ -15577,7 +15638,7 @@ yydefault: case 154: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1958 +//line mysql_sql.y:1961 { ep := &tree.ExportParam{ Outfile: true, @@ -15597,7 +15658,7 @@ yydefault: case 155: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1976 +//line mysql_sql.y:1979 { yyLOCAL = &tree.Load{ Local: yyDollar[3].boolValUnion(), @@ -15613,7 +15674,7 @@ yydefault: case 156: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1990 +//line mysql_sql.y:1993 { yyLOCAL = &tree.DumpTable{Table: yyDollar[3].tableNameUnion(), Path: yyDollar[5].str} } @@ -15621,7 +15682,7 @@ yydefault: case 157: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:1994 +//line mysql_sql.y:1997 { yyLOCAL = &tree.DumpTable{Table: yyDollar[3].tableNameUnion(), Path: yyDollar[5].str, MetadataOnly: true} } @@ -15629,7 +15690,7 @@ yydefault: case 158: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2000 +//line mysql_sql.y:2003 { yyLOCAL = &tree.LoadTable{Table: yyDollar[3].tableNameUnion(), Path: yyDollar[5].str} } @@ -15637,7 +15698,7 @@ yydefault: case 159: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2006 +//line mysql_sql.y:2009 { yyLOCAL = &tree.LoadExtension{ Name: tree.Identifier(yyDollar[2].str), @@ -15647,7 +15708,7 @@ yydefault: case 160: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:2013 +//line mysql_sql.y:2016 { yyLOCAL = nil } @@ -15655,7 +15716,7 @@ yydefault: case 161: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:2017 +//line mysql_sql.y:2020 { yyLOCAL = yyDollar[2].updateExprsUnion() } @@ -15663,7 +15724,7 @@ yydefault: case 162: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:2023 +//line mysql_sql.y:2026 { yyLOCAL = tree.UpdateExprs{yyDollar[1].updateExprUnion()} } @@ -15671,7 +15732,7 @@ yydefault: case 163: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:2027 +//line mysql_sql.y:2030 { yyLOCAL = append(yyDollar[1].updateExprsUnion(), yyDollar[3].updateExprUnion()) } @@ -15679,7 +15740,7 @@ yydefault: case 164: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UpdateExpr -//line mysql_sql.y:2033 +//line mysql_sql.y:2036 { yyLOCAL = &tree.UpdateExpr{ Names: []*tree.UnresolvedName{yyDollar[1].unresolvedNameUnion()}, @@ -15690,7 +15751,7 @@ yydefault: case 165: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UpdateExpr -//line mysql_sql.y:2040 +//line mysql_sql.y:2043 { yyLOCAL = &tree.UpdateExpr{ Names: []*tree.UnresolvedName{yyDollar[1].unresolvedNameUnion()}, @@ -15701,7 +15762,7 @@ yydefault: case 166: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:2048 +//line mysql_sql.y:2051 { yyLOCAL = -1 } @@ -15709,7 +15770,7 @@ yydefault: case 167: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:2052 +//line mysql_sql.y:2055 { str := strings.ToLower(yyDollar[2].str) if str == "true" { @@ -15725,7 +15786,7 @@ yydefault: case 168: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:2064 +//line mysql_sql.y:2067 { yyLOCAL = true } @@ -15733,7 +15794,7 @@ yydefault: case 169: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:2068 +//line mysql_sql.y:2071 { str := strings.ToLower(yyDollar[2].str) if str == "true" { @@ -15749,7 +15810,7 @@ yydefault: case 170: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:2082 +//line mysql_sql.y:2085 { yyLOCAL = tree.NewUnresolvedName(yyDollar[1].cstrUnion()) } @@ -15757,7 +15818,7 @@ yydefault: case 171: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:2086 +//line mysql_sql.y:2089 { tblNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) yyLOCAL = tree.NewUnresolvedName(tblNameCStr, yyDollar[3].cstrUnion()) @@ -15766,7 +15827,7 @@ yydefault: case 172: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:2091 +//line mysql_sql.y:2094 { dbNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) tblNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[3].cstrUnion().Origin()) @@ -15776,7 +15837,7 @@ yydefault: case 173: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []tree.LoadColumn -//line mysql_sql.y:2098 +//line mysql_sql.y:2101 { yyLOCAL = nil } @@ -15784,7 +15845,7 @@ yydefault: case 174: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []tree.LoadColumn -//line mysql_sql.y:2102 +//line mysql_sql.y:2105 { yyLOCAL = nil } @@ -15792,7 +15853,7 @@ yydefault: case 175: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.LoadColumn -//line mysql_sql.y:2106 +//line mysql_sql.y:2109 { yyLOCAL = yyDollar[2].loadColumnsUnion() } @@ -15800,7 +15861,7 @@ yydefault: case 176: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.LoadColumn -//line mysql_sql.y:2112 +//line mysql_sql.y:2115 { switch yyDollar[1].loadColumnUnion().(type) { case *tree.UnresolvedName: @@ -15813,7 +15874,7 @@ yydefault: case 177: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.LoadColumn -//line mysql_sql.y:2121 +//line mysql_sql.y:2124 { switch yyDollar[3].loadColumnUnion().(type) { case *tree.UnresolvedName: @@ -15826,7 +15887,7 @@ yydefault: case 178: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.LoadColumn -//line mysql_sql.y:2132 +//line mysql_sql.y:2135 { yyLOCAL = yyDollar[1].unresolvedNameUnion() } @@ -15834,7 +15895,7 @@ yydefault: case 179: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.LoadColumn -//line mysql_sql.y:2136 +//line mysql_sql.y:2139 { yyLOCAL = yyDollar[1].varExprUnion() } @@ -15842,7 +15903,7 @@ yydefault: case 180: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.VarExpr -//line mysql_sql.y:2142 +//line mysql_sql.y:2145 { yyLOCAL = []*tree.VarExpr{yyDollar[1].varExprUnion()} } @@ -15850,7 +15911,7 @@ yydefault: case 181: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.VarExpr -//line mysql_sql.y:2146 +//line mysql_sql.y:2149 { yyLOCAL = append(yyDollar[1].varExprsUnion(), yyDollar[3].varExprUnion()) } @@ -15858,7 +15919,7 @@ yydefault: case 182: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.VarExpr -//line mysql_sql.y:2152 +//line mysql_sql.y:2155 { yyLOCAL = []*tree.VarExpr{yyDollar[1].varExprUnion()} } @@ -15866,7 +15927,7 @@ yydefault: case 183: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.VarExpr -//line mysql_sql.y:2156 +//line mysql_sql.y:2159 { yyLOCAL = append(yyDollar[1].varExprsUnion(), yyDollar[3].varExprUnion()) } @@ -15874,7 +15935,7 @@ yydefault: case 184: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.VarExpr -//line mysql_sql.y:2162 +//line mysql_sql.y:2165 { yyLOCAL = yyDollar[1].varExprUnion() } @@ -15882,7 +15943,7 @@ yydefault: case 185: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.VarExpr -//line mysql_sql.y:2166 +//line mysql_sql.y:2169 { yyLOCAL = yyDollar[1].varExprUnion() } @@ -15890,7 +15951,7 @@ yydefault: case 186: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.VarExpr -//line mysql_sql.y:2172 +//line mysql_sql.y:2175 { v := strings.ToLower(yyDollar[1].str) var isGlobal bool @@ -15912,7 +15973,7 @@ yydefault: case 187: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.VarExpr -//line mysql_sql.y:2192 +//line mysql_sql.y:2195 { // vs := strings.Split($1, ".") // var r string @@ -15934,7 +15995,7 @@ yydefault: case 188: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:2211 +//line mysql_sql.y:2214 { yyLOCAL = 0 } @@ -15942,7 +16003,7 @@ yydefault: case 189: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:2215 +//line mysql_sql.y:2218 { yyLOCAL = yyDollar[2].item.(int64) } @@ -15950,7 +16011,7 @@ yydefault: case 190: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:2219 +//line mysql_sql.y:2222 { yyLOCAL = yyDollar[2].item.(int64) } @@ -15958,7 +16019,7 @@ yydefault: case 191: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Lines -//line mysql_sql.y:2224 +//line mysql_sql.y:2227 { yyLOCAL = nil } @@ -15966,7 +16027,7 @@ yydefault: case 192: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Lines -//line mysql_sql.y:2228 +//line mysql_sql.y:2231 { yyLOCAL = &tree.Lines{ StartingBy: yyDollar[2].str, @@ -15979,7 +16040,7 @@ yydefault: case 193: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Lines -//line mysql_sql.y:2237 +//line mysql_sql.y:2240 { yyLOCAL = &tree.Lines{ StartingBy: yyDollar[3].str, @@ -15991,32 +16052,32 @@ yydefault: yyVAL.union = yyLOCAL case 194: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:2247 +//line mysql_sql.y:2250 { yyVAL.str = "" } case 196: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:2254 +//line mysql_sql.y:2257 { yyVAL.str = yyDollar[3].str } case 197: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:2259 +//line mysql_sql.y:2262 { yyVAL.str = "\n" } case 199: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:2266 +//line mysql_sql.y:2269 { yyVAL.str = yyDollar[3].str } case 200: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:2271 +//line mysql_sql.y:2274 { yyLOCAL = nil } @@ -16024,7 +16085,7 @@ yydefault: case 201: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:2275 +//line mysql_sql.y:2278 { res := &tree.Fields{ Terminated: &tree.Terminated{ @@ -16054,7 +16115,7 @@ yydefault: case 202: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.Fields -//line mysql_sql.y:2303 +//line mysql_sql.y:2306 { yyLOCAL = []*tree.Fields{yyDollar[1].fieldsUnion()} } @@ -16062,7 +16123,7 @@ yydefault: case 203: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*tree.Fields -//line mysql_sql.y:2307 +//line mysql_sql.y:2310 { yyLOCAL = append(yyDollar[1].fieldsListUnion(), yyDollar[2].fieldsUnion()) } @@ -16070,7 +16131,7 @@ yydefault: case 204: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:2313 +//line mysql_sql.y:2316 { yyLOCAL = &tree.Fields{ Terminated: &tree.Terminated{ @@ -16082,7 +16143,7 @@ yydefault: case 205: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:2321 +//line mysql_sql.y:2324 { str := yyDollar[4].str if str != "\\" && len(str) > 1 { @@ -16106,7 +16167,7 @@ yydefault: case 206: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:2341 +//line mysql_sql.y:2344 { str := yyDollar[3].str if str != "\\" && len(str) > 1 { @@ -16129,7 +16190,7 @@ yydefault: case 207: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:2360 +//line mysql_sql.y:2363 { str := yyDollar[3].str if str != "\\" && len(str) > 1 { @@ -16152,7 +16213,7 @@ yydefault: case 209: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.DuplicateKey -//line mysql_sql.y:2385 +//line mysql_sql.y:2388 { yyLOCAL = &tree.DuplicateKeyError{} } @@ -16160,7 +16221,7 @@ yydefault: case 210: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.DuplicateKey -//line mysql_sql.y:2389 +//line mysql_sql.y:2392 { yyLOCAL = &tree.DuplicateKeyIgnore{} } @@ -16168,7 +16229,7 @@ yydefault: case 211: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.DuplicateKey -//line mysql_sql.y:2393 +//line mysql_sql.y:2396 { yyLOCAL = &tree.DuplicateKeyReplace{} } @@ -16176,7 +16237,7 @@ yydefault: case 212: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:2398 +//line mysql_sql.y:2401 { yyLOCAL = false } @@ -16184,7 +16245,7 @@ yydefault: case 213: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:2402 +//line mysql_sql.y:2405 { yyLOCAL = true } @@ -16192,7 +16253,7 @@ yydefault: case 214: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2408 +//line mysql_sql.y:2411 { yyLOCAL = &tree.Grant{ Typ: tree.GrantTypePrivilege, @@ -16209,7 +16270,7 @@ yydefault: case 215: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2421 +//line mysql_sql.y:2424 { yyLOCAL = &tree.Grant{ Typ: tree.GrantTypeRole, @@ -16224,7 +16285,7 @@ yydefault: case 216: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2432 +//line mysql_sql.y:2435 { yyLOCAL = &tree.Grant{ Typ: tree.GrantTypeProxy, @@ -16240,7 +16301,7 @@ yydefault: case 217: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:2445 +//line mysql_sql.y:2448 { yyLOCAL = false } @@ -16248,7 +16309,7 @@ yydefault: case 218: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:2449 +//line mysql_sql.y:2452 { yyLOCAL = true } @@ -16256,7 +16317,7 @@ yydefault: case 219: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2459 +//line mysql_sql.y:2462 { yyLOCAL = &tree.Revoke{ Typ: tree.RevokeTypePrivilege, @@ -16273,7 +16334,7 @@ yydefault: case 220: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2472 +//line mysql_sql.y:2475 { yyLOCAL = &tree.Revoke{ Typ: tree.RevokeTypeRole, @@ -16288,7 +16349,7 @@ yydefault: case 221: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.PrivilegeLevel -//line mysql_sql.y:2485 +//line mysql_sql.y:2488 { yyLOCAL = &tree.PrivilegeLevel{ Level: tree.PRIVILEGE_LEVEL_TYPE_STAR, @@ -16298,7 +16359,7 @@ yydefault: case 222: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.PrivilegeLevel -//line mysql_sql.y:2491 +//line mysql_sql.y:2494 { yyLOCAL = &tree.PrivilegeLevel{ Level: tree.PRIVILEGE_LEVEL_TYPE_STAR_STAR, @@ -16308,7 +16369,7 @@ yydefault: case 223: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.PrivilegeLevel -//line mysql_sql.y:2497 +//line mysql_sql.y:2500 { tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) yyLOCAL = &tree.PrivilegeLevel{ @@ -16320,7 +16381,7 @@ yydefault: case 224: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.PrivilegeLevel -//line mysql_sql.y:2505 +//line mysql_sql.y:2508 { dbName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[3].cstrUnion().Origin()) @@ -16334,7 +16395,7 @@ yydefault: case 225: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.PrivilegeLevel -//line mysql_sql.y:2515 +//line mysql_sql.y:2518 { tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) yyLOCAL = &tree.PrivilegeLevel{ @@ -16346,7 +16407,7 @@ yydefault: case 226: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ObjectType -//line mysql_sql.y:2525 +//line mysql_sql.y:2528 { yyLOCAL = tree.OBJECT_TYPE_TABLE } @@ -16354,7 +16415,7 @@ yydefault: case 227: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ObjectType -//line mysql_sql.y:2529 +//line mysql_sql.y:2532 { yyLOCAL = tree.OBJECT_TYPE_DATABASE } @@ -16362,7 +16423,7 @@ yydefault: case 228: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ObjectType -//line mysql_sql.y:2533 +//line mysql_sql.y:2536 { yyLOCAL = tree.OBJECT_TYPE_FUNCTION } @@ -16370,7 +16431,7 @@ yydefault: case 229: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ObjectType -//line mysql_sql.y:2537 +//line mysql_sql.y:2540 { yyLOCAL = tree.OBJECT_TYPE_PROCEDURE } @@ -16378,7 +16439,7 @@ yydefault: case 230: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ObjectType -//line mysql_sql.y:2541 +//line mysql_sql.y:2544 { yyLOCAL = tree.OBJECT_TYPE_VIEW } @@ -16386,7 +16447,7 @@ yydefault: case 231: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ObjectType -//line mysql_sql.y:2545 +//line mysql_sql.y:2548 { yyLOCAL = tree.OBJECT_TYPE_ACCOUNT } @@ -16394,7 +16455,7 @@ yydefault: case 232: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.Privilege -//line mysql_sql.y:2551 +//line mysql_sql.y:2554 { yyLOCAL = []*tree.Privilege{yyDollar[1].privilegeUnion()} } @@ -16402,7 +16463,7 @@ yydefault: case 233: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.Privilege -//line mysql_sql.y:2555 +//line mysql_sql.y:2558 { yyLOCAL = append(yyDollar[1].privilegesUnion(), yyDollar[3].privilegeUnion()) } @@ -16410,7 +16471,7 @@ yydefault: case 234: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Privilege -//line mysql_sql.y:2561 +//line mysql_sql.y:2564 { yyLOCAL = &tree.Privilege{ Type: yyDollar[1].privilegeTypeUnion(), @@ -16421,7 +16482,7 @@ yydefault: case 235: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Privilege -//line mysql_sql.y:2568 +//line mysql_sql.y:2571 { yyLOCAL = &tree.Privilege{ Type: yyDollar[1].privilegeTypeUnion(), @@ -16432,7 +16493,7 @@ yydefault: case 236: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.UnresolvedName -//line mysql_sql.y:2577 +//line mysql_sql.y:2580 { yyLOCAL = []*tree.UnresolvedName{yyDollar[1].unresolvedNameUnion()} } @@ -16440,7 +16501,7 @@ yydefault: case 237: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.UnresolvedName -//line mysql_sql.y:2581 +//line mysql_sql.y:2584 { yyLOCAL = append(yyDollar[1].unresolveNamesUnion(), yyDollar[3].unresolvedNameUnion()) } @@ -16448,7 +16509,7 @@ yydefault: case 238: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2587 +//line mysql_sql.y:2590 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_ALL } @@ -16456,7 +16517,7 @@ yydefault: case 239: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2591 +//line mysql_sql.y:2594 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE_ACCOUNT } @@ -16464,7 +16525,7 @@ yydefault: case 240: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2595 +//line mysql_sql.y:2598 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_DROP_ACCOUNT } @@ -16472,7 +16533,7 @@ yydefault: case 241: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2599 +//line mysql_sql.y:2602 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_ALTER_ACCOUNT } @@ -16480,7 +16541,7 @@ yydefault: case 242: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2603 +//line mysql_sql.y:2606 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_UPGRADE_ACCOUNT } @@ -16488,7 +16549,7 @@ yydefault: case 243: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2607 +//line mysql_sql.y:2610 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_ALL } @@ -16496,7 +16557,7 @@ yydefault: case 244: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2611 +//line mysql_sql.y:2614 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_ALTER_TABLE } @@ -16504,7 +16565,7 @@ yydefault: case 245: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2615 +//line mysql_sql.y:2618 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_ALTER_VIEW } @@ -16512,7 +16573,7 @@ yydefault: case 246: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2619 +//line mysql_sql.y:2622 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE } @@ -16520,7 +16581,7 @@ yydefault: case 247: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2623 +//line mysql_sql.y:2626 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE_USER } @@ -16528,7 +16589,7 @@ yydefault: case 248: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2627 +//line mysql_sql.y:2630 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_DROP_USER } @@ -16536,7 +16597,7 @@ yydefault: case 249: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2631 +//line mysql_sql.y:2634 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_ALTER_USER } @@ -16544,7 +16605,7 @@ yydefault: case 250: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2635 +//line mysql_sql.y:2638 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE_TABLESPACE } @@ -16552,7 +16613,7 @@ yydefault: case 251: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2639 +//line mysql_sql.y:2642 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_TRIGGER } @@ -16560,7 +16621,7 @@ yydefault: case 252: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2643 +//line mysql_sql.y:2646 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_DELETE } @@ -16568,7 +16629,7 @@ yydefault: case 253: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2647 +//line mysql_sql.y:2650 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_DROP_TABLE } @@ -16576,7 +16637,7 @@ yydefault: case 254: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2651 +//line mysql_sql.y:2654 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_DROP_VIEW } @@ -16584,7 +16645,7 @@ yydefault: case 255: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2655 +//line mysql_sql.y:2658 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_EXECUTE } @@ -16592,7 +16653,7 @@ yydefault: case 256: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2659 +//line mysql_sql.y:2662 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_INDEX } @@ -16600,7 +16661,7 @@ yydefault: case 257: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2663 +//line mysql_sql.y:2666 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_INSERT } @@ -16608,7 +16669,7 @@ yydefault: case 258: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2667 +//line mysql_sql.y:2670 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_SELECT } @@ -16616,7 +16677,7 @@ yydefault: case 259: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2671 +//line mysql_sql.y:2674 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_SUPER } @@ -16624,7 +16685,7 @@ yydefault: case 260: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2675 +//line mysql_sql.y:2678 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE_DATABASE } @@ -16632,7 +16693,7 @@ yydefault: case 261: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2679 +//line mysql_sql.y:2682 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_DROP_DATABASE } @@ -16640,7 +16701,7 @@ yydefault: case 262: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2683 +//line mysql_sql.y:2686 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_SHOW_DATABASES } @@ -16648,7 +16709,7 @@ yydefault: case 263: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2687 +//line mysql_sql.y:2690 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CONNECT } @@ -16656,7 +16717,7 @@ yydefault: case 264: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2691 +//line mysql_sql.y:2694 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_MANAGE_GRANTS } @@ -16664,7 +16725,7 @@ yydefault: case 265: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2695 +//line mysql_sql.y:2698 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_OWNERSHIP } @@ -16672,7 +16733,7 @@ yydefault: case 266: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2699 +//line mysql_sql.y:2702 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_SHOW_TABLES } @@ -16680,7 +16741,7 @@ yydefault: case 267: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2703 +//line mysql_sql.y:2706 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE_TABLE } @@ -16688,7 +16749,7 @@ yydefault: case 268: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2707 +//line mysql_sql.y:2710 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_UPDATE } @@ -16696,7 +16757,7 @@ yydefault: case 269: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2711 +//line mysql_sql.y:2714 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_GRANT_OPTION } @@ -16704,7 +16765,7 @@ yydefault: case 270: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2715 +//line mysql_sql.y:2718 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_REFERENCES } @@ -16712,7 +16773,7 @@ yydefault: case 271: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2719 +//line mysql_sql.y:2722 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_REFERENCE } @@ -16720,7 +16781,7 @@ yydefault: case 272: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2723 +//line mysql_sql.y:2726 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_REPLICATION_SLAVE } @@ -16728,7 +16789,7 @@ yydefault: case 273: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2727 +//line mysql_sql.y:2730 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_REPLICATION_CLIENT } @@ -16736,7 +16797,7 @@ yydefault: case 274: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2731 +//line mysql_sql.y:2734 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_USAGE } @@ -16744,7 +16805,7 @@ yydefault: case 275: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2735 +//line mysql_sql.y:2738 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_RELOAD } @@ -16752,7 +16813,7 @@ yydefault: case 276: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2739 +//line mysql_sql.y:2742 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_FILE } @@ -16760,7 +16821,7 @@ yydefault: case 277: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2743 +//line mysql_sql.y:2746 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE_TEMPORARY_TABLES } @@ -16768,7 +16829,7 @@ yydefault: case 278: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2747 +//line mysql_sql.y:2750 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_LOCK_TABLES } @@ -16776,7 +16837,7 @@ yydefault: case 279: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2751 +//line mysql_sql.y:2754 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE_VIEW } @@ -16784,7 +16845,7 @@ yydefault: case 280: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2755 +//line mysql_sql.y:2758 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_SHOW_VIEW } @@ -16792,7 +16853,7 @@ yydefault: case 281: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2759 +//line mysql_sql.y:2762 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE_ROLE } @@ -16800,7 +16861,7 @@ yydefault: case 282: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2763 +//line mysql_sql.y:2766 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_DROP_ROLE } @@ -16808,7 +16869,7 @@ yydefault: case 283: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2767 +//line mysql_sql.y:2770 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_ALTER_ROLE } @@ -16816,7 +16877,7 @@ yydefault: case 284: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2771 +//line mysql_sql.y:2774 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_CREATE_ROUTINE } @@ -16824,7 +16885,7 @@ yydefault: case 285: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2775 +//line mysql_sql.y:2778 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_ALTER_ROUTINE } @@ -16832,7 +16893,7 @@ yydefault: case 286: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2779 +//line mysql_sql.y:2782 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_EVENT } @@ -16840,7 +16901,7 @@ yydefault: case 287: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2783 +//line mysql_sql.y:2786 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_SHUTDOWN } @@ -16848,7 +16909,7 @@ yydefault: case 288: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.PrivilegeType -//line mysql_sql.y:2787 +//line mysql_sql.y:2790 { yyLOCAL = tree.PRIVILEGE_TYPE_STATIC_TRUNCATE } @@ -16856,7 +16917,7 @@ yydefault: case 296: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2802 +//line mysql_sql.y:2805 { yyLOCAL = &tree.SetLogserviceSettings{ Name: yyDollar[4].str, @@ -16867,7 +16928,7 @@ yydefault: case 297: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2811 +//line mysql_sql.y:2814 { yyLOCAL = &tree.SetTransaction{ Scope: tree.TransactionScopeNext, @@ -16878,7 +16939,7 @@ yydefault: case 298: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2818 +//line mysql_sql.y:2821 { yyLOCAL = &tree.SetTransaction{ Scope: tree.TransactionScopeGlobal, @@ -16889,7 +16950,7 @@ yydefault: case 299: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2825 +//line mysql_sql.y:2828 { yyLOCAL = &tree.SetTransaction{ Scope: tree.TransactionScopeSession, @@ -16900,7 +16961,7 @@ yydefault: case 300: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2834 +//line mysql_sql.y:2837 { var connID uint32 switch v := yyDollar[5].item.(type) { @@ -16920,7 +16981,7 @@ yydefault: case 301: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.TransactionCharacteristic -//line mysql_sql.y:2852 +//line mysql_sql.y:2855 { yyLOCAL = []*tree.TransactionCharacteristic{yyDollar[1].transactionCharacteristicUnion()} } @@ -16928,7 +16989,7 @@ yydefault: case 302: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.TransactionCharacteristic -//line mysql_sql.y:2856 +//line mysql_sql.y:2859 { yyLOCAL = append(yyDollar[1].transactionCharacteristicListUnion(), yyDollar[3].transactionCharacteristicUnion()) } @@ -16936,7 +16997,7 @@ yydefault: case 303: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.TransactionCharacteristic -//line mysql_sql.y:2862 +//line mysql_sql.y:2865 { yyLOCAL = &tree.TransactionCharacteristic{ IsLevel: true, @@ -16947,7 +17008,7 @@ yydefault: case 304: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.TransactionCharacteristic -//line mysql_sql.y:2869 +//line mysql_sql.y:2872 { yyLOCAL = &tree.TransactionCharacteristic{ Access: yyDollar[1].accessModeUnion(), @@ -16957,7 +17018,7 @@ yydefault: case 305: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IsolationLevelType -//line mysql_sql.y:2877 +//line mysql_sql.y:2880 { yyLOCAL = tree.ISOLATION_LEVEL_REPEATABLE_READ } @@ -16965,7 +17026,7 @@ yydefault: case 306: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IsolationLevelType -//line mysql_sql.y:2881 +//line mysql_sql.y:2884 { yyLOCAL = tree.ISOLATION_LEVEL_READ_COMMITTED } @@ -16973,7 +17034,7 @@ yydefault: case 307: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IsolationLevelType -//line mysql_sql.y:2885 +//line mysql_sql.y:2888 { yyLOCAL = tree.ISOLATION_LEVEL_READ_UNCOMMITTED } @@ -16981,7 +17042,7 @@ yydefault: case 308: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IsolationLevelType -//line mysql_sql.y:2889 +//line mysql_sql.y:2892 { yyLOCAL = tree.ISOLATION_LEVEL_SERIALIZABLE } @@ -16989,7 +17050,7 @@ yydefault: case 309: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AccessModeType -//line mysql_sql.y:2895 +//line mysql_sql.y:2898 { yyLOCAL = tree.ACCESS_MODE_READ_WRITE } @@ -16997,7 +17058,7 @@ yydefault: case 310: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AccessModeType -//line mysql_sql.y:2899 +//line mysql_sql.y:2902 { yyLOCAL = tree.ACCESS_MODE_READ_ONLY } @@ -17005,7 +17066,7 @@ yydefault: case 311: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2905 +//line mysql_sql.y:2908 { yyLOCAL = &tree.SetRole{ SecondaryRole: false, @@ -17016,7 +17077,7 @@ yydefault: case 312: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2912 +//line mysql_sql.y:2915 { yyLOCAL = &tree.SetRole{ SecondaryRole: true, @@ -17027,7 +17088,7 @@ yydefault: case 313: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2919 +//line mysql_sql.y:2922 { yyLOCAL = &tree.SetRole{ SecondaryRole: true, @@ -17038,7 +17099,7 @@ yydefault: case 314: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2928 +//line mysql_sql.y:2931 { dr := yyDollar[4].setDefaultRoleUnion() dr.Users = yyDollar[6].usersUnion() @@ -17048,7 +17109,7 @@ yydefault: case 315: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.SetDefaultRole -//line mysql_sql.y:2958 +//line mysql_sql.y:2961 { yyLOCAL = &tree.SetDefaultRole{Type: tree.SET_DEFAULT_ROLE_TYPE_NONE, Roles: nil} } @@ -17056,7 +17117,7 @@ yydefault: case 316: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.SetDefaultRole -//line mysql_sql.y:2962 +//line mysql_sql.y:2965 { yyLOCAL = &tree.SetDefaultRole{Type: tree.SET_DEFAULT_ROLE_TYPE_ALL, Roles: nil} } @@ -17064,7 +17125,7 @@ yydefault: case 317: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.SetDefaultRole -//line mysql_sql.y:2966 +//line mysql_sql.y:2969 { yyLOCAL = &tree.SetDefaultRole{Type: tree.SET_DEFAULT_ROLE_TYPE_NORMAL, Roles: yyDollar[1].rolesUnion()} } @@ -17072,7 +17133,7 @@ yydefault: case 318: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2972 +//line mysql_sql.y:2975 { yyLOCAL = &tree.SetVar{Assignments: yyDollar[2].varAssignmentExprsUnion()} } @@ -17080,7 +17141,7 @@ yydefault: case 319: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2978 +//line mysql_sql.y:2981 { yyLOCAL = &tree.SetPassword{Password: yyDollar[4].str} } @@ -17088,21 +17149,21 @@ yydefault: case 320: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:2982 +//line mysql_sql.y:2985 { yyLOCAL = &tree.SetPassword{User: yyDollar[4].userUnion(), Password: yyDollar[6].str} } yyVAL.union = yyLOCAL case 322: yyDollar = yyS[yypt-4 : yypt+1] -//line mysql_sql.y:2989 +//line mysql_sql.y:2992 { yyVAL.str = yyDollar[3].str } case 323: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.VarAssignmentExpr -//line mysql_sql.y:2995 +//line mysql_sql.y:2998 { yyLOCAL = []*tree.VarAssignmentExpr{yyDollar[1].varAssignmentExprUnion()} } @@ -17110,7 +17171,7 @@ yydefault: case 324: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.VarAssignmentExpr -//line mysql_sql.y:2999 +//line mysql_sql.y:3002 { yyLOCAL = append(yyDollar[1].varAssignmentExprsUnion(), yyDollar[3].varAssignmentExprUnion()) } @@ -17118,7 +17179,7 @@ yydefault: case 325: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:3005 +//line mysql_sql.y:3008 { yyLOCAL = &tree.VarAssignmentExpr{ System: true, @@ -17131,7 +17192,7 @@ yydefault: case 326: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:3014 +//line mysql_sql.y:3017 { yyLOCAL = &tree.VarAssignmentExpr{ System: true, @@ -17145,7 +17206,7 @@ yydefault: case 327: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:3024 +//line mysql_sql.y:3027 { yyLOCAL = &tree.VarAssignmentExpr{ System: true, @@ -17159,7 +17220,7 @@ yydefault: case 328: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:3034 +//line mysql_sql.y:3037 { yyLOCAL = &tree.VarAssignmentExpr{ System: true, @@ -17172,7 +17233,7 @@ yydefault: case 329: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:3043 +//line mysql_sql.y:3046 { yyLOCAL = &tree.VarAssignmentExpr{ System: true, @@ -17185,7 +17246,7 @@ yydefault: case 330: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:3052 +//line mysql_sql.y:3055 { vs := strings.Split(yyDollar[1].str, ".") var isGlobal bool @@ -17212,7 +17273,7 @@ yydefault: case 331: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:3075 +//line mysql_sql.y:3078 { v := strings.ToLower(yyDollar[1].str) var isGlobal bool @@ -17240,7 +17301,7 @@ yydefault: case 332: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:3099 +//line mysql_sql.y:3102 { yyLOCAL = &tree.VarAssignmentExpr{ SetNames: true, @@ -17252,7 +17313,7 @@ yydefault: case 333: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:3107 +//line mysql_sql.y:3110 { yyLOCAL = &tree.VarAssignmentExpr{ SetNames: true, @@ -17264,7 +17325,7 @@ yydefault: case 334: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:3115 +//line mysql_sql.y:3118 { yyLOCAL = &tree.VarAssignmentExpr{ SetNames: true, @@ -17277,7 +17338,7 @@ yydefault: case 335: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:3124 +//line mysql_sql.y:3127 { yyLOCAL = &tree.VarAssignmentExpr{ SetNames: true, @@ -17289,7 +17350,7 @@ yydefault: case 336: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:3132 +//line mysql_sql.y:3135 { yyLOCAL = &tree.VarAssignmentExpr{ Name: strings.ToLower(yyDollar[1].str), @@ -17300,7 +17361,7 @@ yydefault: case 337: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.VarAssignmentExpr -//line mysql_sql.y:3139 +//line mysql_sql.y:3142 { yyLOCAL = &tree.VarAssignmentExpr{ Name: strings.ToLower(yyDollar[1].str), @@ -17311,7 +17372,7 @@ yydefault: case 338: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:3148 +//line mysql_sql.y:3151 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_char) } @@ -17319,7 +17380,7 @@ yydefault: case 339: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:3152 +//line mysql_sql.y:3155 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_char) } @@ -17327,39 +17388,39 @@ yydefault: case 340: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:3156 +//line mysql_sql.y:3159 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL case 341: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:3162 +//line mysql_sql.y:3165 { yyVAL.str = string(yyDollar[1].str) } case 342: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:3166 +//line mysql_sql.y:3169 { yyVAL.str = yyDollar[1].str } case 343: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:3172 +//line mysql_sql.y:3175 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } case 344: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:3176 +//line mysql_sql.y:3179 { yyVAL.str = yyDollar[1].cstrUnion().Compare() + "." + yyDollar[3].cstrUnion().Compare() } case 345: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:3182 +//line mysql_sql.y:3185 { yyLOCAL = []string{yyDollar[1].str} } @@ -17367,7 +17428,7 @@ yydefault: case 346: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:3186 +//line mysql_sql.y:3189 { yyLOCAL = append(yyDollar[1].strsUnion(), yyDollar[3].str) } @@ -17375,7 +17436,7 @@ yydefault: case 353: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3200 +//line mysql_sql.y:3203 { yyLOCAL = &tree.SavePoint{Name: tree.Identifier(yyDollar[2].cstrUnion().Compare())} } @@ -17383,7 +17444,7 @@ yydefault: case 354: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3206 +//line mysql_sql.y:3209 { yyLOCAL = &tree.ReleaseSavePoint{Name: tree.Identifier(yyDollar[3].cstrUnion().Compare())} } @@ -17391,7 +17452,7 @@ yydefault: case 355: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3212 +//line mysql_sql.y:3215 { yyLOCAL = &tree.RollbackToSavePoint{Name: tree.Identifier(yyDollar[3].cstrUnion().Compare())} } @@ -17399,7 +17460,7 @@ yydefault: case 356: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3217 +//line mysql_sql.y:3220 { yyLOCAL = &tree.RollbackToSavePoint{Name: tree.Identifier(yyDollar[4].cstrUnion().Compare())} } @@ -17407,7 +17468,7 @@ yydefault: case 357: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3222 +//line mysql_sql.y:3225 { yyLOCAL = &tree.RollbackToSavePoint{Name: tree.Identifier(yyDollar[5].cstrUnion().Compare())} } @@ -17415,7 +17476,7 @@ yydefault: case 358: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3227 +//line mysql_sql.y:3230 { yyLOCAL = &tree.RollbackToSavePoint{Name: tree.Identifier(yyDollar[4].cstrUnion().Compare())} } @@ -17423,7 +17484,7 @@ yydefault: case 359: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3233 +//line mysql_sql.y:3236 { yyLOCAL = &tree.RollbackTransaction{Type: yyDollar[2].completionTypeUnion()} } @@ -17431,7 +17492,7 @@ yydefault: case 360: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3239 +//line mysql_sql.y:3242 { yyLOCAL = &tree.CommitTransaction{Type: yyDollar[2].completionTypeUnion()} } @@ -17439,7 +17500,7 @@ yydefault: case 361: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.CompletionType -//line mysql_sql.y:3244 +//line mysql_sql.y:3247 { yyLOCAL = tree.COMPLETION_TYPE_NO_CHAIN } @@ -17447,7 +17508,7 @@ yydefault: case 362: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.CompletionType -//line mysql_sql.y:3248 +//line mysql_sql.y:3251 { yyLOCAL = tree.COMPLETION_TYPE_NO_CHAIN } @@ -17455,7 +17516,7 @@ yydefault: case 363: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.CompletionType -//line mysql_sql.y:3252 +//line mysql_sql.y:3255 { yyLOCAL = tree.COMPLETION_TYPE_CHAIN } @@ -17463,7 +17524,7 @@ yydefault: case 364: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.CompletionType -//line mysql_sql.y:3256 +//line mysql_sql.y:3259 { yyLOCAL = tree.COMPLETION_TYPE_CHAIN } @@ -17471,7 +17532,7 @@ yydefault: case 365: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.CompletionType -//line mysql_sql.y:3260 +//line mysql_sql.y:3263 { yyLOCAL = tree.COMPLETION_TYPE_RELEASE } @@ -17479,7 +17540,7 @@ yydefault: case 366: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.CompletionType -//line mysql_sql.y:3264 +//line mysql_sql.y:3267 { yyLOCAL = tree.COMPLETION_TYPE_RELEASE } @@ -17487,7 +17548,7 @@ yydefault: case 367: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.CompletionType -//line mysql_sql.y:3268 +//line mysql_sql.y:3271 { yyLOCAL = tree.COMPLETION_TYPE_NO_CHAIN } @@ -17495,7 +17556,7 @@ yydefault: case 368: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.CompletionType -//line mysql_sql.y:3272 +//line mysql_sql.y:3275 { yyLOCAL = tree.COMPLETION_TYPE_NO_CHAIN } @@ -17503,7 +17564,7 @@ yydefault: case 369: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.CompletionType -//line mysql_sql.y:3276 +//line mysql_sql.y:3279 { yyLOCAL = tree.COMPLETION_TYPE_NO_CHAIN } @@ -17511,7 +17572,7 @@ yydefault: case 370: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3282 +//line mysql_sql.y:3285 { yyLOCAL = &tree.BeginTransaction{} } @@ -17519,7 +17580,7 @@ yydefault: case 371: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3286 +//line mysql_sql.y:3289 { yyLOCAL = &tree.BeginTransaction{} } @@ -17527,7 +17588,7 @@ yydefault: case 372: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3290 +//line mysql_sql.y:3293 { yyLOCAL = &tree.BeginTransaction{} } @@ -17535,7 +17596,7 @@ yydefault: case 373: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3294 +//line mysql_sql.y:3297 { m := tree.MakeTransactionModes(tree.READ_WRITE_MODE_READ_WRITE) yyLOCAL = &tree.BeginTransaction{Modes: m} @@ -17544,7 +17605,7 @@ yydefault: case 374: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3299 +//line mysql_sql.y:3302 { m := tree.MakeTransactionModes(tree.READ_WRITE_MODE_READ_ONLY) yyLOCAL = &tree.BeginTransaction{Modes: m} @@ -17553,7 +17614,7 @@ yydefault: case 375: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3304 +//line mysql_sql.y:3307 { yyLOCAL = &tree.BeginTransaction{} } @@ -17561,7 +17622,7 @@ yydefault: case 376: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3310 +//line mysql_sql.y:3313 { name := yyDollar[2].cstrUnion() secondaryRole := false @@ -17578,7 +17639,7 @@ yydefault: case 377: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3323 +//line mysql_sql.y:3326 { name := yylex.(*Lexer).GetDbOrTblNameCStr("") secondaryRole := false @@ -17595,7 +17656,7 @@ yydefault: case 378: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3336 +//line mysql_sql.y:3339 { name := yylex.(*Lexer).GetDbOrTblNameCStr("") secondaryRole := false @@ -17612,7 +17673,7 @@ yydefault: case 379: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3349 +//line mysql_sql.y:3352 { name := yylex.(*Lexer).GetDbOrTblNameCStr("") secondaryRole := true @@ -17629,7 +17690,7 @@ yydefault: case 380: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3362 +//line mysql_sql.y:3365 { name := yylex.(*Lexer).GetDbOrTblNameCStr("") secondaryRole := true @@ -17646,7 +17707,7 @@ yydefault: case 381: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3377 +//line mysql_sql.y:3380 { if intoErr := tree.ValidateSelectIntoEnclosingStatement(yyDollar[1].statementUnion()); intoErr != "" { yylex.Error(intoErr) @@ -17658,7 +17719,7 @@ yydefault: case 382: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3385 +//line mysql_sql.y:3388 { yyDollar[2].statementUnion().(*tree.Update).With = yyDollar[1].withClauseUnion() if intoErr := tree.ValidateSelectIntoEnclosingStatement(yyDollar[2].statementUnion()); intoErr != "" { @@ -17671,7 +17732,7 @@ yydefault: case 383: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3396 +//line mysql_sql.y:3399 { // Single-table syntax yyLOCAL = &tree.Update{ @@ -17689,7 +17750,7 @@ yydefault: case 384: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3410 +//line mysql_sql.y:3413 { // Multiple-table syntax yyLOCAL = &tree.Update{ @@ -17706,7 +17767,7 @@ yydefault: case 385: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3423 +//line mysql_sql.y:3426 { // PostgreSQL-style UPDATE target SET ... FROM source_tables WHERE ... // The target table is kept in Tables; FROM-clause sources are stored @@ -17726,7 +17787,7 @@ yydefault: case 386: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:3441 +//line mysql_sql.y:3444 { yyLOCAL = tree.UpdateExprs{yyDollar[1].updateExprUnion()} } @@ -17734,7 +17795,7 @@ yydefault: case 387: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:3445 +//line mysql_sql.y:3448 { yyLOCAL = append(yyDollar[1].updateExprsUnion(), yyDollar[3].updateExprUnion()) } @@ -17742,7 +17803,7 @@ yydefault: case 388: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UpdateExpr -//line mysql_sql.y:3451 +//line mysql_sql.y:3454 { yyLOCAL = &tree.UpdateExpr{Names: []*tree.UnresolvedName{yyDollar[1].unresolvedNameUnion()}, Expr: yyDollar[3].exprUnion()} } @@ -17750,7 +17811,7 @@ yydefault: case 391: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3461 +//line mysql_sql.y:3464 { yyLOCAL = &tree.LockTableStmt{TableLocks: yyDollar[3].tableLocksUnion()} } @@ -17758,7 +17819,7 @@ yydefault: case 392: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.TableLock -//line mysql_sql.y:3467 +//line mysql_sql.y:3470 { yyLOCAL = []tree.TableLock{yyDollar[1].tableLockUnion()} } @@ -17766,7 +17827,7 @@ yydefault: case 393: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.TableLock -//line mysql_sql.y:3471 +//line mysql_sql.y:3474 { yyLOCAL = append(yyDollar[1].tableLocksUnion(), yyDollar[3].tableLockUnion()) } @@ -17774,7 +17835,7 @@ yydefault: case 394: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.TableLock -//line mysql_sql.y:3477 +//line mysql_sql.y:3480 { yyLOCAL = tree.TableLock{Table: *yyDollar[1].tableNameUnion(), LockType: yyDollar[2].tableLockTypeUnion()} } @@ -17782,7 +17843,7 @@ yydefault: case 395: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableLockType -//line mysql_sql.y:3483 +//line mysql_sql.y:3486 { yyLOCAL = tree.TableLockRead } @@ -17790,7 +17851,7 @@ yydefault: case 396: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.TableLockType -//line mysql_sql.y:3487 +//line mysql_sql.y:3490 { yyLOCAL = tree.TableLockReadLocal } @@ -17798,7 +17859,7 @@ yydefault: case 397: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableLockType -//line mysql_sql.y:3491 +//line mysql_sql.y:3494 { yyLOCAL = tree.TableLockWrite } @@ -17806,7 +17867,7 @@ yydefault: case 398: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.TableLockType -//line mysql_sql.y:3495 +//line mysql_sql.y:3498 { yyLOCAL = tree.TableLockLowPriorityWrite } @@ -17814,7 +17875,7 @@ yydefault: case 399: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3501 +//line mysql_sql.y:3504 { yyLOCAL = &tree.UnLockTableStmt{} } @@ -17822,7 +17883,7 @@ yydefault: case 409: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3516 +//line mysql_sql.y:3519 { yyLOCAL = &tree.SetVar{Assignments: yyDollar[2].varAssignmentExprsUnion()} } @@ -17830,7 +17891,7 @@ yydefault: case 413: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3523 +//line mysql_sql.y:3526 { yyLOCAL = yyDollar[1].selectUnion() } @@ -17838,7 +17899,7 @@ yydefault: case 414: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3529 +//line mysql_sql.y:3532 { yyLOCAL = tree.NewPrepareStmt(tree.Identifier(yyDollar[2].str), yyDollar[4].statementUnion()) } @@ -17846,7 +17907,7 @@ yydefault: case 415: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3533 +//line mysql_sql.y:3536 { yyLOCAL = tree.NewPrepareString(tree.Identifier(yyDollar[2].str), yyDollar[4].str) } @@ -17854,7 +17915,7 @@ yydefault: case 416: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3537 +//line mysql_sql.y:3540 { yyLOCAL = tree.NewPrepareVar(tree.Identifier(yyDollar[2].str), yyDollar[4].varExprUnion()) } @@ -17862,7 +17923,7 @@ yydefault: case 417: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3543 +//line mysql_sql.y:3546 { yyLOCAL = &tree.ExecuteSQLTask{ Name: tree.Identifier(yyDollar[3].cstrUnion().Compare()), @@ -17872,7 +17933,7 @@ yydefault: case 418: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3549 +//line mysql_sql.y:3552 { yyLOCAL = tree.NewExecute(tree.Identifier(yyDollar[2].str)) } @@ -17880,7 +17941,7 @@ yydefault: case 419: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3553 +//line mysql_sql.y:3556 { yyLOCAL = tree.NewExecuteWithVariables(tree.Identifier(yyDollar[2].str), yyDollar[4].varExprsUnion()) } @@ -17888,7 +17949,7 @@ yydefault: case 420: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3559 +//line mysql_sql.y:3562 { yyLOCAL = tree.NewDeallocate(tree.Identifier(yyDollar[3].str), false) } @@ -17896,7 +17957,7 @@ yydefault: case 421: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3565 +//line mysql_sql.y:3568 { yyLOCAL = tree.NewReset(tree.Identifier(yyDollar[3].str)) } @@ -17904,7 +17965,7 @@ yydefault: case 427: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3576 +//line mysql_sql.y:3579 { yyLOCAL = yyDollar[1].selectUnion() } @@ -17912,7 +17973,7 @@ yydefault: case 428: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3582 +//line mysql_sql.y:3585 { yyLOCAL = &tree.ShowColumns{Table: yyDollar[2].unresolvedObjectNameUnion()} } @@ -17920,7 +17981,7 @@ yydefault: case 429: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3586 +//line mysql_sql.y:3589 { yyLOCAL = &tree.ShowColumns{Table: yyDollar[2].unresolvedObjectNameUnion(), ColName: yyDollar[3].unresolvedNameUnion()} } @@ -17928,7 +17989,7 @@ yydefault: case 430: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3590 +//line mysql_sql.y:3593 { yyLOCAL = tree.NewExplainFor("", uint64(yyDollar[4].item.(int64))) } @@ -17936,7 +17997,7 @@ yydefault: case 431: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3594 +//line mysql_sql.y:3597 { yyLOCAL = tree.NewExplainFor(yyDollar[4].str, uint64(yyDollar[7].item.(int64))) } @@ -17944,7 +18005,7 @@ yydefault: case 432: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3598 +//line mysql_sql.y:3601 { yyLOCAL = yyDollar[1].statementUnion() } @@ -17952,7 +18013,7 @@ yydefault: case 433: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3604 +//line mysql_sql.y:3607 { if intoErr := tree.ValidateSelectIntoEnclosingStatement(yyDollar[2].statementUnion()); intoErr != "" { yylex.Error(intoErr) @@ -17964,7 +18025,7 @@ yydefault: case 434: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3612 +//line mysql_sql.y:3615 { if intoErr := tree.ValidateSelectIntoEnclosingStatement(yyDollar[3].statementUnion()); intoErr != "" { yylex.Error(intoErr) @@ -17979,7 +18040,7 @@ yydefault: case 435: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3623 +//line mysql_sql.y:3626 { if intoErr := tree.ValidateSelectIntoEnclosingStatement(yyDollar[3].statementUnion()); intoErr != "" { yylex.Error(intoErr) @@ -17994,7 +18055,7 @@ yydefault: case 436: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3634 +//line mysql_sql.y:3637 { if intoErr := tree.ValidateSelectIntoEnclosingStatement(yyDollar[4].statementUnion()); intoErr != "" { yylex.Error(intoErr) @@ -18010,7 +18071,7 @@ yydefault: case 437: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3646 +//line mysql_sql.y:3649 { if intoErr := tree.ValidateSelectIntoEnclosingStatement(yyDollar[3].statementUnion()); intoErr != "" { yylex.Error(intoErr) @@ -18025,7 +18086,7 @@ yydefault: case 438: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3657 +//line mysql_sql.y:3660 { if intoErr := tree.ValidateSelectIntoEnclosingStatement(yyDollar[4].statementUnion()); intoErr != "" { yylex.Error(intoErr) @@ -18041,7 +18102,7 @@ yydefault: case 439: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3669 +//line mysql_sql.y:3672 { if intoErr := tree.ValidateSelectIntoEnclosingStatement(yyDollar[4].statementUnion()); intoErr != "" { yylex.Error(intoErr) @@ -18057,7 +18118,7 @@ yydefault: case 440: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3681 +//line mysql_sql.y:3684 { if intoErr := tree.ValidateSelectIntoEnclosingStatement(yyDollar[5].statementUnion()); intoErr != "" { yylex.Error(intoErr) @@ -18069,7 +18130,7 @@ yydefault: case 441: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3689 +//line mysql_sql.y:3692 { yyLOCAL = tree.MakeExplainStmt(yyDollar[3].statementUnion(), nil) } @@ -18077,7 +18138,7 @@ yydefault: case 442: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3693 +//line mysql_sql.y:3696 { options := []tree.OptionElem{ tree.MakeOptionElem(tree.VerboseOption, "NULL"), @@ -18088,7 +18149,7 @@ yydefault: case 443: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3700 +//line mysql_sql.y:3703 { options := []tree.OptionElem{ tree.MakeOptionElem(tree.AnalyzeOption, "NULL"), @@ -18099,7 +18160,7 @@ yydefault: case 444: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3707 +//line mysql_sql.y:3710 { options := []tree.OptionElem{ tree.MakeOptionElem(tree.AnalyzeOption, "NULL"), @@ -18111,7 +18172,7 @@ yydefault: case 459: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.OptionElem -//line mysql_sql.y:3745 +//line mysql_sql.y:3748 { yyLOCAL = []tree.OptionElem{yyDollar[1].explainOptionUnion()} } @@ -18119,7 +18180,7 @@ yydefault: case 460: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.OptionElem -//line mysql_sql.y:3749 +//line mysql_sql.y:3752 { yyLOCAL = append(yyDollar[1].explainOptionsUnion(), yyDollar[3].explainOptionUnion()) } @@ -18127,45 +18188,45 @@ yydefault: case 461: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.OptionElem -//line mysql_sql.y:3755 +//line mysql_sql.y:3758 { yyLOCAL = tree.MakeOptionElem(yyDollar[1].str, yyDollar[2].str) } yyVAL.union = yyLOCAL case 462: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:3761 +//line mysql_sql.y:3764 { yyVAL.str = yyDollar[1].str } case 463: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:3766 +//line mysql_sql.y:3769 { yyVAL.str = "true" } case 464: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:3767 +//line mysql_sql.y:3770 { yyVAL.str = "false" } case 465: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:3768 +//line mysql_sql.y:3771 { yyVAL.str = yyDollar[1].str } case 466: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:3769 +//line mysql_sql.y:3772 { yyVAL.str = yyDollar[1].str } case 467: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3773 +//line mysql_sql.y:3776 { stmt := tree.NewAnalyzeStmt(yyDollar[3].analyzeTableEntriesUnion()) stmt.FullScan = yyDollar[4].boolValUnion() @@ -18175,7 +18236,7 @@ yydefault: case 468: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:3781 +//line mysql_sql.y:3784 { yyLOCAL = false } @@ -18183,7 +18244,7 @@ yydefault: case 469: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:3785 +//line mysql_sql.y:3788 { yyLOCAL = true } @@ -18191,7 +18252,7 @@ yydefault: case 470: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.AnalyzeTableEntry -//line mysql_sql.y:3791 +//line mysql_sql.y:3794 { yyLOCAL = []*tree.AnalyzeTableEntry{yyDollar[1].analyzeTableEntryUnion()} } @@ -18199,7 +18260,7 @@ yydefault: case 471: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.AnalyzeTableEntry -//line mysql_sql.y:3795 +//line mysql_sql.y:3798 { yyLOCAL = append(yyDollar[1].analyzeTableEntriesUnion(), yyDollar[3].analyzeTableEntryUnion()) } @@ -18207,7 +18268,7 @@ yydefault: case 472: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.AnalyzeTableEntry -//line mysql_sql.y:3801 +//line mysql_sql.y:3804 { yyLOCAL = &tree.AnalyzeTableEntry{Table: yyDollar[1].tableNameUnion()} } @@ -18215,7 +18276,7 @@ yydefault: case 473: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.AnalyzeTableEntry -//line mysql_sql.y:3805 +//line mysql_sql.y:3808 { yyLOCAL = &tree.AnalyzeTableEntry{Table: yyDollar[1].tableNameUnion(), Cols: yyDollar[3].identifierListUnion()} } @@ -18223,7 +18284,7 @@ yydefault: case 474: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3811 +//line mysql_sql.y:3814 { yyLOCAL = tree.NewCheckTableStmt(yyDollar[3].tableNamesUnion(), yyDollar[4].checkTableOptionUnion()) } @@ -18231,7 +18292,7 @@ yydefault: case 475: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.CheckTableOption -//line mysql_sql.y:3817 +//line mysql_sql.y:3820 { yyLOCAL = tree.CheckTableOptionNone } @@ -18239,7 +18300,7 @@ yydefault: case 476: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.CheckTableOption -//line mysql_sql.y:3821 +//line mysql_sql.y:3824 { yyLOCAL = tree.CheckTableOptionExtended } @@ -18247,7 +18308,7 @@ yydefault: case 477: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.CheckTableOption -//line mysql_sql.y:3825 +//line mysql_sql.y:3828 { yyLOCAL = tree.CheckTableOptionForUpgrade } @@ -18255,7 +18316,7 @@ yydefault: case 478: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3831 +//line mysql_sql.y:3834 { yyLOCAL = tree.NewShowProfileStmt(yyDollar[3].int64ValUnion(), yyDollar[4].limitUnion()) } @@ -18263,7 +18324,7 @@ yydefault: case 479: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:3837 +//line mysql_sql.y:3840 { yyLOCAL = 0 } @@ -18271,7 +18332,7 @@ yydefault: case 480: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:3841 +//line mysql_sql.y:3844 { yyLOCAL = yyDollar[3].item.(int64) } @@ -18279,7 +18340,7 @@ yydefault: case 481: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3847 +//line mysql_sql.y:3850 { yyLOCAL = &tree.UpgradeStatement{ Target: yyDollar[3].upgrade_targetUnion(), @@ -18290,7 +18351,7 @@ yydefault: case 482: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Target -//line mysql_sql.y:3856 +//line mysql_sql.y:3859 { yyLOCAL = &tree.Target{ AccountName: yyDollar[1].str, @@ -18301,7 +18362,7 @@ yydefault: case 483: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Target -//line mysql_sql.y:3863 +//line mysql_sql.y:3866 { yyLOCAL = &tree.Target{ AccountName: "", @@ -18312,7 +18373,7 @@ yydefault: case 484: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:3871 +//line mysql_sql.y:3874 { yyLOCAL = -1 } @@ -18320,7 +18381,7 @@ yydefault: case 485: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:3875 +//line mysql_sql.y:3878 { res := yyDollar[3].item.(int64) if res <= 0 { @@ -18333,7 +18394,7 @@ yydefault: case 500: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3903 +//line mysql_sql.y:3906 { yyLOCAL = &tree.AlterIcebergCatalog{ Name: tree.Identifier(yyDollar[4].cstrUnion().Compare()), @@ -18344,7 +18405,7 @@ yydefault: case 501: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3910 +//line mysql_sql.y:3913 { yyLOCAL = &tree.AlterIcebergCatalog{ Name: tree.Identifier(yyDollar[4].cstrUnion().Compare()), @@ -18355,7 +18416,7 @@ yydefault: case 502: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3919 +//line mysql_sql.y:3922 { yyLOCAL = &tree.AlterMongoDBConnection{ Name: tree.Identifier(yyDollar[4].cstrUnion().Compare()), @@ -18367,7 +18428,7 @@ yydefault: case 503: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3927 +//line mysql_sql.y:3930 { yyLOCAL = &tree.AlterMongoDBConnection{ Name: tree.Identifier(yyDollar[4].cstrUnion().Compare()), @@ -18379,7 +18440,7 @@ yydefault: case 504: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3935 +//line mysql_sql.y:3938 { yyLOCAL = &tree.AlterMongoDBConnection{ Name: tree.Identifier(yyDollar[4].cstrUnion().Compare()), @@ -18390,7 +18451,7 @@ yydefault: case 505: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3942 +//line mysql_sql.y:3945 { yyLOCAL = &tree.AlterMongoDBConnection{ Name: tree.Identifier(yyDollar[4].cstrUnion().Compare()), @@ -18401,7 +18462,7 @@ yydefault: case 506: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3951 +//line mysql_sql.y:3954 { var ifExists = yyDollar[3].boolValUnion() var name = yyDollar[4].tableNameUnion() @@ -18426,7 +18487,7 @@ yydefault: case 507: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3974 +//line mysql_sql.y:3977 { var ifExists = yyDollar[3].boolValUnion() var name = yyDollar[4].tableNameUnion() @@ -18438,7 +18499,7 @@ yydefault: case 508: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3984 +//line mysql_sql.y:3987 { var table = yyDollar[3].tableNameUnion() alterTable := tree.NewAlterTable(table) @@ -18449,7 +18510,7 @@ yydefault: case 509: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3991 +//line mysql_sql.y:3994 { var table = yyDollar[3].tableNameUnion() alterTable := tree.NewAlterTable(table) @@ -18460,7 +18521,7 @@ yydefault: case 510: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:3998 +//line mysql_sql.y:4001 { var table = yyDollar[3].tableNameUnion() alterTable := tree.NewAlterTable(table) @@ -18471,7 +18532,7 @@ yydefault: case 511: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4007 +//line mysql_sql.y:4010 { alterTables := yyDollar[3].renameTableOptionsUnion() renameTables := tree.NewRenameTable(alterTables) @@ -18481,7 +18542,7 @@ yydefault: case 512: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.AlterTable -//line mysql_sql.y:4015 +//line mysql_sql.y:4018 { yyLOCAL = []*tree.AlterTable{yyDollar[1].renameTableOptionUnion()} } @@ -18489,7 +18550,7 @@ yydefault: case 513: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.AlterTable -//line mysql_sql.y:4019 +//line mysql_sql.y:4022 { yyLOCAL = append(yyDollar[1].renameTableOptionsUnion(), yyDollar[3].renameTableOptionUnion()) } @@ -18497,7 +18558,7 @@ yydefault: case 514: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.AlterTable -//line mysql_sql.y:4025 +//line mysql_sql.y:4028 { var table = yyDollar[1].tableNameUnion() alterTable := tree.NewAlterTable(table) @@ -18509,7 +18570,7 @@ yydefault: case 515: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4035 +//line mysql_sql.y:4038 { var io *tree.IndexOption = nil if yyDollar[5].indexOptionUnion() == nil { @@ -18526,7 +18587,7 @@ yydefault: case 516: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4048 +//line mysql_sql.y:4051 { var io *tree.IndexOption = nil if yyDollar[5].indexOptionUnion() == nil { @@ -18543,7 +18604,7 @@ yydefault: case 517: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4061 +//line mysql_sql.y:4064 { var io *tree.IndexOption = nil if yyDollar[5].indexOptionUnion() == nil { @@ -18560,7 +18621,7 @@ yydefault: case 518: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4074 +//line mysql_sql.y:4077 { var io *tree.IndexOption = nil if yyDollar[5].indexOptionUnion() == nil { @@ -18577,7 +18638,7 @@ yydefault: case 519: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4087 +//line mysql_sql.y:4090 { var io *tree.IndexOption = nil if yyDollar[5].indexOptionUnion() == nil { @@ -18594,7 +18655,7 @@ yydefault: case 520: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.AlterTableOptions -//line mysql_sql.y:4102 +//line mysql_sql.y:4105 { yyLOCAL = []tree.AlterTableOption{yyDollar[1].alterTableOptionUnion()} } @@ -18602,7 +18663,7 @@ yydefault: case 521: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOptions -//line mysql_sql.y:4106 +//line mysql_sql.y:4109 { yyLOCAL = append(yyDollar[1].alterTableOptionsUnion(), yyDollar[3].alterTableOptionUnion()) } @@ -18610,7 +18671,7 @@ yydefault: case 522: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.AlterPartitionOption -//line mysql_sql.y:4112 +//line mysql_sql.y:4115 { yyLOCAL = yyDollar[1].alterPartitionOptionUnion() } @@ -18618,7 +18679,7 @@ yydefault: case 523: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.AlterPartitionOption -//line mysql_sql.y:4116 +//line mysql_sql.y:4119 { yyDollar[3].partitionByUnion().Num = uint64(yyDollar[4].int64ValUnion()) var PartBy = yyDollar[3].partitionByUnion() @@ -18644,7 +18705,7 @@ yydefault: case 524: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4140 +//line mysql_sql.y:4143 { var ifExists = yyDollar[3].boolValUnion() var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) @@ -18656,7 +18717,7 @@ yydefault: case 525: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4150 +//line mysql_sql.y:4153 { yyLOCAL = &tree.AlterSQLTask{ Name: tree.Identifier(yyDollar[3].cstrUnion().Compare()), @@ -18667,7 +18728,7 @@ yydefault: case 526: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4157 +//line mysql_sql.y:4160 { yyLOCAL = &tree.AlterSQLTask{ Name: tree.Identifier(yyDollar[3].cstrUnion().Compare()), @@ -18678,7 +18739,7 @@ yydefault: case 527: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4164 +//line mysql_sql.y:4167 { yyLOCAL = &tree.AlterSQLTask{ Name: tree.Identifier(yyDollar[3].cstrUnion().Compare()), @@ -18691,7 +18752,7 @@ yydefault: case 528: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4173 +//line mysql_sql.y:4176 { yyLOCAL = &tree.AlterSQLTask{ Name: tree.Identifier(yyDollar[3].cstrUnion().Compare()), @@ -18703,7 +18764,7 @@ yydefault: case 529: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4181 +//line mysql_sql.y:4184 { yyLOCAL = &tree.AlterSQLTask{ Name: tree.Identifier(yyDollar[3].cstrUnion().Compare()), @@ -18715,7 +18776,7 @@ yydefault: case 530: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4189 +//line mysql_sql.y:4192 { yyLOCAL = &tree.AlterSQLTask{ Name: tree.Identifier(yyDollar[3].cstrUnion().Compare()), @@ -18727,7 +18788,7 @@ yydefault: case 531: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4199 +//line mysql_sql.y:4202 { var oldName = yyDollar[5].cstrUnion().Compare() var newName = yyDollar[8].cstrUnion().Compare() @@ -18737,7 +18798,7 @@ yydefault: case 532: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4205 +//line mysql_sql.y:4208 { var oldName = yyDollar[3].cstrUnion().Compare() var newName = yyDollar[6].cstrUnion().Compare() @@ -18747,7 +18808,7 @@ yydefault: case 533: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4211 +//line mysql_sql.y:4214 { var roleName = yyDollar[3].cstrUnion().Compare() var ruleSQL = yyDollar[6].str @@ -18760,7 +18821,7 @@ yydefault: case 534: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4220 +//line mysql_sql.y:4223 { var roleName = yyDollar[3].cstrUnion().Compare() var dbName = yyDollar[8].cstrUnion().Compare() @@ -18771,7 +18832,7 @@ yydefault: case 535: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterPartitionOption -//line mysql_sql.y:4229 +//line mysql_sql.y:4232 { var typ = tree.AlterPartitionAddPartition var partitions = yyDollar[3].partitionsUnion() @@ -18785,7 +18846,7 @@ yydefault: case 536: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterPartitionOption -//line mysql_sql.y:4239 +//line mysql_sql.y:4242 { var typ = tree.AlterPartitionDropPartition var partitionNames = yyDollar[3].PartitionNamesUnion() @@ -18805,7 +18866,7 @@ yydefault: case 537: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterPartitionOption -//line mysql_sql.y:4255 +//line mysql_sql.y:4258 { var typ = tree.AlterPartitionTruncatePartition var partitionNames = yyDollar[3].PartitionNamesUnion() @@ -18825,7 +18886,7 @@ yydefault: case 538: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:4273 +//line mysql_sql.y:4276 { yyLOCAL = nil } @@ -18833,7 +18894,7 @@ yydefault: case 539: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:4277 +//line mysql_sql.y:4280 { yyLOCAL = yyDollar[1].PartitionNamesUnion() } @@ -18841,7 +18902,7 @@ yydefault: case 540: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:4283 +//line mysql_sql.y:4286 { yyLOCAL = tree.IdentifierList{tree.Identifier(yyDollar[1].cstrUnion().Compare())} } @@ -18849,7 +18910,7 @@ yydefault: case 541: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:4287 +//line mysql_sql.y:4290 { yyLOCAL = append(yyDollar[1].PartitionNamesUnion(), tree.Identifier(yyDollar[3].cstrUnion().Compare())) } @@ -18857,7 +18918,7 @@ yydefault: case 542: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4293 +//line mysql_sql.y:4296 { var def = yyDollar[2].tableDefUnion() opt := tree.NewAlterOptionAdd(def) @@ -18867,7 +18928,7 @@ yydefault: case 543: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4299 +//line mysql_sql.y:4302 { var typ = tree.AlterTableModifyColumn var newColumn = yyDollar[3].columnTableDefUnion() @@ -18879,7 +18940,7 @@ yydefault: case 544: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4307 +//line mysql_sql.y:4310 { // Type OldColumnName NewColumn Position var typ = tree.AlterTableChangeColumn @@ -18893,7 +18954,7 @@ yydefault: case 545: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4317 +//line mysql_sql.y:4320 { var typ = tree.AlterTableRenameColumn var oldColumnName = yyDollar[3].unresolvedNameUnion() @@ -18905,7 +18966,7 @@ yydefault: case 546: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4325 +//line mysql_sql.y:4328 { var typ = tree.AlterTableAlterColumn var columnName = yyDollar[3].unresolvedNameUnion() @@ -18919,7 +18980,7 @@ yydefault: case 547: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4335 +//line mysql_sql.y:4338 { var typ = tree.AlterTableAlterColumn var columnName = yyDollar[3].unresolvedNameUnion() @@ -18933,7 +18994,7 @@ yydefault: case 548: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4345 +//line mysql_sql.y:4348 { var typ = tree.AlterTableAlterColumn var columnName = yyDollar[3].unresolvedNameUnion() @@ -18947,7 +19008,7 @@ yydefault: case 549: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4355 +//line mysql_sql.y:4358 { var orderByClauseType = tree.AlterTableOrderByColumn var orderByColumnList = yyDollar[3].alterColumnOrderByUnion() @@ -18958,7 +19019,7 @@ yydefault: case 550: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4362 +//line mysql_sql.y:4365 { yyLOCAL = tree.AlterTableOption(yyDollar[2].alterTableOptionUnion()) } @@ -18966,7 +19027,7 @@ yydefault: case 551: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4366 +//line mysql_sql.y:4369 { yyLOCAL = tree.AlterTableOption(yyDollar[2].alterTableOptionUnion()) } @@ -18974,7 +19035,7 @@ yydefault: case 552: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4370 +//line mysql_sql.y:4373 { yyLOCAL = tree.AlterTableOption(yyDollar[1].tableOptionUnion()) } @@ -18982,7 +19043,7 @@ yydefault: case 553: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4374 +//line mysql_sql.y:4377 { yyLOCAL = tree.AlterTableOption(yyDollar[3].alterTableOptionUnion()) } @@ -18990,7 +19051,7 @@ yydefault: case 554: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4378 +//line mysql_sql.y:4381 { var column = yyDollar[3].columnTableDefUnion() var position = yyDollar[4].alterColPositionUnion() @@ -19001,7 +19062,7 @@ yydefault: case 555: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4385 +//line mysql_sql.y:4388 { yyLOCAL = tree.NewAlterOptionAlgorithm(yyDollar[3].str) } @@ -19009,7 +19070,7 @@ yydefault: case 556: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4389 +//line mysql_sql.y:4392 { yyLOCAL = tree.NewTableOptionCharset(yyDollar[4].str) } @@ -19017,7 +19078,7 @@ yydefault: case 557: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4393 +//line mysql_sql.y:4396 { yyLOCAL = tree.NewTableOptionCharset(yyDollar[5].str) } @@ -19025,7 +19086,7 @@ yydefault: case 558: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4397 +//line mysql_sql.y:4400 { yyLOCAL = tree.NewTableOptionCharset(yyDollar[5].str) } @@ -19033,7 +19094,7 @@ yydefault: case 559: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4401 +//line mysql_sql.y:4404 { yyLOCAL = tree.NewTableOptionCharset(yyDollar[1].str) } @@ -19041,7 +19102,7 @@ yydefault: case 560: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4405 +//line mysql_sql.y:4408 { yyLOCAL = tree.NewTableOptionCharset(yyDollar[1].str) } @@ -19049,7 +19110,7 @@ yydefault: case 561: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4409 +//line mysql_sql.y:4412 { yyLOCAL = tree.NewTableOptionCharset(yyDollar[1].str) } @@ -19057,7 +19118,7 @@ yydefault: case 562: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4413 +//line mysql_sql.y:4416 { yyLOCAL = tree.NewAlterOptionLock(yyDollar[3].str) } @@ -19065,33 +19126,33 @@ yydefault: case 563: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4417 +//line mysql_sql.y:4420 { yyLOCAL = tree.NewTableOptionCharset(yyDollar[1].str) } yyVAL.union = yyLOCAL case 564: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:4422 +//line mysql_sql.y:4425 { yyVAL.str = "" } case 581: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:4453 +//line mysql_sql.y:4456 { yyVAL.str = "" } case 582: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:4457 +//line mysql_sql.y:4460 { yyVAL.str = string("COLUMN") } case 583: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.ColumnPosition -//line mysql_sql.y:4462 +//line mysql_sql.y:4465 { var typ = tree.ColumnPositionNone var relativeColumn *tree.UnresolvedName @@ -19101,7 +19162,7 @@ yydefault: case 584: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.ColumnPosition -//line mysql_sql.y:4468 +//line mysql_sql.y:4471 { var typ = tree.ColumnPositionFirst var relativeColumn *tree.UnresolvedName @@ -19111,7 +19172,7 @@ yydefault: case 585: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.ColumnPosition -//line mysql_sql.y:4474 +//line mysql_sql.y:4477 { var typ = tree.ColumnPositionAfter var relativeColumn = yyDollar[2].unresolvedNameUnion() @@ -19121,7 +19182,7 @@ yydefault: case 586: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.AlterColumnOrder -//line mysql_sql.y:4482 +//line mysql_sql.y:4485 { yyLOCAL = []*tree.AlterColumnOrder{yyDollar[1].alterColumnOrderUnion()} } @@ -19129,7 +19190,7 @@ yydefault: case 587: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.AlterColumnOrder -//line mysql_sql.y:4486 +//line mysql_sql.y:4489 { yyLOCAL = append(yyDollar[1].alterColumnOrderByUnion(), yyDollar[3].alterColumnOrderUnion()) } @@ -19137,7 +19198,7 @@ yydefault: case 588: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.AlterColumnOrder -//line mysql_sql.y:4492 +//line mysql_sql.y:4495 { var column = yyDollar[1].unresolvedNameUnion() var direction = yyDollar[2].directionUnion() @@ -19147,7 +19208,7 @@ yydefault: case 589: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4500 +//line mysql_sql.y:4503 { var name = yyDollar[1].unresolvedObjectNameUnion() yyLOCAL = tree.NewAlterOptionTableName(name) @@ -19156,7 +19217,7 @@ yydefault: case 590: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4507 +//line mysql_sql.y:4510 { var dropType = tree.AlterTableDropIndex var name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) @@ -19166,7 +19227,7 @@ yydefault: case 591: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4513 +//line mysql_sql.y:4516 { var dropType = tree.AlterTableDropKey var name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) @@ -19176,7 +19237,7 @@ yydefault: case 592: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4519 +//line mysql_sql.y:4522 { var dropType = tree.AlterTableDropColumn var name = tree.Identifier(yyDollar[1].cstrUnion().Compare()) @@ -19186,7 +19247,7 @@ yydefault: case 593: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4525 +//line mysql_sql.y:4528 { var dropType = tree.AlterTableDropColumn var name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) @@ -19196,7 +19257,7 @@ yydefault: case 594: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4531 +//line mysql_sql.y:4534 { var dropType = tree.AlterTableDropForeignKey var name = tree.Identifier(yyDollar[3].cstrUnion().Compare()) @@ -19207,7 +19268,7 @@ yydefault: case 595: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4538 +//line mysql_sql.y:4541 { yyLOCAL = &tree.AlterOptionDrop{ Typ: tree.AlterTableDropForeignKey, @@ -19218,7 +19279,7 @@ yydefault: case 596: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4545 +//line mysql_sql.y:4548 { var dropType = tree.AlterTableDropPrimaryKey var name = tree.Identifier("") @@ -19228,7 +19289,7 @@ yydefault: case 597: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4553 +//line mysql_sql.y:4556 { var indexName = tree.Identifier(yyDollar[2].cstrUnion().Compare()) var visibility = yyDollar[3].indexVisibilityUnion() @@ -19238,7 +19299,7 @@ yydefault: case 598: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4559 +//line mysql_sql.y:4562 { var io *tree.IndexOption = nil if yyDollar[5].indexOptionUnion() == nil { @@ -19257,7 +19318,7 @@ yydefault: case 599: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4574 +//line mysql_sql.y:4577 { var checkType = yyDollar[1].str var enforce = yyDollar[3].boolValUnion() @@ -19267,7 +19328,7 @@ yydefault: case 600: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AlterTableOption -//line mysql_sql.y:4580 +//line mysql_sql.y:4583 { var checkType = yyDollar[1].str var enforce = yyDollar[3].boolValUnion() @@ -19277,7 +19338,7 @@ yydefault: case 601: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.VisibleType -//line mysql_sql.y:4588 +//line mysql_sql.y:4591 { yyLOCAL = tree.VISIBLE_TYPE_VISIBLE } @@ -19285,7 +19346,7 @@ yydefault: case 602: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.VisibleType -//line mysql_sql.y:4592 +//line mysql_sql.y:4595 { yyLOCAL = tree.VISIBLE_TYPE_INVISIBLE } @@ -19293,7 +19354,7 @@ yydefault: case 603: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:4598 +//line mysql_sql.y:4601 { yyLOCAL = true } @@ -19301,7 +19362,7 @@ yydefault: case 604: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:4602 +//line mysql_sql.y:4605 { yyLOCAL = false } @@ -19309,7 +19370,7 @@ yydefault: case 605: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4608 +//line mysql_sql.y:4611 { var ifExists = yyDollar[3].boolValUnion() var name = yyDollar[4].exprUnion() @@ -19329,7 +19390,7 @@ yydefault: case 606: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4626 +//line mysql_sql.y:4629 { var accountName = "" var dbName = yyDollar[3].str @@ -19348,7 +19409,7 @@ yydefault: case 607: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4641 +//line mysql_sql.y:4644 { var accountName = "" var dbName = yyDollar[3].str @@ -19367,7 +19428,7 @@ yydefault: case 608: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4656 +//line mysql_sql.y:4659 { var accountName = yyDollar[4].str var dbName = "" @@ -19386,7 +19447,7 @@ yydefault: case 609: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4671 +//line mysql_sql.y:4674 { assignments := []*tree.VarAssignmentExpr{ { @@ -19402,7 +19463,7 @@ yydefault: case 610: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.AlterAccountAuthOption -//line mysql_sql.y:4684 +//line mysql_sql.y:4687 { yyLOCAL = tree.AlterAccountAuthOption{ Exist: false, @@ -19412,7 +19473,7 @@ yydefault: case 611: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.AlterAccountAuthOption -//line mysql_sql.y:4690 +//line mysql_sql.y:4693 { yyLOCAL = tree.AlterAccountAuthOption{ Exist: true, @@ -19425,7 +19486,7 @@ yydefault: case 612: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4701 +//line mysql_sql.y:4704 { // Create temporary variables with meaningful names ifExists := yyDollar[3].boolValUnion() @@ -19441,7 +19502,7 @@ yydefault: case 613: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4713 +//line mysql_sql.y:4716 { ifExists := yyDollar[3].boolValUnion() var Username = yyDollar[4].usernameRecordUnion().Username @@ -19456,7 +19517,7 @@ yydefault: case 614: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4724 +//line mysql_sql.y:4727 { ifExists := yyDollar[3].boolValUnion() var Username = yyDollar[4].usernameRecordUnion().Username @@ -19471,7 +19532,7 @@ yydefault: case 615: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Role -//line mysql_sql.y:4736 +//line mysql_sql.y:4739 { yyLOCAL = nil } @@ -19479,7 +19540,7 @@ yydefault: case 616: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Role -//line mysql_sql.y:4740 +//line mysql_sql.y:4743 { var UserName = yyDollar[3].str yyLOCAL = tree.NewRole( @@ -19490,7 +19551,7 @@ yydefault: case 617: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:4748 +//line mysql_sql.y:4751 { yyLOCAL = false } @@ -19498,7 +19559,7 @@ yydefault: case 618: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:4752 +//line mysql_sql.y:4755 { yyLOCAL = true } @@ -19506,7 +19567,7 @@ yydefault: case 619: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4757 +//line mysql_sql.y:4760 { yyLOCAL = nil } @@ -19514,7 +19575,7 @@ yydefault: case 620: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4761 +//line mysql_sql.y:4764 { yyLOCAL = yyDollar[1].userMiscOptionUnion() } @@ -19522,7 +19583,7 @@ yydefault: case 621: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4777 +//line mysql_sql.y:4780 { yyLOCAL = tree.NewUserMiscOptionAccountUnlock() } @@ -19530,7 +19591,7 @@ yydefault: case 622: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4781 +//line mysql_sql.y:4784 { yyLOCAL = tree.NewUserMiscOptionAccountLock() } @@ -19538,7 +19599,7 @@ yydefault: case 623: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4785 +//line mysql_sql.y:4788 { yyLOCAL = tree.NewUserMiscOptionPasswordExpireNone() } @@ -19546,7 +19607,7 @@ yydefault: case 624: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4789 +//line mysql_sql.y:4792 { var Value = yyDollar[3].item.(int64) yyLOCAL = tree.NewUserMiscOptionPasswordExpireInterval( @@ -19557,7 +19618,7 @@ yydefault: case 625: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4796 +//line mysql_sql.y:4799 { yyLOCAL = tree.NewUserMiscOptionPasswordExpireNever() } @@ -19565,7 +19626,7 @@ yydefault: case 626: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4800 +//line mysql_sql.y:4803 { yyLOCAL = tree.NewUserMiscOptionPasswordExpireDefault() } @@ -19573,7 +19634,7 @@ yydefault: case 627: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4804 +//line mysql_sql.y:4807 { yyLOCAL = tree.NewUserMiscOptionPasswordHistoryDefault() } @@ -19581,7 +19642,7 @@ yydefault: case 628: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4808 +//line mysql_sql.y:4811 { var Value = yyDollar[3].item.(int64) yyLOCAL = tree.NewUserMiscOptionPasswordHistoryCount( @@ -19592,7 +19653,7 @@ yydefault: case 629: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4815 +//line mysql_sql.y:4818 { yyLOCAL = tree.NewUserMiscOptionPasswordReuseIntervalDefault() } @@ -19600,7 +19661,7 @@ yydefault: case 630: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4819 +//line mysql_sql.y:4822 { var Value = yyDollar[4].item.(int64) yyLOCAL = tree.NewUserMiscOptionPasswordReuseIntervalCount( @@ -19611,7 +19672,7 @@ yydefault: case 631: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4826 +//line mysql_sql.y:4829 { yyLOCAL = tree.NewUserMiscOptionPasswordRequireCurrentNone() } @@ -19619,7 +19680,7 @@ yydefault: case 632: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4830 +//line mysql_sql.y:4833 { yyLOCAL = tree.NewUserMiscOptionPasswordRequireCurrentDefault() } @@ -19627,7 +19688,7 @@ yydefault: case 633: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4834 +//line mysql_sql.y:4837 { yyLOCAL = tree.NewUserMiscOptionPasswordRequireCurrentOptional() } @@ -19635,7 +19696,7 @@ yydefault: case 634: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4838 +//line mysql_sql.y:4841 { var Value = yyDollar[2].item.(int64) yyLOCAL = tree.NewUserMiscOptionFailedLoginAttempts( @@ -19646,7 +19707,7 @@ yydefault: case 635: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4845 +//line mysql_sql.y:4848 { var Value = yyDollar[2].item.(int64) yyLOCAL = tree.NewUserMiscOptionPasswordLockTimeCount( @@ -19657,27 +19718,27 @@ yydefault: case 636: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.UserMiscOption -//line mysql_sql.y:4852 +//line mysql_sql.y:4855 { yyLOCAL = tree.NewUserMiscOptionPasswordLockTimeUnbounded() } yyVAL.union = yyLOCAL case 637: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:4858 +//line mysql_sql.y:4861 { yyVAL.item = nil } case 638: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:4863 +//line mysql_sql.y:4866 { yyVAL.item = nil } case 684: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4918 +//line mysql_sql.y:4921 { yyLOCAL = &tree.ShowSQLTasks{} } @@ -19685,7 +19746,7 @@ yydefault: case 685: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4924 +//line mysql_sql.y:4927 { stmt := &tree.ShowSQLTaskRuns{} if yyDollar[4].str != "" { @@ -19701,20 +19762,20 @@ yydefault: yyVAL.union = yyLOCAL case 686: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:4938 +//line mysql_sql.y:4941 { yyVAL.str = "" } case 687: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:4942 +//line mysql_sql.y:4945 { yyVAL.str = yyDollar[2].cstrUnion().Compare() } case 688: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:4947 +//line mysql_sql.y:4950 { yyLOCAL = -1 } @@ -19722,7 +19783,7 @@ yydefault: case 689: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:4951 +//line mysql_sql.y:4954 { yyLOCAL = sqlTaskInt64(yyDollar[2].item) } @@ -19730,7 +19791,7 @@ yydefault: case 690: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4957 +//line mysql_sql.y:4960 { yyLOCAL = &tree.ShowIcebergCatalogs{ Like: yyDollar[4].comparisionExprUnion(), @@ -19741,7 +19802,7 @@ yydefault: case 691: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4965 +//line mysql_sql.y:4968 { yyLOCAL = &tree.ShowIcebergNamespaces{ Catalog: tree.Identifier(yyDollar[5].cstrUnion().Compare()), @@ -19753,7 +19814,7 @@ yydefault: case 692: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4973 +//line mysql_sql.y:4976 { yyLOCAL = &tree.ShowIcebergNamespaces{ Catalog: tree.Identifier(yyDollar[6].cstrUnion().Compare()), @@ -19765,7 +19826,7 @@ yydefault: case 693: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4981 +//line mysql_sql.y:4984 { yyLOCAL = &tree.ShowIcebergNamespaces{ Like: yyDollar[4].comparisionExprUnion(), @@ -19776,7 +19837,7 @@ yydefault: case 694: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4988 +//line mysql_sql.y:4991 { yyLOCAL = &tree.ShowIcebergTables{ Like: yyDollar[4].comparisionExprUnion(), @@ -19787,7 +19848,7 @@ yydefault: case 695: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:4995 +//line mysql_sql.y:4998 { yyLOCAL = &tree.ShowIcebergTables{ Catalog: tree.Identifier(yyDollar[5].cstrUnion().Compare()), @@ -19799,7 +19860,7 @@ yydefault: case 696: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5003 +//line mysql_sql.y:5006 { yyLOCAL = &tree.ShowIcebergTables{ Catalog: tree.Identifier(yyDollar[5].cstrUnion().Compare()), @@ -19812,7 +19873,7 @@ yydefault: case 697: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5012 +//line mysql_sql.y:5015 { yyLOCAL = &tree.ShowIcebergTables{ Catalog: tree.Identifier(yyDollar[6].cstrUnion().Compare()), @@ -19824,7 +19885,7 @@ yydefault: case 698: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5020 +//line mysql_sql.y:5023 { yyLOCAL = &tree.ShowIcebergTables{ Namespace: yyDollar[6].str, @@ -19836,7 +19897,7 @@ yydefault: case 699: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5028 +//line mysql_sql.y:5031 { yyLOCAL = &tree.ShowIcebergTables{ Namespace: yyDollar[6].str, @@ -19849,7 +19910,7 @@ yydefault: case 700: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5039 +//line mysql_sql.y:5042 { yyLOCAL = &tree.ShowMongoDBConnections{ Like: yyDollar[4].comparisionExprUnion(), @@ -19859,14 +19920,14 @@ yydefault: yyVAL.union = yyLOCAL case 701: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:5048 +//line mysql_sql.y:5051 { yyVAL.str = yyDollar[1].str } case 702: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5054 +//line mysql_sql.y:5057 { yyLOCAL = &tree.ShowLogserviceReplicas{} } @@ -19874,7 +19935,7 @@ yydefault: case 703: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5060 +//line mysql_sql.y:5063 { yyLOCAL = &tree.ShowLogserviceStores{} } @@ -19882,7 +19943,7 @@ yydefault: case 704: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5066 +//line mysql_sql.y:5069 { yyLOCAL = &tree.ShowLogserviceSettings{} } @@ -19890,7 +19951,7 @@ yydefault: case 705: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5072 +//line mysql_sql.y:5075 { yyLOCAL = &tree.ShowRules{ RoleName: yyDollar[5].cstrUnion().Compare(), @@ -19900,7 +19961,7 @@ yydefault: case 706: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5080 +//line mysql_sql.y:5083 { yyLOCAL = &tree.ShowCollation{ Like: yyDollar[3].comparisionExprUnion(), @@ -19911,7 +19972,7 @@ yydefault: case 707: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5089 +//line mysql_sql.y:5092 { yyLOCAL = &tree.ShowStages{ Like: yyDollar[3].comparisionExprUnion(), @@ -19921,7 +19982,7 @@ yydefault: case 708: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5097 +//line mysql_sql.y:5100 { yyLOCAL = &tree.ShowSnapShots{ Where: yyDollar[3].whereUnion(), @@ -19931,7 +19992,7 @@ yydefault: case 709: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5105 +//line mysql_sql.y:5108 { yyLOCAL = &tree.ShowPitr{ Where: yyDollar[3].whereUnion(), @@ -19941,7 +20002,7 @@ yydefault: case 710: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5113 +//line mysql_sql.y:5116 { yyLOCAL = &tree.ShowRecoveryWindow{ Level: tree.RECOVERYWINDOWLEVELACCOUNT, @@ -19951,7 +20012,7 @@ yydefault: case 711: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5119 +//line mysql_sql.y:5122 { yyLOCAL = &tree.ShowRecoveryWindow{ Level: tree.RECOVERYWINDOWLEVELDATABASE, @@ -19962,7 +20023,7 @@ yydefault: case 712: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5126 +//line mysql_sql.y:5129 { yyLOCAL = &tree.ShowRecoveryWindow{ Level: tree.RECOVERYWINDOWLEVELTABLE, @@ -19974,7 +20035,7 @@ yydefault: case 713: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5134 +//line mysql_sql.y:5137 { yyLOCAL = &tree.ShowRecoveryWindow{ Level: tree.RECOVERYWINDOWLEVELACCOUNT, @@ -19985,7 +20046,7 @@ yydefault: case 714: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5143 +//line mysql_sql.y:5146 { yyLOCAL = &tree.ShowGrants{ShowGrantType: tree.GrantForUser} } @@ -19993,7 +20054,7 @@ yydefault: case 715: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5147 +//line mysql_sql.y:5150 { yyLOCAL = &tree.ShowGrants{Username: yyDollar[4].usernameRecordUnion().Username, Hostname: yyDollar[4].usernameRecordUnion().Hostname, Roles: yyDollar[5].rolesUnion(), ShowGrantType: tree.GrantForUser} } @@ -20001,7 +20062,7 @@ yydefault: case 716: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5151 +//line mysql_sql.y:5154 { s := &tree.ShowGrants{} roles := []*tree.Role{ @@ -20015,7 +20076,7 @@ yydefault: case 717: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*tree.Role -//line mysql_sql.y:5162 +//line mysql_sql.y:5165 { yyLOCAL = nil } @@ -20023,7 +20084,7 @@ yydefault: case 718: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*tree.Role -//line mysql_sql.y:5166 +//line mysql_sql.y:5169 { yyLOCAL = yyDollar[2].rolesUnion() } @@ -20031,25 +20092,25 @@ yydefault: case 719: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5172 +//line mysql_sql.y:5175 { yyLOCAL = &tree.ShowTableStatus{DbName: yyDollar[5].str, Like: yyDollar[6].comparisionExprUnion(), Where: yyDollar[7].whereUnion()} } yyVAL.union = yyLOCAL case 720: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:5177 +//line mysql_sql.y:5180 { } case 722: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:5181 +//line mysql_sql.y:5184 { } case 724: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5186 +//line mysql_sql.y:5189 { yyLOCAL = &tree.ShowFunctionOrProcedureStatus{ Like: yyDollar[4].comparisionExprUnion(), @@ -20061,7 +20122,7 @@ yydefault: case 725: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5196 +//line mysql_sql.y:5199 { yyLOCAL = &tree.ShowFunctionOrProcedureStatus{ Like: yyDollar[4].comparisionExprUnion(), @@ -20073,7 +20134,7 @@ yydefault: case 726: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5206 +//line mysql_sql.y:5209 { yyLOCAL = &tree.ShowRolesStmt{ Like: yyDollar[3].comparisionExprUnion(), @@ -20083,7 +20144,7 @@ yydefault: case 727: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5214 +//line mysql_sql.y:5217 { yyLOCAL = &tree.ShowNodeList{} } @@ -20091,7 +20152,7 @@ yydefault: case 728: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5220 +//line mysql_sql.y:5223 { yyLOCAL = &tree.ShowLocks{} } @@ -20099,7 +20160,7 @@ yydefault: case 729: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5226 +//line mysql_sql.y:5229 { yyLOCAL = &tree.ShowTableNumber{DbName: yyDollar[4].str} } @@ -20107,7 +20168,7 @@ yydefault: case 730: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5232 +//line mysql_sql.y:5235 { yyLOCAL = &tree.ShowColumnNumber{Table: yyDollar[3].unresolvedObjectNameUnion(), DbName: yyDollar[4].str} } @@ -20115,7 +20176,7 @@ yydefault: case 731: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5238 +//line mysql_sql.y:5241 { yyLOCAL = &tree.ShowTableValues{Table: yyDollar[3].unresolvedObjectNameUnion(), DbName: yyDollar[4].str} } @@ -20123,7 +20184,7 @@ yydefault: case 732: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5244 +//line mysql_sql.y:5247 { yyLOCAL = &tree.ShowTableSize{Table: yyDollar[3].unresolvedObjectNameUnion(), DbName: yyDollar[4].str} } @@ -20131,7 +20192,7 @@ yydefault: case 733: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5250 +//line mysql_sql.y:5253 { s := yyDollar[2].statementUnion().(*tree.ShowTarget) s.Like = yyDollar[3].comparisionExprUnion() @@ -20142,7 +20203,7 @@ yydefault: case 734: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5259 +//line mysql_sql.y:5262 { yyLOCAL = &tree.ShowTarget{Type: tree.ShowConfig} } @@ -20150,7 +20211,7 @@ yydefault: case 735: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5263 +//line mysql_sql.y:5266 { yyLOCAL = &tree.ShowTarget{Type: tree.ShowCharset} } @@ -20158,7 +20219,7 @@ yydefault: case 736: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5267 +//line mysql_sql.y:5270 { yyLOCAL = &tree.ShowTarget{Type: tree.ShowEngines} } @@ -20166,7 +20227,7 @@ yydefault: case 737: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5271 +//line mysql_sql.y:5274 { yyLOCAL = &tree.ShowTarget{DbName: yyDollar[3].str, Type: tree.ShowTriggers} } @@ -20174,7 +20235,7 @@ yydefault: case 738: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5275 +//line mysql_sql.y:5278 { yyLOCAL = &tree.ShowTarget{DbName: yyDollar[3].str, Type: tree.ShowEvents} } @@ -20182,7 +20243,7 @@ yydefault: case 739: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5279 +//line mysql_sql.y:5282 { yyLOCAL = &tree.ShowTarget{Type: tree.ShowPlugins} } @@ -20190,7 +20251,7 @@ yydefault: case 740: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5283 +//line mysql_sql.y:5286 { yyLOCAL = &tree.ShowTarget{Type: tree.ShowPrivileges} } @@ -20198,7 +20259,7 @@ yydefault: case 741: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5287 +//line mysql_sql.y:5290 { yyLOCAL = &tree.ShowTarget{Type: tree.ShowProfiles} } @@ -20206,7 +20267,7 @@ yydefault: case 742: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5293 +//line mysql_sql.y:5296 { yyLOCAL = &tree.ShowIndex{ TableName: yyDollar[4].unresolvedObjectNameUnion(), @@ -20217,18 +20278,18 @@ yydefault: yyVAL.union = yyLOCAL case 743: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:5302 +//line mysql_sql.y:5305 { } case 744: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:5304 +//line mysql_sql.y:5307 { } case 748: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5313 +//line mysql_sql.y:5316 { yyLOCAL = &tree.ShowVariables{ Global: yyDollar[2].boolValUnion(), @@ -20240,7 +20301,7 @@ yydefault: case 749: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5323 +//line mysql_sql.y:5326 { yyLOCAL = &tree.ShowStatus{ Global: yyDollar[2].boolValUnion(), @@ -20252,7 +20313,7 @@ yydefault: case 750: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:5332 +//line mysql_sql.y:5335 { yyLOCAL = false } @@ -20260,7 +20321,7 @@ yydefault: case 751: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:5336 +//line mysql_sql.y:5339 { yyLOCAL = true } @@ -20268,7 +20329,7 @@ yydefault: case 752: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:5340 +//line mysql_sql.y:5343 { yyLOCAL = false } @@ -20276,7 +20337,7 @@ yydefault: case 753: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5346 +//line mysql_sql.y:5349 { yyLOCAL = &tree.ShowWarnings{Limit: yyDollar[3].limitUnion()} } @@ -20284,7 +20345,7 @@ yydefault: case 754: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5350 +//line mysql_sql.y:5353 { yyLOCAL = &tree.ShowWarnings{Count: true} } @@ -20292,7 +20353,7 @@ yydefault: case 755: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5356 +//line mysql_sql.y:5359 { yyLOCAL = &tree.ShowErrors{Limit: yyDollar[3].limitUnion()} } @@ -20300,7 +20361,7 @@ yydefault: case 756: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5360 +//line mysql_sql.y:5363 { yyLOCAL = &tree.ShowErrors{Count: true} } @@ -20308,7 +20369,7 @@ yydefault: case 757: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5366 +//line mysql_sql.y:5369 { yyLOCAL = &tree.ShowProcessList{Full: yyDollar[2].fullOptUnion()} } @@ -20316,7 +20377,7 @@ yydefault: case 758: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5372 +//line mysql_sql.y:5375 { yyLOCAL = &tree.ShowSequences{ DBName: yyDollar[3].str, @@ -20327,7 +20388,7 @@ yydefault: case 759: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5381 +//line mysql_sql.y:5384 { yyLOCAL = &tree.ShowTables{ Open: false, @@ -20342,7 +20403,7 @@ yydefault: case 760: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5392 +//line mysql_sql.y:5395 { yyLOCAL = &tree.ShowTables{ Open: true, @@ -20356,7 +20417,7 @@ yydefault: case 761: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5404 +//line mysql_sql.y:5407 { yyLOCAL = &tree.ShowDatabases{ Like: yyDollar[3].comparisionExprUnion(), @@ -20368,7 +20429,7 @@ yydefault: case 762: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5412 +//line mysql_sql.y:5415 { yyLOCAL = &tree.ShowDatabases{Like: yyDollar[3].comparisionExprUnion(), Where: yyDollar[4].whereUnion()} } @@ -20376,7 +20437,7 @@ yydefault: case 763: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5418 +//line mysql_sql.y:5421 { yyLOCAL = &tree.ShowColumns{ Ext: false, @@ -20392,7 +20453,7 @@ yydefault: case 764: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5430 +//line mysql_sql.y:5433 { yyLOCAL = &tree.ShowColumns{ Ext: true, @@ -20408,7 +20469,7 @@ yydefault: case 765: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5444 +//line mysql_sql.y:5447 { yyLOCAL = &tree.ShowAccounts{Like: yyDollar[3].comparisionExprUnion()} } @@ -20416,7 +20477,7 @@ yydefault: case 766: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5450 +//line mysql_sql.y:5453 { yyLOCAL = &tree.ShowPublications{Like: yyDollar[3].comparisionExprUnion()} } @@ -20424,7 +20485,7 @@ yydefault: case 767: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5456 +//line mysql_sql.y:5459 { yyLOCAL = &tree.ShowPublicationCoverage{Name: yyDollar[4].str} } @@ -20432,7 +20493,7 @@ yydefault: case 768: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5462 +//line mysql_sql.y:5465 { yyLOCAL = &tree.ShowAccountUpgrade{} } @@ -20440,7 +20501,7 @@ yydefault: case 769: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5468 +//line mysql_sql.y:5471 { yyLOCAL = &tree.ShowSubscriptions{Like: yyDollar[3].comparisionExprUnion()} } @@ -20448,7 +20509,7 @@ yydefault: case 770: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5472 +//line mysql_sql.y:5475 { yyLOCAL = &tree.ShowSubscriptions{All: true, Like: yyDollar[4].comparisionExprUnion()} } @@ -20456,7 +20517,7 @@ yydefault: case 771: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5478 +//line mysql_sql.y:5481 { yyLOCAL = &tree.ShowCcprSubscriptions{TaskId: yyDollar[4].str} } @@ -20464,7 +20525,7 @@ yydefault: case 772: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5482 +//line mysql_sql.y:5485 { yyLOCAL = &tree.ShowCcprSubscriptions{} } @@ -20472,7 +20533,7 @@ yydefault: case 773: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.ComparisonExpr -//line mysql_sql.y:5487 +//line mysql_sql.y:5490 { yyLOCAL = nil } @@ -20480,7 +20541,7 @@ yydefault: case 774: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.ComparisonExpr -//line mysql_sql.y:5491 +//line mysql_sql.y:5494 { yyLOCAL = tree.NewComparisonExpr(tree.LIKE, nil, yyDollar[2].exprUnion()) } @@ -20488,27 +20549,27 @@ yydefault: case 775: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.ComparisonExpr -//line mysql_sql.y:5495 +//line mysql_sql.y:5498 { yyLOCAL = tree.NewComparisonExpr(tree.ILIKE, nil, yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL case 776: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:5500 +//line mysql_sql.y:5503 { yyVAL.str = "" } case 777: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:5504 +//line mysql_sql.y:5507 { yyVAL.str = yyDollar[2].cstrUnion().Compare() } case 778: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UnresolvedObjectName -//line mysql_sql.y:5510 +//line mysql_sql.y:5513 { yyLOCAL = yyDollar[2].unresolvedObjectNameUnion() } @@ -20516,7 +20577,7 @@ yydefault: case 783: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:5523 +//line mysql_sql.y:5526 { yyLOCAL = false } @@ -20524,7 +20585,7 @@ yydefault: case 784: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:5527 +//line mysql_sql.y:5530 { yyLOCAL = true } @@ -20532,7 +20593,7 @@ yydefault: case 785: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5533 +//line mysql_sql.y:5536 { yyLOCAL = &tree.ShowCreateTable{ Name: yyDollar[4].unresolvedObjectNameUnion(), @@ -20543,7 +20604,7 @@ yydefault: case 786: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5541 +//line mysql_sql.y:5544 { yyLOCAL = &tree.ShowCreateView{ Name: yyDollar[4].unresolvedObjectNameUnion(), @@ -20554,7 +20615,7 @@ yydefault: case 787: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5548 +//line mysql_sql.y:5551 { yyLOCAL = &tree.ShowCreateDatabase{ IfNotExists: yyDollar[4].ifNotExistsUnion(), @@ -20566,7 +20627,7 @@ yydefault: case 788: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5556 +//line mysql_sql.y:5559 { yyLOCAL = &tree.ShowCreatePublications{Name: yyDollar[4].str} } @@ -20574,7 +20635,7 @@ yydefault: case 789: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5562 +//line mysql_sql.y:5565 { yyLOCAL = &tree.ShowBackendServers{} } @@ -20582,7 +20643,7 @@ yydefault: case 790: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnresolvedObjectName -//line mysql_sql.y:5568 +//line mysql_sql.y:5571 { tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) yyLOCAL = tree.NewUnresolvedObjectName(tblName) @@ -20591,7 +20652,7 @@ yydefault: case 791: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UnresolvedObjectName -//line mysql_sql.y:5573 +//line mysql_sql.y:5576 { dbName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[3].cstrUnion().Origin()) @@ -20600,14 +20661,14 @@ yydefault: yyVAL.union = yyLOCAL case 792: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:5581 +//line mysql_sql.y:5584 { yyVAL.str = yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) } case 793: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnresolvedObjectName -//line mysql_sql.y:5587 +//line mysql_sql.y:5590 { tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) yyLOCAL = tree.NewUnresolvedObjectName(tblName) @@ -20616,7 +20677,7 @@ yydefault: case 794: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UnresolvedObjectName -//line mysql_sql.y:5592 +//line mysql_sql.y:5595 { dbName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[3].cstrUnion().Origin()) @@ -20626,7 +20687,7 @@ yydefault: case 795: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.UnresolvedObjectName -//line mysql_sql.y:5598 +//line mysql_sql.y:5601 { yyLOCAL = tree.NewUnresolvedObjectName(yyDollar[1].cstrUnion().Compare(), yyDollar[3].cstrUnion().Compare(), yyDollar[5].cstrUnion().Compare()) } @@ -20634,7 +20695,7 @@ yydefault: case 796: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5604 +//line mysql_sql.y:5607 { yyLOCAL = tree.NewTruncateTable(yyDollar[2].tableNameUnion()) } @@ -20642,7 +20703,7 @@ yydefault: case 797: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5608 +//line mysql_sql.y:5611 { yyLOCAL = tree.NewTruncateTable(yyDollar[3].tableNameUnion()) } @@ -20650,7 +20711,7 @@ yydefault: case 819: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5639 +//line mysql_sql.y:5642 { yyLOCAL = &tree.DropSQLTask{ IfExists: yyDollar[3].boolValUnion(), @@ -20661,7 +20722,7 @@ yydefault: case 820: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5648 +//line mysql_sql.y:5651 { yyLOCAL = &tree.DropIcebergCatalog{ IfExists: yyDollar[4].boolValUnion(), @@ -20672,7 +20733,7 @@ yydefault: case 821: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5657 +//line mysql_sql.y:5660 { yyLOCAL = &tree.DropMongoDBConnection{ IfExists: yyDollar[4].boolValUnion(), @@ -20683,7 +20744,7 @@ yydefault: case 822: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5666 +//line mysql_sql.y:5669 { var ifExists = yyDollar[3].boolValUnion() var name = yyDollar[4].tableNamesUnion() @@ -20693,7 +20754,7 @@ yydefault: case 823: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5674 +//line mysql_sql.y:5677 { var ifExists = yyDollar[3].boolValUnion() var name = yyDollar[4].exprUnion() @@ -20703,7 +20764,7 @@ yydefault: case 824: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5682 +//line mysql_sql.y:5685 { var ifExists = yyDollar[3].boolValUnion() var users = yyDollar[4].usersUnion() @@ -20713,7 +20774,7 @@ yydefault: case 825: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.User -//line mysql_sql.y:5690 +//line mysql_sql.y:5693 { yyLOCAL = []*tree.User{yyDollar[1].userUnion()} } @@ -20721,7 +20782,7 @@ yydefault: case 826: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.User -//line mysql_sql.y:5694 +//line mysql_sql.y:5697 { yyLOCAL = append(yyDollar[1].usersUnion(), yyDollar[3].userUnion()) } @@ -20729,7 +20790,7 @@ yydefault: case 827: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.User -//line mysql_sql.y:5700 +//line mysql_sql.y:5703 { var Username = yyDollar[1].usernameRecordUnion().Username var Hostname = yyDollar[1].usernameRecordUnion().Hostname @@ -20744,7 +20805,7 @@ yydefault: case 828: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5713 +//line mysql_sql.y:5716 { var ifExists = yyDollar[3].boolValUnion() var roles = yyDollar[4].rolesUnion() @@ -20754,7 +20815,7 @@ yydefault: case 829: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5721 +//line mysql_sql.y:5724 { var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) var tableName = yyDollar[6].tableNameUnion() @@ -20765,7 +20826,7 @@ yydefault: case 830: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5730 +//line mysql_sql.y:5733 { var ifExists = yyDollar[4].boolValUnion() var names = yyDollar[5].tableNamesUnion() @@ -20777,7 +20838,7 @@ yydefault: case 831: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5740 +//line mysql_sql.y:5743 { var ifExists = yyDollar[3].boolValUnion() var names = yyDollar[4].tableNamesUnion() @@ -20787,7 +20848,7 @@ yydefault: case 832: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5748 +//line mysql_sql.y:5751 { var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) var ifExists = yyDollar[3].boolValUnion() @@ -20797,7 +20858,7 @@ yydefault: case 833: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5754 +//line mysql_sql.y:5757 { var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) var ifExists = yyDollar[3].boolValUnion() @@ -20807,7 +20868,7 @@ yydefault: case 834: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5762 +//line mysql_sql.y:5765 { yyLOCAL = tree.NewDeallocate(tree.Identifier(yyDollar[3].str), true) } @@ -20815,7 +20876,7 @@ yydefault: case 835: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5768 +//line mysql_sql.y:5771 { var ifExists = yyDollar[3].boolValUnion() var name = yyDollar[4].functionNameUnion() @@ -20828,7 +20889,7 @@ yydefault: case 836: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5779 +//line mysql_sql.y:5782 { var name = yyDollar[3].procNameUnion() var ifExists = false @@ -20838,7 +20899,7 @@ yydefault: case 837: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5785 +//line mysql_sql.y:5788 { var name = yyDollar[5].procNameUnion() var ifExists = true @@ -20848,7 +20909,7 @@ yydefault: case 838: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5793 +//line mysql_sql.y:5796 { if intoErr := tree.ValidateSelectIntoEnclosingStatement(yyDollar[1].statementUnion()); intoErr != "" { yylex.Error(intoErr) @@ -20860,7 +20921,7 @@ yydefault: case 839: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5801 +//line mysql_sql.y:5804 { if intoErr := tree.ValidateSelectIntoEnclosingStatement(yyDollar[1].statementUnion()); intoErr != "" { yylex.Error(intoErr) @@ -20872,7 +20933,7 @@ yydefault: case 840: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5809 +//line mysql_sql.y:5812 { yyDollar[2].statementUnion().(*tree.Delete).With = yyDollar[1].withClauseUnion() if intoErr := tree.ValidateSelectIntoEnclosingStatement(yyDollar[2].statementUnion()); intoErr != "" { @@ -20885,7 +20946,7 @@ yydefault: case 841: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5818 +//line mysql_sql.y:5821 { yyDollar[2].statementUnion().(*tree.Delete).With = yyDollar[1].withClauseUnion() if intoErr := tree.ValidateSelectIntoEnclosingStatement(yyDollar[2].statementUnion()); intoErr != "" { @@ -20898,7 +20959,7 @@ yydefault: case 842: yyDollar = yyS[yypt-12 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5829 +//line mysql_sql.y:5832 { // Single-Table Syntax t := &tree.AliasedTableExpr{ @@ -20923,7 +20984,7 @@ yydefault: case 843: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5850 +//line mysql_sql.y:5853 { // Multiple-Table Syntax yyLOCAL = &tree.Delete{ @@ -20940,7 +21001,7 @@ yydefault: case 844: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5865 +//line mysql_sql.y:5868 { // Multiple-Table Syntax yyLOCAL = &tree.Delete{ @@ -20957,7 +21018,7 @@ yydefault: case 845: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableExprs -//line mysql_sql.y:5880 +//line mysql_sql.y:5883 { yyLOCAL = tree.TableExprs{yyDollar[1].tableNameUnion()} } @@ -20965,7 +21026,7 @@ yydefault: case 846: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableExprs -//line mysql_sql.y:5884 +//line mysql_sql.y:5887 { yyLOCAL = append(yyDollar[1].tableExprsUnion(), yyDollar[3].tableNameUnion()) } @@ -20973,7 +21034,7 @@ yydefault: case 847: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.TableName -//line mysql_sql.y:5890 +//line mysql_sql.y:5893 { tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) prefix := tree.ObjectNamePrefix{ExplicitSchema: false} @@ -20983,7 +21044,7 @@ yydefault: case 848: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.TableName -//line mysql_sql.y:5896 +//line mysql_sql.y:5899 { dbName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[3].cstrUnion().Origin()) @@ -20993,47 +21054,47 @@ yydefault: yyVAL.union = yyLOCAL case 849: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:5905 +//line mysql_sql.y:5908 { } case 850: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:5907 +//line mysql_sql.y:5910 { } case 851: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:5910 +//line mysql_sql.y:5913 { yyVAL.str = "" } case 856: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:5919 +//line mysql_sql.y:5922 { yyVAL.str = "" } case 858: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:5923 +//line mysql_sql.y:5926 { yyVAL.str = "" } case 859: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:5927 +//line mysql_sql.y:5930 { yyVAL.str = "ignore" } case 860: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:5935 +//line mysql_sql.y:5938 { } case 863: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:5941 +//line mysql_sql.y:5944 { rep := yyDollar[5].replaceUnion() if intoErr := tree.ValidateSelectIntoNotAllowed(rep.Rows); intoErr != "" { @@ -21052,7 +21113,7 @@ yydefault: case 864: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.Replace -//line mysql_sql.y:5958 +//line mysql_sql.y:5961 { vc := tree.NewValuesClause(yyDollar[2].rowsExprsUnion()) yyLOCAL = &tree.Replace{ @@ -21063,7 +21124,7 @@ yydefault: case 865: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Replace -//line mysql_sql.y:5965 +//line mysql_sql.y:5968 { yyLOCAL = &tree.Replace{ Rows: yyDollar[1].selectUnion(), @@ -21073,7 +21134,7 @@ yydefault: case 866: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.Replace -//line mysql_sql.y:5971 +//line mysql_sql.y:5974 { vc := tree.NewValuesClause(yyDollar[5].rowsExprsUnion()) yyLOCAL = &tree.Replace{ @@ -21086,7 +21147,7 @@ yydefault: case 867: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Replace -//line mysql_sql.y:5980 +//line mysql_sql.y:5983 { vc := tree.NewValuesClause(yyDollar[4].rowsExprsUnion()) yyLOCAL = &tree.Replace{ @@ -21097,7 +21158,7 @@ yydefault: case 868: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Replace -//line mysql_sql.y:5987 +//line mysql_sql.y:5990 { yyLOCAL = &tree.Replace{ Columns: yyDollar[2].insertColumnsUnion().Identifiers, @@ -21109,7 +21170,7 @@ yydefault: case 869: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.Replace -//line mysql_sql.y:5995 +//line mysql_sql.y:5998 { if yyDollar[2].assignmentsUnion() == nil { yylex.Error("the set list of replace can not be empty") @@ -21135,7 +21196,7 @@ yydefault: case 871: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6020 +//line mysql_sql.y:6023 { yyDollar[2].statementUnion().(*tree.Insert).With = yyDollar[1].withClauseUnion() if intoErr := tree.ValidateSelectIntoEnclosingStatement(yyDollar[2].statementUnion()); intoErr != "" { @@ -21148,7 +21209,7 @@ yydefault: case 873: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6030 +//line mysql_sql.y:6033 { yyDollar[2].statementUnion().(*tree.MultiInsert).With = yyDollar[1].withClauseUnion() yyLOCAL = yyDollar[2].statementUnion() @@ -21157,7 +21218,7 @@ yydefault: case 874: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6040 +//line mysql_sql.y:6043 { if intoErr := tree.ValidateSelectIntoNotAllowed(yyDollar[4].selectUnion()); intoErr != "" { yylex.Error(intoErr) @@ -21169,7 +21230,7 @@ yydefault: case 875: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6048 +//line mysql_sql.y:6051 { if intoErr := tree.ValidateSelectIntoNotAllowed(yyDollar[5].selectUnion()); intoErr != "" { yylex.Error(intoErr) @@ -21181,7 +21242,7 @@ yydefault: case 876: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6056 +//line mysql_sql.y:6059 { if intoErr := tree.ValidateSelectIntoNotAllowed(yyDollar[5].selectUnion()); intoErr != "" { yylex.Error(intoErr) @@ -21193,7 +21254,7 @@ yydefault: case 877: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.MultiInsertWhen -//line mysql_sql.y:6066 +//line mysql_sql.y:6069 { yyLOCAL = []*tree.MultiInsertWhen{yyDollar[1].multiInsertWhenUnion()} } @@ -21201,7 +21262,7 @@ yydefault: case 878: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*tree.MultiInsertWhen -//line mysql_sql.y:6070 +//line mysql_sql.y:6073 { yyLOCAL = append(yyDollar[1].multiInsertWhensUnion(), yyDollar[2].multiInsertWhenUnion()) } @@ -21209,7 +21270,7 @@ yydefault: case 879: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.MultiInsertWhen -//line mysql_sql.y:6076 +//line mysql_sql.y:6079 { yyLOCAL = &tree.MultiInsertWhen{Cond: yyDollar[2].exprUnion(), Targets: yyDollar[4].multiInsertTargetsUnion()} } @@ -21217,7 +21278,7 @@ yydefault: case 880: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*tree.MultiInsertTarget -//line mysql_sql.y:6081 +//line mysql_sql.y:6084 { yyLOCAL = nil } @@ -21225,7 +21286,7 @@ yydefault: case 881: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*tree.MultiInsertTarget -//line mysql_sql.y:6085 +//line mysql_sql.y:6088 { yyLOCAL = yyDollar[2].multiInsertTargetsUnion() } @@ -21233,7 +21294,7 @@ yydefault: case 882: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.MultiInsertTarget -//line mysql_sql.y:6091 +//line mysql_sql.y:6094 { yyLOCAL = []*tree.MultiInsertTarget{yyDollar[1].multiInsertTargetUnion()} } @@ -21241,7 +21302,7 @@ yydefault: case 883: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*tree.MultiInsertTarget -//line mysql_sql.y:6095 +//line mysql_sql.y:6098 { yyLOCAL = append(yyDollar[1].multiInsertTargetsUnion(), yyDollar[2].multiInsertTargetUnion()) } @@ -21249,7 +21310,7 @@ yydefault: case 884: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.MultiInsertTarget -//line mysql_sql.y:6101 +//line mysql_sql.y:6104 { yyLOCAL = &tree.MultiInsertTarget{Table: yyDollar[2].tableNameUnion()} } @@ -21257,7 +21318,7 @@ yydefault: case 885: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.MultiInsertTarget -//line mysql_sql.y:6105 +//line mysql_sql.y:6108 { yyLOCAL = &tree.MultiInsertTarget{Table: yyDollar[2].tableNameUnion(), Values: yyDollar[5].exprsUnion()} } @@ -21265,7 +21326,7 @@ yydefault: case 886: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.MultiInsertTarget -//line mysql_sql.y:6109 +//line mysql_sql.y:6112 { yyLOCAL = &tree.MultiInsertTarget{Table: yyDollar[2].tableNameUnion(), Columns: yyDollar[4].insertColumnsUnion().Identifiers, ColumnNames: yyDollar[4].insertColumnsUnion().Names} } @@ -21273,7 +21334,7 @@ yydefault: case 887: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL *tree.MultiInsertTarget -//line mysql_sql.y:6113 +//line mysql_sql.y:6116 { yyLOCAL = &tree.MultiInsertTarget{Table: yyDollar[2].tableNameUnion(), Columns: yyDollar[4].insertColumnsUnion().Identifiers, ColumnNames: yyDollar[4].insertColumnsUnion().Names, Values: yyDollar[8].exprsUnion()} } @@ -21281,7 +21342,7 @@ yydefault: case 888: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6119 +//line mysql_sql.y:6122 { ins := yyDollar[4].insertUnion() if intoErr := tree.ValidateSelectIntoNotAllowed(ins.Rows); intoErr != "" { @@ -21308,7 +21369,7 @@ yydefault: case 889: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6142 +//line mysql_sql.y:6145 { ins := yyDollar[5].insertUnion() if intoErr := tree.ValidateSelectIntoNotAllowed(ins.Rows); intoErr != "" { @@ -21331,7 +21392,7 @@ yydefault: case 890: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6161 +//line mysql_sql.y:6164 { ins := yyDollar[5].insertUnion() if intoErr := tree.ValidateSelectIntoNotAllowed(ins.Rows); intoErr != "" { @@ -21355,7 +21416,7 @@ yydefault: case 891: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6181 +//line mysql_sql.y:6184 { ins := yyDollar[5].insertUnion() if intoErr := tree.ValidateSelectIntoNotAllowed(ins.Rows); intoErr != "" { @@ -21382,7 +21443,7 @@ yydefault: case 892: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.SelectExprs -//line mysql_sql.y:6205 +//line mysql_sql.y:6208 { yyLOCAL = nil } @@ -21390,7 +21451,7 @@ yydefault: case 893: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.SelectExprs -//line mysql_sql.y:6209 +//line mysql_sql.y:6212 { yyLOCAL = yyDollar[2].selectExprsUnion() } @@ -21398,7 +21459,7 @@ yydefault: case 894: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6215 +//line mysql_sql.y:6218 { yyLOCAL = yyDollar[1].mergeUnion() } @@ -21406,7 +21467,7 @@ yydefault: case 895: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:6219 +//line mysql_sql.y:6222 { yyDollar[2].mergeUnion().With = yyDollar[1].withClauseUnion() yyLOCAL = yyDollar[2].mergeUnion() @@ -21415,7 +21476,7 @@ yydefault: case 896: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.Merge -//line mysql_sql.y:6226 +//line mysql_sql.y:6229 { yyLOCAL = &tree.Merge{ Target: yyDollar[3].tableExprUnion(), @@ -21428,7 +21489,7 @@ yydefault: case 897: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL *tree.Merge -//line mysql_sql.y:6235 +//line mysql_sql.y:6238 { yyLOCAL = &tree.Merge{ Target: yyDollar[3].tableExprUnion(), @@ -21442,7 +21503,7 @@ yydefault: case 898: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.MergeClauses -//line mysql_sql.y:6247 +//line mysql_sql.y:6250 { yyLOCAL = tree.MergeClauses{yyDollar[1].mergeClauseUnion()} } @@ -21450,7 +21511,7 @@ yydefault: case 899: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.MergeClauses -//line mysql_sql.y:6251 +//line mysql_sql.y:6254 { yyLOCAL = append(yyDollar[1].mergeClausesUnion(), yyDollar[2].mergeClauseUnion()) } @@ -21458,7 +21519,7 @@ yydefault: case 900: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *tree.MergeClause -//line mysql_sql.y:6257 +//line mysql_sql.y:6260 { yyLOCAL = &tree.MergeClause{ Matched: true, @@ -21471,7 +21532,7 @@ yydefault: case 901: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.MergeClause -//line mysql_sql.y:6266 +//line mysql_sql.y:6269 { yyLOCAL = &tree.MergeClause{ Matched: true, @@ -21483,7 +21544,7 @@ yydefault: case 902: yyDollar = yyS[yypt-13 : yypt+1] var yyLOCAL *tree.MergeClause -//line mysql_sql.y:6274 +//line mysql_sql.y:6277 { yyLOCAL = &tree.MergeClause{ Matched: false, @@ -21497,7 +21558,7 @@ yydefault: case 903: yyDollar = yyS[yypt-13 : yypt+1] var yyLOCAL *tree.MergeClause -//line mysql_sql.y:6284 +//line mysql_sql.y:6287 { yyLOCAL = &tree.MergeClause{ Matched: false, @@ -21511,7 +21572,7 @@ yydefault: case 904: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL *tree.MergeClause -//line mysql_sql.y:6294 +//line mysql_sql.y:6297 { yyLOCAL = &tree.MergeClause{ Matched: false, @@ -21524,7 +21585,7 @@ yydefault: case 905: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL *tree.MergeClause -//line mysql_sql.y:6303 +//line mysql_sql.y:6306 { yyLOCAL = &tree.MergeClause{ Matched: false, @@ -21536,7 +21597,7 @@ yydefault: yyVAL.union = yyLOCAL case 906: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:6314 +//line mysql_sql.y:6317 { if !strings.EqualFold(yyDollar[1].cstrUnion().Origin(), "matched") { yylex.Error("expected MATCHED") @@ -21547,7 +21608,7 @@ yydefault: case 907: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:6323 +//line mysql_sql.y:6326 { yyLOCAL = nil } @@ -21555,7 +21616,7 @@ yydefault: case 908: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:6327 +//line mysql_sql.y:6330 { yyLOCAL = yyDollar[2].exprUnion() } @@ -21563,7 +21624,7 @@ yydefault: case 909: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:6333 +//line mysql_sql.y:6336 { yyLOCAL = tree.IdentifierList{tree.Identifier(yyDollar[1].str)} } @@ -21571,7 +21632,7 @@ yydefault: case 910: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:6337 +//line mysql_sql.y:6340 { yyLOCAL = append(yyDollar[1].identifierListUnion(), tree.Identifier(yyDollar[3].str)) } @@ -21579,7 +21640,7 @@ yydefault: case 911: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.Insert -//line mysql_sql.y:6343 +//line mysql_sql.y:6346 { vc := tree.NewValuesClause(yyDollar[2].rowsExprsUnion()) yyLOCAL = &tree.Insert{ @@ -21590,7 +21651,7 @@ yydefault: case 912: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Insert -//line mysql_sql.y:6350 +//line mysql_sql.y:6353 { yyLOCAL = &tree.Insert{ Rows: yyDollar[1].selectUnion(), @@ -21600,7 +21661,7 @@ yydefault: case 913: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.Insert -//line mysql_sql.y:6356 +//line mysql_sql.y:6359 { vc := tree.NewValuesClause(yyDollar[5].rowsExprsUnion()) yyLOCAL = &tree.Insert{ @@ -21613,7 +21674,7 @@ yydefault: case 914: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Insert -//line mysql_sql.y:6365 +//line mysql_sql.y:6368 { vc := tree.NewValuesClause(yyDollar[4].rowsExprsUnion()) yyLOCAL = &tree.Insert{ @@ -21624,7 +21685,7 @@ yydefault: case 915: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Insert -//line mysql_sql.y:6372 +//line mysql_sql.y:6375 { yyLOCAL = &tree.Insert{ Columns: yyDollar[2].insertColumnsUnion().Identifiers, @@ -21636,7 +21697,7 @@ yydefault: case 916: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.Insert -//line mysql_sql.y:6380 +//line mysql_sql.y:6383 { if yyDollar[2].assignmentsUnion() == nil { yylex.Error("the set list of insert can not be empty") @@ -21661,7 +21722,7 @@ yydefault: case 917: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:6402 +//line mysql_sql.y:6405 { yyLOCAL = []*tree.UpdateExpr{} } @@ -21669,7 +21730,7 @@ yydefault: case 918: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:6406 +//line mysql_sql.y:6409 { yyLOCAL = yyDollar[1].updateExprsUnion() } @@ -21677,7 +21738,7 @@ yydefault: case 919: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:6412 +//line mysql_sql.y:6415 { yyLOCAL = yyDollar[5].updateExprsUnion() } @@ -21685,7 +21746,7 @@ yydefault: case 920: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.UpdateExprs -//line mysql_sql.y:6416 +//line mysql_sql.y:6419 { yyLOCAL = []*tree.UpdateExpr{nil} } @@ -21693,7 +21754,7 @@ yydefault: case 921: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*tree.Assignment -//line mysql_sql.y:6422 +//line mysql_sql.y:6425 { yyLOCAL = nil } @@ -21701,7 +21762,7 @@ yydefault: case 922: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.Assignment -//line mysql_sql.y:6426 +//line mysql_sql.y:6429 { yyLOCAL = []*tree.Assignment{yyDollar[1].assignmentUnion()} } @@ -21709,7 +21770,7 @@ yydefault: case 923: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.Assignment -//line mysql_sql.y:6430 +//line mysql_sql.y:6433 { yyLOCAL = append(yyDollar[1].assignmentsUnion(), yyDollar[3].assignmentUnion()) } @@ -21717,7 +21778,7 @@ yydefault: case 924: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Assignment -//line mysql_sql.y:6436 +//line mysql_sql.y:6439 { yyLOCAL = &tree.Assignment{ Column: tree.Identifier(yyDollar[1].unresolvedNameUnion().ColName()), @@ -21729,7 +21790,7 @@ yydefault: case 925: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.InsertColumns -//line mysql_sql.y:6446 +//line mysql_sql.y:6449 { yyLOCAL = tree.InsertColumns{ Identifiers: tree.IdentifierList{tree.Identifier(yyDollar[1].unresolvedNameUnion().ColName())}, @@ -21740,7 +21801,7 @@ yydefault: case 926: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.InsertColumns -//line mysql_sql.y:6453 +//line mysql_sql.y:6456 { yyLOCAL = yyDollar[1].insertColumnsUnion() yyLOCAL.Identifiers = append(yyDollar[1].insertColumnsUnion().Identifiers, tree.Identifier(yyDollar[3].unresolvedNameUnion().ColName())) @@ -21750,7 +21811,7 @@ yydefault: case 927: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:6461 +//line mysql_sql.y:6464 { yyLOCAL = tree.NewUnresolvedName(yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin())) } @@ -21758,7 +21819,7 @@ yydefault: case 928: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:6465 +//line mysql_sql.y:6468 { tblName := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) yyLOCAL = tree.NewUnresolvedName(tblName, yyDollar[3].cstrUnion()) @@ -21767,7 +21828,7 @@ yydefault: case 929: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:6470 +//line mysql_sql.y:6473 { dbName := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) tblName := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[3].cstrUnion().Origin()) @@ -21777,7 +21838,7 @@ yydefault: case 930: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:6478 +//line mysql_sql.y:6481 { yyLOCAL = tree.IdentifierList{tree.Identifier(yyDollar[1].cstrUnion().Compare())} } @@ -21785,7 +21846,7 @@ yydefault: case 931: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:6482 +//line mysql_sql.y:6485 { yyLOCAL = tree.IdentifierList{tree.Identifier(yyDollar[3].cstrUnion().Compare())} } @@ -21793,7 +21854,7 @@ yydefault: case 932: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:6486 +//line mysql_sql.y:6489 { yyLOCAL = append(yyDollar[1].identifierListUnion(), tree.Identifier(yyDollar[3].cstrUnion().Compare())) } @@ -21801,7 +21862,7 @@ yydefault: case 933: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:6490 +//line mysql_sql.y:6493 { yyLOCAL = append(yyDollar[1].identifierListUnion(), tree.Identifier(yyDollar[5].cstrUnion().Compare())) } @@ -21809,7 +21870,7 @@ yydefault: case 934: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.Exprs -//line mysql_sql.y:6496 +//line mysql_sql.y:6499 { yyLOCAL = []tree.Exprs{yyDollar[1].exprsUnion()} } @@ -21817,7 +21878,7 @@ yydefault: case 935: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.Exprs -//line mysql_sql.y:6500 +//line mysql_sql.y:6503 { yyLOCAL = append(yyDollar[1].rowsExprsUnion(), yyDollar[3].exprsUnion()) } @@ -21825,20 +21886,20 @@ yydefault: case 936: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:6506 +//line mysql_sql.y:6509 { yyLOCAL = yyDollar[3].exprsUnion() } yyVAL.union = yyLOCAL case 937: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:6511 +//line mysql_sql.y:6514 { } case 939: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:6515 +//line mysql_sql.y:6518 { yyLOCAL = nil } @@ -21846,7 +21907,7 @@ yydefault: case 941: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:6522 +//line mysql_sql.y:6525 { yyLOCAL = tree.Exprs{yyDollar[1].exprUnion()} } @@ -21854,7 +21915,7 @@ yydefault: case 942: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:6526 +//line mysql_sql.y:6529 { yyLOCAL = append(yyDollar[1].exprsUnion(), yyDollar[3].exprUnion()) } @@ -21862,7 +21923,7 @@ yydefault: case 944: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:6533 +//line mysql_sql.y:6536 { yyLOCAL = &tree.DefaultVal{} } @@ -21870,7 +21931,7 @@ yydefault: case 945: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:6538 +//line mysql_sql.y:6541 { yyLOCAL = nil } @@ -21878,7 +21939,7 @@ yydefault: case 946: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:6542 +//line mysql_sql.y:6545 { yyLOCAL = yyDollar[3].identifierListUnion() } @@ -21886,7 +21947,7 @@ yydefault: case 947: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.InsertPartitionClause -//line mysql_sql.y:6547 +//line mysql_sql.y:6550 { yyLOCAL = nil } @@ -21894,7 +21955,7 @@ yydefault: case 948: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.InsertPartitionClause -//line mysql_sql.y:6551 +//line mysql_sql.y:6554 { yyLOCAL = &tree.InsertPartitionClause{Names: yyDollar[3].identifierListUnion()} } @@ -21902,7 +21963,7 @@ yydefault: case 949: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.InsertPartitionClause -//line mysql_sql.y:6555 +//line mysql_sql.y:6558 { yyLOCAL = &tree.InsertPartitionClause{Values: yyDollar[3].partitionValuesUnion()} } @@ -21910,7 +21971,7 @@ yydefault: case 950: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.PartitionValues -//line mysql_sql.y:6561 +//line mysql_sql.y:6564 { yyLOCAL = tree.PartitionValues{{Name: tree.Identifier(yyDollar[1].cstrUnion().Compare()), Expr: yyDollar[3].exprUnion()}} } @@ -21918,7 +21979,7 @@ yydefault: case 951: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.PartitionValues -//line mysql_sql.y:6565 +//line mysql_sql.y:6568 { yyLOCAL = append(yyDollar[1].partitionValuesUnion(), tree.PartitionValue{Name: tree.Identifier(yyDollar[3].cstrUnion().Compare()), Expr: yyDollar[5].exprUnion()}) } @@ -21926,7 +21987,7 @@ yydefault: case 952: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:6571 +//line mysql_sql.y:6574 { yyLOCAL = tree.IdentifierList{tree.Identifier(yyDollar[1].cstrUnion().Compare())} } @@ -21934,7 +21995,7 @@ yydefault: case 953: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:6575 +//line mysql_sql.y:6578 { yyLOCAL = append(yyDollar[1].identifierListUnion(), tree.Identifier(yyDollar[3].cstrUnion().Compare())) } @@ -21942,7 +22003,7 @@ yydefault: case 954: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:6581 +//line mysql_sql.y:6584 { yyLOCAL = yyDollar[2].tableNameUnion() } @@ -21950,7 +22011,7 @@ yydefault: case 955: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:6585 +//line mysql_sql.y:6588 { yyLOCAL = yyDollar[1].tableNameUnion() } @@ -21958,7 +22019,7 @@ yydefault: case 956: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.SelectInto -//line mysql_sql.y:6591 +//line mysql_sql.y:6594 { yyLOCAL = &tree.SelectInto{} } @@ -21966,7 +22027,7 @@ yydefault: case 957: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL *tree.SelectInto -//line mysql_sql.y:6595 +//line mysql_sql.y:6598 { yyLOCAL = &tree.SelectInto{Export: &tree.ExportParam{ Outfile: true, @@ -21984,20 +22045,20 @@ yydefault: case 958: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.SelectInto -//line mysql_sql.y:6609 +//line mysql_sql.y:6612 { yyLOCAL = &tree.SelectInto{UserVars: yyDollar[2].varExprsUnion()} } yyVAL.union = yyLOCAL case 959: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:6614 +//line mysql_sql.y:6617 { yyVAL.str = "" } case 960: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:6618 +//line mysql_sql.y:6621 { str := strings.ToLower(yyDollar[2].str) if str != "csv" && str != "jsonline" && str != "parquet" { @@ -22009,7 +22070,7 @@ yydefault: case 961: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:6628 +//line mysql_sql.y:6631 { yyLOCAL = uint64(0) } @@ -22017,7 +22078,7 @@ yydefault: case 962: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:6632 +//line mysql_sql.y:6635 { size, err := util.ParseDataSize(yyDollar[2].str) if err != nil { @@ -22030,7 +22091,7 @@ yydefault: case 963: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:6642 +//line mysql_sql.y:6645 { yyLOCAL = &tree.Fields{ Terminated: &tree.Terminated{ @@ -22045,7 +22106,7 @@ yydefault: case 964: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:6653 +//line mysql_sql.y:6656 { yyLOCAL = &tree.Fields{ Terminated: &tree.Terminated{ @@ -22060,7 +22121,7 @@ yydefault: case 965: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:6664 +//line mysql_sql.y:6667 { str := yyDollar[7].str if str != "\\" && len(str) > 1 { @@ -22086,7 +22147,7 @@ yydefault: case 966: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Fields -//line mysql_sql.y:6686 +//line mysql_sql.y:6689 { str := yyDollar[4].str if str != "\\" && len(str) > 1 { @@ -22112,7 +22173,7 @@ yydefault: case 967: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Lines -//line mysql_sql.y:6709 +//line mysql_sql.y:6712 { yyLOCAL = &tree.Lines{ TerminatedBy: &tree.Terminated{ @@ -22124,7 +22185,7 @@ yydefault: case 968: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.Lines -//line mysql_sql.y:6717 +//line mysql_sql.y:6720 { yyLOCAL = &tree.Lines{ TerminatedBy: &tree.Terminated{ @@ -22136,7 +22197,7 @@ yydefault: case 969: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:6726 +//line mysql_sql.y:6729 { yyLOCAL = true } @@ -22144,7 +22205,7 @@ yydefault: case 970: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:6730 +//line mysql_sql.y:6733 { str := strings.ToLower(yyDollar[2].str) if str == "true" { @@ -22160,7 +22221,7 @@ yydefault: case 971: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:6743 +//line mysql_sql.y:6746 { yyLOCAL = 0 } @@ -22168,7 +22229,7 @@ yydefault: case 972: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:6747 +//line mysql_sql.y:6750 { yyLOCAL = yyDollar[2].item.(int64) } @@ -22176,7 +22237,7 @@ yydefault: case 973: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:6752 +//line mysql_sql.y:6755 { yyLOCAL = []string{} } @@ -22184,7 +22245,7 @@ yydefault: case 974: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:6756 +//line mysql_sql.y:6759 { yyLOCAL = yyDollar[3].strsUnion() } @@ -22192,7 +22253,7 @@ yydefault: case 975: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:6762 +//line mysql_sql.y:6765 { yyLOCAL = make([]string, 0, 4) yyLOCAL = append(yyLOCAL, yyDollar[1].cstrUnion().Compare()) @@ -22201,7 +22262,7 @@ yydefault: case 976: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:6767 +//line mysql_sql.y:6770 { yyLOCAL = append(yyDollar[1].strsUnion(), yyDollar[3].cstrUnion().Compare()) } @@ -22209,7 +22270,7 @@ yydefault: case 977: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:6776 +//line mysql_sql.y:6779 { intoVars, deprecatedInto, intoErr := tree.SelectIntoVariablesForTopLevel(yyDollar[1].selectStatementUnion()) if intoErr != "" { @@ -22226,7 +22287,7 @@ yydefault: case 979: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:6792 +//line mysql_sql.y:6795 { yyLOCAL = yyDollar[1].selectUnion() } @@ -22234,7 +22295,7 @@ yydefault: case 980: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:6796 +//line mysql_sql.y:6799 { intoVars, deprecatedInto, intoErr := tree.SelectIntoVariablesForTopLevel(yyDollar[1].selectStatementUnion()) if intoErr != "" { @@ -22251,7 +22312,7 @@ yydefault: case 981: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:6816 +//line mysql_sql.y:6819 { yyLOCAL = yyDollar[1].selectUnion() } @@ -22259,7 +22320,7 @@ yydefault: case 982: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:6820 +//line mysql_sql.y:6823 { yyLOCAL = tree.NewSelect(&tree.ValuesClause{Rows: yyDollar[2].rowsExprsUnion(), RowWord: true}, yyDollar[3].orderByUnion(), yyDollar[4].limitUnion()) } @@ -22267,7 +22328,7 @@ yydefault: case 983: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:6826 +//line mysql_sql.y:6829 { intoVars, deprecatedInto, intoErr := tree.SelectIntoVariablesForTopLevel(yyDollar[1].selectStatementUnion()) if intoErr != "" { @@ -22288,7 +22349,7 @@ yydefault: case 984: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:6843 +//line mysql_sql.y:6846 { intoVars, deprecatedInto, intoErr := tree.SelectIntoVariablesForTopLevel(yyDollar[1].selectStatementUnion()) if intoErr != "" { @@ -22309,7 +22370,7 @@ yydefault: case 985: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:6860 +//line mysql_sql.y:6863 { intoVars, deprecatedInto, intoErr := tree.SelectIntoVariablesForTopLevel(yyDollar[1].selectStatementUnion()) if intoErr != "" { @@ -22330,7 +22391,7 @@ yydefault: case 986: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:6877 +//line mysql_sql.y:6880 { intoVars, deprecatedInto, intoErr := tree.SelectIntoVariablesForTopLevel(yyDollar[1].selectStatementUnion()) if intoErr != "" { @@ -22351,7 +22412,7 @@ yydefault: case 987: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:6894 +//line mysql_sql.y:6897 { intoVars, deprecatedInto, intoErr := tree.SelectIntoVariablesForTopLevel(yyDollar[1].selectStatementUnion()) if intoErr != "" { @@ -22372,7 +22433,7 @@ yydefault: case 988: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:6911 +//line mysql_sql.y:6914 { intoVars, deprecatedInto, intoErr := tree.SelectIntoVariablesForTopLevel(yyDollar[1].selectStatementUnion()) if intoErr != "" { @@ -22393,7 +22454,7 @@ yydefault: case 989: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:6928 +//line mysql_sql.y:6931 { intoVars, deprecatedInto, intoErr := tree.SelectIntoVariablesForTopLevel(yyDollar[2].selectStatementUnion()) if intoErr != "" { @@ -22414,7 +22475,7 @@ yydefault: case 990: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:6945 +//line mysql_sql.y:6948 { intoVars, deprecatedInto, intoErr := tree.SelectIntoVariablesForTopLevel(yyDollar[2].selectStatementUnion()) if intoErr != "" { @@ -22435,7 +22496,7 @@ yydefault: case 991: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:6962 +//line mysql_sql.y:6965 { intoVars, deprecatedInto, intoErr := tree.SelectIntoVariablesForTopLevel(yyDollar[2].selectStatementUnion()) if intoErr != "" { @@ -22456,7 +22517,7 @@ yydefault: case 992: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:6979 +//line mysql_sql.y:6982 { intoVars, deprecatedInto, intoErr := tree.SelectIntoVariablesForTopLevel(yyDollar[2].selectStatementUnion()) if intoErr != "" { @@ -22477,7 +22538,7 @@ yydefault: case 993: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:6996 +//line mysql_sql.y:6999 { intoVars, deprecatedInto, intoErr := tree.SelectIntoVariablesForTopLevel(yyDollar[2].selectStatementUnion()) if intoErr != "" { @@ -22498,7 +22559,7 @@ yydefault: case 994: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.TimeWindow -//line mysql_sql.y:7014 +//line mysql_sql.y:7017 { yyLOCAL = nil } @@ -22506,7 +22567,7 @@ yydefault: case 995: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.TimeWindow -//line mysql_sql.y:7018 +//line mysql_sql.y:7021 { yyLOCAL = yyDollar[1].timeWindowUnion() } @@ -22514,7 +22575,7 @@ yydefault: case 996: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.TimeWindow -//line mysql_sql.y:7024 +//line mysql_sql.y:7027 { yyLOCAL = &tree.TimeWindow{ Interval: yyDollar[1].timeIntervalUnion(), @@ -22527,7 +22588,7 @@ yydefault: case 997: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.Interval -//line mysql_sql.y:7035 +//line mysql_sql.y:7038 { str := fmt.Sprintf("%v", yyDollar[5].item) v, errStr := util.GetInt64(yyDollar[5].item) @@ -22545,7 +22606,7 @@ yydefault: case 998: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Sliding -//line mysql_sql.y:7050 +//line mysql_sql.y:7053 { yyLOCAL = nil } @@ -22553,7 +22614,7 @@ yydefault: case 999: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.Sliding -//line mysql_sql.y:7054 +//line mysql_sql.y:7057 { str := fmt.Sprintf("%v", yyDollar[3].item) v, errStr := util.GetInt64(yyDollar[3].item) @@ -22570,7 +22631,7 @@ yydefault: case 1000: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:7068 +//line mysql_sql.y:7071 { yyLOCAL = false } @@ -22578,7 +22639,7 @@ yydefault: case 1001: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:7072 +//line mysql_sql.y:7075 { yyLOCAL = true } @@ -22586,7 +22647,7 @@ yydefault: case 1002: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Fill -//line mysql_sql.y:7077 +//line mysql_sql.y:7080 { yyLOCAL = nil } @@ -22594,7 +22655,7 @@ yydefault: case 1003: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Fill -//line mysql_sql.y:7081 +//line mysql_sql.y:7084 { yyLOCAL = &tree.Fill{ Mode: yyDollar[3].fillModeUnion(), @@ -22604,7 +22665,7 @@ yydefault: case 1004: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.Fill -//line mysql_sql.y:7087 +//line mysql_sql.y:7090 { yyLOCAL = &tree.Fill{ Mode: tree.FillValue, @@ -22615,7 +22676,7 @@ yydefault: case 1005: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FillMode -//line mysql_sql.y:7096 +//line mysql_sql.y:7099 { yyLOCAL = tree.FillPrev } @@ -22623,7 +22684,7 @@ yydefault: case 1006: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FillMode -//line mysql_sql.y:7100 +//line mysql_sql.y:7103 { yyLOCAL = tree.FillNext } @@ -22631,7 +22692,7 @@ yydefault: case 1007: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FillMode -//line mysql_sql.y:7104 +//line mysql_sql.y:7107 { yyLOCAL = tree.FillNone } @@ -22639,7 +22700,7 @@ yydefault: case 1008: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FillMode -//line mysql_sql.y:7108 +//line mysql_sql.y:7111 { yyLOCAL = tree.FillNull } @@ -22647,7 +22708,7 @@ yydefault: case 1009: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FillMode -//line mysql_sql.y:7112 +//line mysql_sql.y:7115 { yyLOCAL = tree.FillLinear } @@ -22655,7 +22716,7 @@ yydefault: case 1010: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.With -//line mysql_sql.y:7118 +//line mysql_sql.y:7121 { yyLOCAL = &tree.With{ IsRecursive: false, @@ -22666,7 +22727,7 @@ yydefault: case 1011: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.With -//line mysql_sql.y:7125 +//line mysql_sql.y:7128 { yyLOCAL = &tree.With{ IsRecursive: true, @@ -22677,7 +22738,7 @@ yydefault: case 1012: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.CTE -//line mysql_sql.y:7134 +//line mysql_sql.y:7137 { yyLOCAL = []*tree.CTE{yyDollar[1].cteUnion()} } @@ -22685,7 +22746,7 @@ yydefault: case 1013: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.CTE -//line mysql_sql.y:7138 +//line mysql_sql.y:7141 { yyLOCAL = append(yyDollar[1].cteListUnion(), yyDollar[3].cteUnion()) } @@ -22693,7 +22754,7 @@ yydefault: case 1014: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.CTE -//line mysql_sql.y:7144 +//line mysql_sql.y:7147 { yyLOCAL = &tree.CTE{ Name: &tree.AliasClause{Alias: tree.Identifier(yyDollar[1].cstrUnion().Compare()), Cols: yyDollar[2].identifierListUnion()}, @@ -22704,7 +22765,7 @@ yydefault: case 1015: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:7152 +//line mysql_sql.y:7155 { yyLOCAL = nil } @@ -22712,7 +22773,7 @@ yydefault: case 1016: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:7156 +//line mysql_sql.y:7159 { yyLOCAL = yyDollar[2].identifierListUnion() } @@ -22720,7 +22781,7 @@ yydefault: case 1017: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Limit -//line mysql_sql.y:7161 +//line mysql_sql.y:7164 { yyLOCAL = nil } @@ -22728,7 +22789,7 @@ yydefault: case 1018: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Limit -//line mysql_sql.y:7165 +//line mysql_sql.y:7168 { yyLOCAL = yyDollar[1].limitUnion() } @@ -22736,7 +22797,7 @@ yydefault: case 1019: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Limit -//line mysql_sql.y:7170 +//line mysql_sql.y:7173 { yyLOCAL = nil } @@ -22744,7 +22805,7 @@ yydefault: case 1020: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Limit -//line mysql_sql.y:7174 +//line mysql_sql.y:7177 { yyLOCAL = yyDollar[1].limitUnion() } @@ -22752,7 +22813,7 @@ yydefault: case 1021: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Limit -//line mysql_sql.y:7178 +//line mysql_sql.y:7181 { yyLOCAL = yyDollar[1].limitUnion() } @@ -22760,7 +22821,7 @@ yydefault: case 1022: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.Limit -//line mysql_sql.y:7184 +//line mysql_sql.y:7187 { yyLOCAL = &tree.Limit{Count: yyDollar[2].exprUnion()} } @@ -22768,7 +22829,7 @@ yydefault: case 1023: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Limit -//line mysql_sql.y:7188 +//line mysql_sql.y:7191 { yyLOCAL = &tree.Limit{Offset: yyDollar[2].exprUnion(), Count: yyDollar[4].exprUnion()} } @@ -22776,7 +22837,7 @@ yydefault: case 1024: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Limit -//line mysql_sql.y:7192 +//line mysql_sql.y:7195 { yyLOCAL = &tree.Limit{Offset: yyDollar[4].exprUnion(), Count: yyDollar[2].exprUnion()} } @@ -22784,7 +22845,7 @@ yydefault: case 1025: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.Limit -//line mysql_sql.y:7198 +//line mysql_sql.y:7201 { yyLOCAL = &tree.Limit{Offset: yyDollar[2].exprUnion()} } @@ -22792,7 +22853,7 @@ yydefault: case 1026: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.RankOption -//line mysql_sql.y:7203 +//line mysql_sql.y:7206 { yyLOCAL = nil } @@ -22800,7 +22861,7 @@ yydefault: case 1027: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.RankOption -//line mysql_sql.y:7207 +//line mysql_sql.y:7210 { // Parse option strings to extract key=value pairs into a map optionMap := make(map[string]string) @@ -22838,7 +22899,7 @@ yydefault: case 1028: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.OrderBy -//line mysql_sql.y:7242 +//line mysql_sql.y:7245 { yyLOCAL = nil } @@ -22846,7 +22907,7 @@ yydefault: case 1029: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.OrderBy -//line mysql_sql.y:7246 +//line mysql_sql.y:7249 { yyLOCAL = yyDollar[1].orderByUnion() } @@ -22854,7 +22915,7 @@ yydefault: case 1030: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.OrderBy -//line mysql_sql.y:7251 +//line mysql_sql.y:7254 { yyLOCAL = nil } @@ -22862,7 +22923,7 @@ yydefault: case 1031: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.OrderBy -//line mysql_sql.y:7255 +//line mysql_sql.y:7258 { yyLOCAL = yyDollar[4].orderByUnion() } @@ -22870,7 +22931,7 @@ yydefault: case 1032: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.OrderBy -//line mysql_sql.y:7261 +//line mysql_sql.y:7264 { yyLOCAL = yyDollar[3].orderByUnion() } @@ -22878,7 +22939,7 @@ yydefault: case 1033: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.OrderBy -//line mysql_sql.y:7267 +//line mysql_sql.y:7270 { yyLOCAL = tree.OrderBy{yyDollar[1].orderUnion()} } @@ -22886,7 +22947,7 @@ yydefault: case 1034: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.OrderBy -//line mysql_sql.y:7271 +//line mysql_sql.y:7274 { yyLOCAL = append(yyDollar[1].orderByUnion(), yyDollar[3].orderUnion()) } @@ -22894,7 +22955,7 @@ yydefault: case 1035: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Order -//line mysql_sql.y:7277 +//line mysql_sql.y:7280 { yyLOCAL = &tree.Order{Expr: yyDollar[1].exprUnion(), Direction: yyDollar[2].directionUnion(), NullsPosition: yyDollar[3].nullsPositionUnion()} } @@ -22902,7 +22963,7 @@ yydefault: case 1036: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Direction -//line mysql_sql.y:7282 +//line mysql_sql.y:7285 { yyLOCAL = tree.DefaultDirection } @@ -22910,7 +22971,7 @@ yydefault: case 1037: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Direction -//line mysql_sql.y:7286 +//line mysql_sql.y:7289 { yyLOCAL = tree.Ascending } @@ -22918,7 +22979,7 @@ yydefault: case 1038: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Direction -//line mysql_sql.y:7290 +//line mysql_sql.y:7293 { yyLOCAL = tree.Descending } @@ -22926,21 +22987,21 @@ yydefault: case 1039: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.NullsPosition -//line mysql_sql.y:7295 +//line mysql_sql.y:7298 { yyLOCAL = tree.DefaultNullsPosition } yyVAL.union = yyLOCAL case 1040: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:7299 +//line mysql_sql.y:7302 { yylex.Error("NULLS FIRST is not supported in MySQL syntax") return 1 } case 1041: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:7303 +//line mysql_sql.y:7306 { yylex.Error("NULLS LAST is not supported in MySQL syntax") return 1 @@ -22948,7 +23009,7 @@ yydefault: case 1042: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.SelectLockInfo -//line mysql_sql.y:7308 +//line mysql_sql.y:7311 { yyLOCAL = nil } @@ -22956,7 +23017,7 @@ yydefault: case 1043: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.SelectLockInfo -//line mysql_sql.y:7312 +//line mysql_sql.y:7315 { yyLOCAL = &tree.SelectLockInfo{ LockType: tree.SelectLockForUpdate, @@ -22966,7 +23027,7 @@ yydefault: case 1044: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.SelectLockInfo -//line mysql_sql.y:7318 +//line mysql_sql.y:7321 { yyLOCAL = &tree.SelectLockInfo{ LockType: tree.SelectLockForShare, @@ -22976,7 +23037,7 @@ yydefault: case 1045: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.SelectLockInfo -//line mysql_sql.y:7324 +//line mysql_sql.y:7327 { yyLOCAL = &tree.SelectLockInfo{ LockType: tree.SelectLockForShare, @@ -22986,7 +23047,7 @@ yydefault: case 1046: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7332 +//line mysql_sql.y:7335 { yyLOCAL = &tree.ParenSelect{Select: yyDollar[2].selectUnion()} } @@ -22994,7 +23055,7 @@ yydefault: case 1047: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7336 +//line mysql_sql.y:7339 { yyLOCAL = &tree.ParenSelect{Select: &tree.Select{Select: yyDollar[2].selectStatementUnion()}} } @@ -23002,7 +23063,7 @@ yydefault: case 1048: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7340 +//line mysql_sql.y:7343 { yyLOCAL = yyDollar[1].selectStatementUnion() } @@ -23010,7 +23071,7 @@ yydefault: case 1049: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7344 +//line mysql_sql.y:7347 { yyLOCAL = yyDollar[1].selectStatementUnion() } @@ -23018,7 +23079,7 @@ yydefault: case 1050: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7349 +//line mysql_sql.y:7352 { yyLOCAL = yyDollar[1].selectStatementUnion() } @@ -23026,7 +23087,7 @@ yydefault: case 1051: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7353 +//line mysql_sql.y:7356 { yyLOCAL = &tree.UnionClause{ Type: yyDollar[2].unionTypeRecordUnion().Type, @@ -23040,7 +23101,7 @@ yydefault: case 1052: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7363 +//line mysql_sql.y:7366 { yyLOCAL = &tree.UnionClause{ Type: yyDollar[2].unionTypeRecordUnion().Type, @@ -23054,7 +23115,7 @@ yydefault: case 1053: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7373 +//line mysql_sql.y:7376 { yyLOCAL = &tree.UnionClause{ Type: yyDollar[2].unionTypeRecordUnion().Type, @@ -23068,7 +23129,7 @@ yydefault: case 1054: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7383 +//line mysql_sql.y:7386 { yyLOCAL = &tree.UnionClause{ Type: yyDollar[2].unionTypeRecordUnion().Type, @@ -23082,7 +23143,7 @@ yydefault: case 1055: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7393 +//line mysql_sql.y:7396 { yyLOCAL = &tree.UnionClause{Type: yyDollar[2].unionTypeRecordUnion().Type, Left: yyDollar[1].selectStatementUnion(), Right: yyDollar[3].selectStatementUnion(), All: yyDollar[2].unionTypeRecordUnion().All, Distinct: yyDollar[2].unionTypeRecordUnion().Distinct} } @@ -23090,7 +23151,7 @@ yydefault: case 1056: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7397 +//line mysql_sql.y:7400 { yyLOCAL = &tree.UnionClause{Type: yyDollar[2].unionTypeRecordUnion().Type, Left: yyDollar[1].selectStatementUnion(), Right: yyDollar[3].selectStatementUnion(), All: yyDollar[2].unionTypeRecordUnion().All, Distinct: yyDollar[2].unionTypeRecordUnion().Distinct} } @@ -23098,7 +23159,7 @@ yydefault: case 1057: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7401 +//line mysql_sql.y:7404 { yyLOCAL = &tree.UnionClause{Type: yyDollar[2].unionTypeRecordUnion().Type, Left: yyDollar[1].selectStatementUnion(), Right: yyDollar[3].selectStatementUnion(), All: yyDollar[2].unionTypeRecordUnion().All, Distinct: yyDollar[2].unionTypeRecordUnion().Distinct} } @@ -23106,7 +23167,7 @@ yydefault: case 1058: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7405 +//line mysql_sql.y:7408 { yyLOCAL = &tree.UnionClause{Type: yyDollar[2].unionTypeRecordUnion().Type, Left: yyDollar[1].selectStatementUnion(), Right: yyDollar[3].selectStatementUnion(), All: yyDollar[2].unionTypeRecordUnion().All, Distinct: yyDollar[2].unionTypeRecordUnion().Distinct} } @@ -23114,7 +23175,7 @@ yydefault: case 1059: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7413 +//line mysql_sql.y:7416 { yyLOCAL = &tree.ParenSelect{Select: tree.NewSelect(yyDollar[2].selectStatementUnion(), yyDollar[3].orderByUnion(), yyDollar[4].limitUnion())} } @@ -23122,7 +23183,7 @@ yydefault: case 1060: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7419 +//line mysql_sql.y:7422 { yyLOCAL = yyDollar[1].selectStatementUnion() } @@ -23130,7 +23191,7 @@ yydefault: case 1061: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7423 +//line mysql_sql.y:7426 { yyLOCAL = &tree.UnionClause{Type: yyDollar[2].unionTypeRecordUnion().Type, Left: yyDollar[1].selectStatementUnion(), Right: yyDollar[3].selectStatementUnion(), All: yyDollar[2].unionTypeRecordUnion().All, Distinct: yyDollar[2].unionTypeRecordUnion().Distinct} } @@ -23138,7 +23199,7 @@ yydefault: case 1062: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7429 +//line mysql_sql.y:7432 { yyLOCAL = makeSelectStarFromTable(yyDollar[2].tableNameUnion()) } @@ -23146,7 +23207,7 @@ yydefault: case 1063: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7434 +//line mysql_sql.y:7437 { yyLOCAL = yyDollar[1].selectStatementUnion() } @@ -23154,7 +23215,7 @@ yydefault: case 1064: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7438 +//line mysql_sql.y:7441 { yyLOCAL = yyDollar[1].selectStatementUnion() } @@ -23162,7 +23223,7 @@ yydefault: case 1065: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7442 +//line mysql_sql.y:7445 { yyLOCAL = yyDollar[1].selectStatementUnion() } @@ -23170,7 +23231,7 @@ yydefault: case 1066: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7446 +//line mysql_sql.y:7449 { yyLOCAL = &tree.ValuesClause{Rows: yyDollar[2].rowsExprsUnion(), RowWord: true} } @@ -23178,7 +23239,7 @@ yydefault: case 1067: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7452 +//line mysql_sql.y:7455 { yyLOCAL = &tree.ParenSelect{Select: tree.NewSelect(yyDollar[2].selectStatementUnion(), yyDollar[3].orderByUnion(), yyDollar[4].limitUnion())} } @@ -23186,7 +23247,7 @@ yydefault: case 1068: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7458 +//line mysql_sql.y:7461 { yyLOCAL = yyDollar[1].selectStatementUnion() } @@ -23194,7 +23255,7 @@ yydefault: case 1069: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7462 +//line mysql_sql.y:7465 { yyLOCAL = &tree.UnionClause{Type: yyDollar[2].unionTypeRecordUnion().Type, Left: yyDollar[1].selectStatementUnion(), Right: yyDollar[3].selectStatementUnion(), All: yyDollar[2].unionTypeRecordUnion().All, Distinct: yyDollar[2].unionTypeRecordUnion().Distinct} } @@ -23202,7 +23263,7 @@ yydefault: case 1070: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7468 +//line mysql_sql.y:7471 { yyLOCAL = &tree.ValuesClause{Rows: yyDollar[2].rowsExprsUnion(), RowWord: true} } @@ -23210,7 +23271,7 @@ yydefault: case 1071: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7474 +//line mysql_sql.y:7477 { yyLOCAL = yyDollar[1].selectStatementUnion() } @@ -23218,7 +23279,7 @@ yydefault: case 1072: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7478 +//line mysql_sql.y:7481 { yyLOCAL = yyDollar[1].selectStatementUnion() } @@ -23226,7 +23287,7 @@ yydefault: case 1073: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7482 +//line mysql_sql.y:7485 { yyLOCAL = yyDollar[1].selectStatementUnion() } @@ -23234,7 +23295,7 @@ yydefault: case 1074: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7486 +//line mysql_sql.y:7489 { yyLOCAL = yyDollar[1].selectStatementUnion() } @@ -23242,7 +23303,7 @@ yydefault: case 1075: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:7492 +//line mysql_sql.y:7495 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.UNION, @@ -23254,7 +23315,7 @@ yydefault: case 1076: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:7500 +//line mysql_sql.y:7503 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.UNION, @@ -23266,7 +23327,7 @@ yydefault: case 1077: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:7508 +//line mysql_sql.y:7511 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.UNION, @@ -23278,7 +23339,7 @@ yydefault: case 1078: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:7517 +//line mysql_sql.y:7520 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.EXCEPT, @@ -23290,7 +23351,7 @@ yydefault: case 1079: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:7525 +//line mysql_sql.y:7528 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.EXCEPT, @@ -23302,7 +23363,7 @@ yydefault: case 1080: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:7533 +//line mysql_sql.y:7536 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.EXCEPT, @@ -23314,7 +23375,7 @@ yydefault: case 1081: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:7541 +//line mysql_sql.y:7544 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.INTERSECT, @@ -23326,7 +23387,7 @@ yydefault: case 1082: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:7549 +//line mysql_sql.y:7552 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.INTERSECT, @@ -23338,7 +23399,7 @@ yydefault: case 1083: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:7557 +//line mysql_sql.y:7560 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.INTERSECT, @@ -23350,7 +23411,7 @@ yydefault: case 1084: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:7565 +//line mysql_sql.y:7568 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.UT_MINUS, @@ -23362,7 +23423,7 @@ yydefault: case 1085: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:7573 +//line mysql_sql.y:7576 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.UT_MINUS, @@ -23374,7 +23435,7 @@ yydefault: case 1086: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UnionTypeRecord -//line mysql_sql.y:7581 +//line mysql_sql.y:7584 { yyLOCAL = &tree.UnionTypeRecord{ Type: tree.UT_MINUS, @@ -23386,7 +23447,7 @@ yydefault: case 1087: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.SelectStatement -//line mysql_sql.y:7591 +//line mysql_sql.y:7594 { yyLOCAL = &tree.SelectClause{ Distinct: tree.QuerySpecOptionDistinct&yyDollar[2].selectOptionsUnion() != 0, @@ -23405,7 +23466,7 @@ yydefault: case 1088: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:7608 +//line mysql_sql.y:7611 { yyLOCAL = tree.QuerySpecOptionNone } @@ -23413,7 +23474,7 @@ yydefault: case 1089: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:7612 +//line mysql_sql.y:7615 { yyLOCAL = yyDollar[1].selectOptionsUnion() } @@ -23421,7 +23482,7 @@ yydefault: case 1090: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:7618 +//line mysql_sql.y:7621 { yyLOCAL = yyDollar[1].selectOptionUnion() } @@ -23429,7 +23490,7 @@ yydefault: case 1091: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:7622 +//line mysql_sql.y:7625 { yyLOCAL = yyDollar[1].selectOptionsUnion() | yyDollar[2].selectOptionUnion() } @@ -23437,7 +23498,7 @@ yydefault: case 1092: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:7628 +//line mysql_sql.y:7631 { yyLOCAL = tree.QuerySpecOptionSqlSmallResult } @@ -23445,7 +23506,7 @@ yydefault: case 1093: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:7632 +//line mysql_sql.y:7635 { yyLOCAL = tree.QuerySpecOptionSqlBigResult } @@ -23453,7 +23514,7 @@ yydefault: case 1094: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:7636 +//line mysql_sql.y:7639 { yyLOCAL = tree.QuerySpecOptionSqlBufferResult } @@ -23461,7 +23522,7 @@ yydefault: case 1095: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:7640 +//line mysql_sql.y:7643 { yyLOCAL = tree.QuerySpecOptionStraightJoin } @@ -23469,7 +23530,7 @@ yydefault: case 1096: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:7644 +//line mysql_sql.y:7647 { yyLOCAL = tree.QuerySpecOptionHighPriority } @@ -23477,7 +23538,7 @@ yydefault: case 1097: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:7648 +//line mysql_sql.y:7651 { yyLOCAL = tree.QuerySpecOptionSqlCalcFoundRows } @@ -23485,7 +23546,7 @@ yydefault: case 1098: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:7652 +//line mysql_sql.y:7655 { yyLOCAL = tree.QuerySpecOptionSqlNoCache } @@ -23493,7 +23554,7 @@ yydefault: case 1099: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:7656 +//line mysql_sql.y:7659 { yyLOCAL = tree.QuerySpecOptionAll } @@ -23501,7 +23562,7 @@ yydefault: case 1100: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:7660 +//line mysql_sql.y:7663 { yyLOCAL = tree.QuerySpecOptionDistinct } @@ -23509,7 +23570,7 @@ yydefault: case 1101: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL uint64 -//line mysql_sql.y:7664 +//line mysql_sql.y:7667 { yyLOCAL = tree.QuerySpecOptionDistinctRow } @@ -23517,7 +23578,7 @@ yydefault: case 1102: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Where -//line mysql_sql.y:7686 +//line mysql_sql.y:7689 { yyLOCAL = nil } @@ -23525,7 +23586,7 @@ yydefault: case 1103: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.Where -//line mysql_sql.y:7690 +//line mysql_sql.y:7693 { yyLOCAL = &tree.Where{Type: tree.AstHaving, Expr: yyDollar[2].exprUnion()} } @@ -23533,7 +23594,7 @@ yydefault: case 1104: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.GroupByClause -//line mysql_sql.y:7695 +//line mysql_sql.y:7698 { yyLOCAL = nil } @@ -23541,7 +23602,7 @@ yydefault: case 1105: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.GroupByClause -//line mysql_sql.y:7699 +//line mysql_sql.y:7702 { exprsList := []tree.Exprs{yyDollar[3].exprsUnion()} yyLOCAL = &tree.GroupByClause{ @@ -23555,7 +23616,7 @@ yydefault: case 1106: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *tree.GroupByClause -//line mysql_sql.y:7709 +//line mysql_sql.y:7712 { yyLOCAL = &tree.GroupByClause{ GroupByExprsList: yyDollar[6].rowsExprsUnion(), @@ -23569,7 +23630,7 @@ yydefault: case 1107: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.GroupByClause -//line mysql_sql.y:7719 +//line mysql_sql.y:7722 { yyLOCAL = &tree.GroupByClause{ GroupByExprsList: []tree.Exprs{yyDollar[5].exprsUnion()}, @@ -23582,7 +23643,7 @@ yydefault: case 1108: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.GroupByClause -//line mysql_sql.y:7728 +//line mysql_sql.y:7731 { yyLOCAL = &tree.GroupByClause{ GroupByExprsList: []tree.Exprs{yyDollar[5].exprsUnion()}, @@ -23595,7 +23656,7 @@ yydefault: case 1109: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.Exprs -//line mysql_sql.y:7739 +//line mysql_sql.y:7742 { yyLOCAL = []tree.Exprs{yyDollar[2].exprsUnion()} } @@ -23603,7 +23664,7 @@ yydefault: case 1110: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL []tree.Exprs -//line mysql_sql.y:7743 +//line mysql_sql.y:7746 { yyLOCAL = append(yyDollar[1].rowsExprsUnion(), yyDollar[4].exprsUnion()) } @@ -23611,7 +23672,7 @@ yydefault: case 1111: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:7749 +//line mysql_sql.y:7752 { yyLOCAL = false } @@ -23619,7 +23680,7 @@ yydefault: case 1112: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:7753 +//line mysql_sql.y:7756 { yyLOCAL = true } @@ -23627,7 +23688,7 @@ yydefault: case 1113: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.Where -//line mysql_sql.y:7758 +//line mysql_sql.y:7761 { yyLOCAL = nil } @@ -23635,7 +23696,7 @@ yydefault: case 1114: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.Where -//line mysql_sql.y:7762 +//line mysql_sql.y:7765 { yyLOCAL = &tree.Where{Type: tree.AstWhere, Expr: yyDollar[2].exprUnion()} } @@ -23643,7 +23704,7 @@ yydefault: case 1115: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.SelectExprs -//line mysql_sql.y:7768 +//line mysql_sql.y:7771 { yyLOCAL = tree.SelectExprs{yyDollar[1].selectExprUnion()} } @@ -23651,7 +23712,7 @@ yydefault: case 1116: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectExprs -//line mysql_sql.y:7772 +//line mysql_sql.y:7775 { yyLOCAL = append(yyDollar[1].selectExprsUnion(), yyDollar[3].selectExprUnion()) } @@ -23659,7 +23720,7 @@ yydefault: case 1117: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.SelectExpr -//line mysql_sql.y:7778 +//line mysql_sql.y:7781 { yyLOCAL = tree.SelectExpr{Expr: tree.StarExpr()} } @@ -23667,7 +23728,7 @@ yydefault: case 1118: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.SelectExpr -//line mysql_sql.y:7782 +//line mysql_sql.y:7785 { yyLOCAL = tree.SelectExpr{Expr: yyDollar[1].exprUnion(), As: yyDollar[2].cstrUnion()} } @@ -23675,7 +23736,7 @@ yydefault: case 1119: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.SelectExpr -//line mysql_sql.y:7786 +//line mysql_sql.y:7789 { yyLOCAL = tree.SelectExpr{Expr: tree.NewUnresolvedNameWithStar(yyDollar[1].cstrUnion())} } @@ -23683,7 +23744,7 @@ yydefault: case 1120: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.SelectExpr -//line mysql_sql.y:7790 +//line mysql_sql.y:7793 { yyLOCAL = tree.SelectExpr{Expr: tree.NewUnresolvedNameWithStar(yyDollar[1].cstrUnion(), yyDollar[3].cstrUnion())} } @@ -23691,7 +23752,7 @@ yydefault: case 1121: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.From -//line mysql_sql.y:7795 +//line mysql_sql.y:7798 { prefix := tree.ObjectNamePrefix{ExplicitSchema: false} tn := tree.NewTableName(tree.Identifier(""), prefix, nil) @@ -23703,7 +23764,7 @@ yydefault: case 1122: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.From -//line mysql_sql.y:7803 +//line mysql_sql.y:7806 { yyLOCAL = yyDollar[1].fromUnion() } @@ -23711,7 +23772,7 @@ yydefault: case 1123: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.From -//line mysql_sql.y:7809 +//line mysql_sql.y:7812 { yyLOCAL = &tree.From{ Tables: tree.TableExprs{yyDollar[2].tableExprUnion()}, @@ -23721,7 +23782,7 @@ yydefault: case 1124: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:7817 +//line mysql_sql.y:7820 { if t, ok := yyDollar[1].tableExprUnion().(*tree.JoinTableExpr); ok { yyLOCAL = t @@ -23735,7 +23796,7 @@ yydefault: case 1125: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:7827 +//line mysql_sql.y:7830 { yyLOCAL = &tree.JoinTableExpr{Left: yyDollar[1].tableExprUnion(), Right: yyDollar[3].tableExprUnion(), JoinType: tree.JOIN_TYPE_CROSS} } @@ -23743,7 +23804,7 @@ yydefault: case 1127: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:7834 +//line mysql_sql.y:7837 { if !strings.EqualFold(yyDollar[2].str, "OJ") { yylex.Error("expected OJ in table reference escape") @@ -23755,7 +23816,7 @@ yydefault: case 1129: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:7845 +//line mysql_sql.y:7848 { yyLOCAL = yyDollar[1].joinTableExprUnion() } @@ -23763,7 +23824,7 @@ yydefault: case 1130: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:7849 +//line mysql_sql.y:7852 { yyLOCAL = yyDollar[1].applyTableExprUnion() } @@ -23771,7 +23832,7 @@ yydefault: case 1131: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.JoinTableExpr -//line mysql_sql.y:7855 +//line mysql_sql.y:7858 { if strings.Contains(yyDollar[2].str, ":") { ss := strings.SplitN(yyDollar[2].str, ":", 2) @@ -23795,7 +23856,7 @@ yydefault: case 1132: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.JoinTableExpr -//line mysql_sql.y:7875 +//line mysql_sql.y:7878 { yyLOCAL = &tree.JoinTableExpr{ Left: yyDollar[1].tableExprUnion(), @@ -23808,7 +23869,7 @@ yydefault: case 1133: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.JoinTableExpr -//line mysql_sql.y:7884 +//line mysql_sql.y:7887 { if yyDollar[4].joinCondUnion() == nil { yylex.Error("outer join requires ON/USING clause") @@ -23825,7 +23886,7 @@ yydefault: case 1134: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.JoinTableExpr -//line mysql_sql.y:7897 +//line mysql_sql.y:7900 { yyLOCAL = &tree.JoinTableExpr{ Left: yyDollar[1].tableExprUnion(), @@ -23837,7 +23898,7 @@ yydefault: case 1135: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.JoinTableExpr -//line mysql_sql.y:7905 +//line mysql_sql.y:7908 { yyLOCAL = &tree.JoinTableExpr{ Left: yyDollar[1].tableExprUnion(), @@ -23850,7 +23911,7 @@ yydefault: case 1136: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.JoinTableExpr -//line mysql_sql.y:7914 +//line mysql_sql.y:7917 { if !hasAsofLeftFactorAlias(yyDollar[1].tableExprUnion()) { yylex.Error("native ASOF JOIN requires an aliased left table factor") @@ -23868,7 +23929,7 @@ yydefault: case 1137: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ApplyTableExpr -//line mysql_sql.y:7930 +//line mysql_sql.y:7933 { yyLOCAL = &tree.ApplyTableExpr{ Left: yyDollar[1].tableExprUnion(), @@ -23879,25 +23940,25 @@ yydefault: yyVAL.union = yyLOCAL case 1138: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:7940 +//line mysql_sql.y:7943 { yyVAL.str = tree.APPLY_TYPE_CROSS } case 1139: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:7944 +//line mysql_sql.y:7947 { yyVAL.str = tree.APPLY_TYPE_OUTER } case 1140: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:7950 +//line mysql_sql.y:7953 { yyVAL.str = tree.JOIN_TYPE_NATURAL } case 1141: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:7954 +//line mysql_sql.y:7957 { switch yyDollar[2].str { case tree.JOIN_TYPE_LEFT: @@ -23910,68 +23971,68 @@ yydefault: } case 1142: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:7967 +//line mysql_sql.y:7970 { yyVAL.str = tree.JOIN_TYPE_LEFT } case 1143: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:7971 +//line mysql_sql.y:7974 { yyVAL.str = tree.JOIN_TYPE_LEFT } case 1144: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:7975 +//line mysql_sql.y:7978 { yyVAL.str = tree.JOIN_TYPE_RIGHT } case 1145: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:7979 +//line mysql_sql.y:7982 { yyVAL.str = tree.JOIN_TYPE_RIGHT } case 1146: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:7983 +//line mysql_sql.y:7986 { yyVAL.str = tree.JOIN_TYPE_FULL } case 1147: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:7987 +//line mysql_sql.y:7990 { yyVAL.str = tree.JOIN_TYPE_FULL } case 1148: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:7993 +//line mysql_sql.y:7996 { yyVAL.str = tree.JOIN_TYPE_DEDUP } case 1149: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:7999 +//line mysql_sql.y:8002 { yyVAL.str = tree.JOIN_TYPE_ASOF } case 1150: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:8003 +//line mysql_sql.y:8006 { yyVAL.str = tree.JOIN_TYPE_ASOF_LEFT } case 1151: yyDollar = yyS[yypt-4 : yypt+1] -//line mysql_sql.y:8007 +//line mysql_sql.y:8010 { yyVAL.str = tree.JOIN_TYPE_ASOF_LEFT } case 1152: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:8012 +//line mysql_sql.y:8015 { yyLOCAL = nil } @@ -23979,7 +24040,7 @@ yydefault: case 1153: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:8016 +//line mysql_sql.y:8019 { yyLOCAL = yyDollar[2].exprUnion() } @@ -23987,7 +24048,7 @@ yydefault: case 1154: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8022 +//line mysql_sql.y:8025 { stmt := &tree.ValuesStatement{ Rows: yyDollar[2].rowsExprsUnion(), @@ -24004,7 +24065,7 @@ yydefault: case 1155: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.Exprs -//line mysql_sql.y:8037 +//line mysql_sql.y:8040 { yyLOCAL = []tree.Exprs{yyDollar[1].exprsUnion()} } @@ -24012,7 +24073,7 @@ yydefault: case 1156: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.Exprs -//line mysql_sql.y:8041 +//line mysql_sql.y:8044 { yyLOCAL = append(yyDollar[1].rowsExprsUnion(), yyDollar[3].exprsUnion()) } @@ -24020,57 +24081,57 @@ yydefault: case 1157: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:8047 +//line mysql_sql.y:8050 { yyLOCAL = yyDollar[3].exprsUnion() } yyVAL.union = yyLOCAL case 1158: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:8053 +//line mysql_sql.y:8056 { yyVAL.str = yyDollar[1].str } case 1159: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:8059 +//line mysql_sql.y:8062 { yyVAL.str = yyDollar[2].str } case 1160: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:8065 +//line mysql_sql.y:8068 { yyVAL.str = tree.JOIN_TYPE_STRAIGHT } case 1161: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:8071 +//line mysql_sql.y:8074 { yyVAL.str = tree.JOIN_TYPE_INNER } case 1162: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:8075 +//line mysql_sql.y:8078 { yyVAL.str = tree.JOIN_TYPE_INNER } case 1163: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:8079 +//line mysql_sql.y:8082 { yyVAL.str = tree.JOIN_TYPE_CROSS } case 1164: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:8083 +//line mysql_sql.y:8086 { yyVAL.str = tree.JOIN_TYPE_CENTROIDX + ":" + yyDollar[2].str } case 1165: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.JoinCond -//line mysql_sql.y:8089 +//line mysql_sql.y:8092 { yyLOCAL = nil } @@ -24078,7 +24139,7 @@ yydefault: case 1166: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.JoinCond -//line mysql_sql.y:8093 +//line mysql_sql.y:8096 { yyLOCAL = yyDollar[1].joinCondUnion() } @@ -24086,7 +24147,7 @@ yydefault: case 1167: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.JoinCond -//line mysql_sql.y:8099 +//line mysql_sql.y:8102 { yyLOCAL = &tree.OnJoinCond{Expr: yyDollar[2].exprUnion()} } @@ -24094,7 +24155,7 @@ yydefault: case 1168: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.JoinCond -//line mysql_sql.y:8103 +//line mysql_sql.y:8106 { yyLOCAL = &tree.UsingJoinCond{Cols: yyDollar[3].identifierListUnion()} } @@ -24102,7 +24163,7 @@ yydefault: case 1169: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:8109 +//line mysql_sql.y:8112 { yyLOCAL = tree.IdentifierList{tree.Identifier(yyDollar[1].cstrUnion().Compare())} } @@ -24110,7 +24171,7 @@ yydefault: case 1170: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:8113 +//line mysql_sql.y:8116 { yyLOCAL = append(yyDollar[1].identifierListUnion(), tree.Identifier(yyDollar[3].cstrUnion().Compare())) } @@ -24118,7 +24179,7 @@ yydefault: case 1171: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:8119 +//line mysql_sql.y:8122 { yyLOCAL = yyDollar[1].aliasedTableExprUnion() } @@ -24126,7 +24187,7 @@ yydefault: case 1172: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:8123 +//line mysql_sql.y:8126 { yyLOCAL = &tree.AliasedTableExpr{ Expr: yyDollar[1].parenTableExprUnion(), @@ -24140,7 +24201,7 @@ yydefault: case 1173: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:8133 +//line mysql_sql.y:8136 { if yyDollar[2].str != "" { yyLOCAL = &tree.AliasedTableExpr{ @@ -24157,7 +24218,7 @@ yydefault: case 1174: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:8146 +//line mysql_sql.y:8149 { yyLOCAL = yyDollar[2].tableExprUnion() } @@ -24165,7 +24226,7 @@ yydefault: case 1175: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.ParenTableExpr -//line mysql_sql.y:8154 +//line mysql_sql.y:8157 { yyLOCAL = &tree.ParenTableExpr{Expr: yyDollar[1].selectStatementUnion().(*tree.ParenSelect).Select} } @@ -24173,7 +24234,7 @@ yydefault: case 1176: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.TableExpr -//line mysql_sql.y:8160 +//line mysql_sql.y:8163 { name := tree.NewUnresolvedName(yyDollar[1].cstrUnion()) yyLOCAL = &tree.TableFunction{ @@ -24189,7 +24250,7 @@ yydefault: case 1177: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.AliasedTableExpr -//line mysql_sql.y:8174 +//line mysql_sql.y:8177 { yyLOCAL = &tree.AliasedTableExpr{ Expr: yyDollar[1].tableNameUnion(), @@ -24203,7 +24264,7 @@ yydefault: case 1178: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*tree.IndexHint -//line mysql_sql.y:8185 +//line mysql_sql.y:8188 { yyLOCAL = nil } @@ -24211,7 +24272,7 @@ yydefault: case 1180: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.IndexHint -//line mysql_sql.y:8192 +//line mysql_sql.y:8195 { yyLOCAL = []*tree.IndexHint{yyDollar[1].indexHintUnion()} } @@ -24219,7 +24280,7 @@ yydefault: case 1181: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*tree.IndexHint -//line mysql_sql.y:8196 +//line mysql_sql.y:8199 { yyLOCAL = append(yyDollar[1].indexHintListUnion(), yyDollar[2].indexHintUnion()) } @@ -24227,7 +24288,7 @@ yydefault: case 1182: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.IndexHint -//line mysql_sql.y:8202 +//line mysql_sql.y:8205 { yyLOCAL = &tree.IndexHint{ IndexNames: yyDollar[4].strsUnion(), @@ -24239,7 +24300,7 @@ yydefault: case 1183: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexHintType -//line mysql_sql.y:8212 +//line mysql_sql.y:8215 { yyLOCAL = tree.HintUse } @@ -24247,7 +24308,7 @@ yydefault: case 1184: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexHintType -//line mysql_sql.y:8216 +//line mysql_sql.y:8219 { yyLOCAL = tree.HintIgnore } @@ -24255,7 +24316,7 @@ yydefault: case 1185: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexHintType -//line mysql_sql.y:8220 +//line mysql_sql.y:8223 { yyLOCAL = tree.HintForce } @@ -24263,7 +24324,7 @@ yydefault: case 1186: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.IndexHintScope -//line mysql_sql.y:8225 +//line mysql_sql.y:8228 { yyLOCAL = tree.HintForScan } @@ -24271,7 +24332,7 @@ yydefault: case 1187: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexHintScope -//line mysql_sql.y:8229 +//line mysql_sql.y:8232 { yyLOCAL = tree.HintForJoin } @@ -24279,7 +24340,7 @@ yydefault: case 1188: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IndexHintScope -//line mysql_sql.y:8233 +//line mysql_sql.y:8236 { yyLOCAL = tree.HintForOrderBy } @@ -24287,7 +24348,7 @@ yydefault: case 1189: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IndexHintScope -//line mysql_sql.y:8237 +//line mysql_sql.y:8240 { yyLOCAL = tree.HintForGroupBy } @@ -24295,7 +24356,7 @@ yydefault: case 1190: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:8242 +//line mysql_sql.y:8245 { yyLOCAL = nil } @@ -24303,7 +24364,7 @@ yydefault: case 1191: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:8246 +//line mysql_sql.y:8249 { yyLOCAL = []string{yyDollar[1].cstrUnion().Compare()} } @@ -24311,7 +24372,7 @@ yydefault: case 1192: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:8250 +//line mysql_sql.y:8253 { yyLOCAL = append(yyDollar[1].strsUnion(), yyDollar[3].cstrUnion().Compare()) } @@ -24319,7 +24380,7 @@ yydefault: case 1193: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:8254 +//line mysql_sql.y:8257 { yyLOCAL = []string{yyDollar[1].str} } @@ -24327,45 +24388,45 @@ yydefault: case 1194: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:8258 +//line mysql_sql.y:8261 { yyLOCAL = append(yyDollar[1].strsUnion(), yyDollar[3].str) } yyVAL.union = yyLOCAL case 1195: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:8264 +//line mysql_sql.y:8267 { yyVAL.str = "" } case 1196: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:8268 +//line mysql_sql.y:8271 { yyVAL.str = yyDollar[1].str } case 1197: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:8272 +//line mysql_sql.y:8275 { yyVAL.str = yyDollar[2].str } case 1198: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:8278 +//line mysql_sql.y:8281 { yyVAL.str = yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) } case 1199: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:8282 +//line mysql_sql.y:8285 { yyVAL.str = yylex.(*Lexer).GetDbOrTblName(yyDollar[1].str) } case 1200: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:8288 +//line mysql_sql.y:8291 { yyLOCAL = tree.NewCStr("", 1) } @@ -24373,7 +24434,7 @@ yydefault: case 1201: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:8292 +//line mysql_sql.y:8295 { yyLOCAL = yyDollar[1].cstrUnion() } @@ -24381,7 +24442,7 @@ yydefault: case 1202: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:8296 +//line mysql_sql.y:8299 { yyLOCAL = yyDollar[2].cstrUnion() } @@ -24389,7 +24450,7 @@ yydefault: case 1203: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:8300 +//line mysql_sql.y:8303 { yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } @@ -24397,21 +24458,21 @@ yydefault: case 1204: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:8304 +//line mysql_sql.y:8307 { yyLOCAL = tree.NewCStr(yyDollar[2].str, 1) } yyVAL.union = yyLOCAL case 1205: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:8310 +//line mysql_sql.y:8313 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } case 1229: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8353 +//line mysql_sql.y:8356 { yyLOCAL = &tree.CreateIcebergCatalog{ IfNotExists: yyDollar[4].ifNotExistsUnion(), @@ -24423,7 +24484,7 @@ yydefault: case 1230: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8363 +//line mysql_sql.y:8366 { yyLOCAL = &tree.CreateMongoDBConnection{ IfNotExists: yyDollar[4].ifNotExistsUnion(), @@ -24435,7 +24496,7 @@ yydefault: case 1231: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8373 +//line mysql_sql.y:8376 { cronExpr := "" timezone := "" @@ -24458,7 +24519,7 @@ yydefault: case 1232: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.SQLTaskSchedule -//line mysql_sql.y:8393 +//line mysql_sql.y:8396 { yyLOCAL = nil } @@ -24466,7 +24527,7 @@ yydefault: case 1233: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.SQLTaskSchedule -//line mysql_sql.y:8397 +//line mysql_sql.y:8400 { yyLOCAL = &tree.SQLTaskSchedule{ CronExpr: yyDollar[2].str, @@ -24476,20 +24537,20 @@ yydefault: yyVAL.union = yyLOCAL case 1234: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:8405 +//line mysql_sql.y:8408 { yyVAL.str = "" } case 1235: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:8409 +//line mysql_sql.y:8412 { yyVAL.str = yyDollar[2].str } case 1236: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:8414 +//line mysql_sql.y:8417 { yyLOCAL = tree.Expr(nil) } @@ -24497,7 +24558,7 @@ yydefault: case 1237: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:8418 +//line mysql_sql.y:8421 { yyLOCAL = yyDollar[3].exprUnion() } @@ -24505,7 +24566,7 @@ yydefault: case 1238: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:8424 +//line mysql_sql.y:8427 { yyLOCAL = yyDollar[1].exprUnion() } @@ -24513,7 +24574,7 @@ yydefault: case 1239: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:8428 +//line mysql_sql.y:8431 { yyLOCAL = tree.NewSubquery(yyDollar[1].selectUnion(), false) } @@ -24521,7 +24582,7 @@ yydefault: case 1240: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:8433 +//line mysql_sql.y:8436 { yyLOCAL = 0 } @@ -24529,27 +24590,27 @@ yydefault: case 1241: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:8437 +//line mysql_sql.y:8440 { yyLOCAL = sqlTaskInt64(yyDollar[2].item) } yyVAL.union = yyLOCAL case 1242: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:8442 +//line mysql_sql.y:8445 { yyVAL.str = "" } case 1243: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:8446 +//line mysql_sql.y:8449 { yyVAL.str = yyDollar[2].str } case 1244: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8452 +//line mysql_sql.y:8455 { var Language = yyDollar[3].str var Name = tree.Identifier(yyDollar[5].str) @@ -24563,20 +24624,20 @@ yydefault: yyVAL.union = yyLOCAL case 1245: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:8465 +//line mysql_sql.y:8468 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } case 1246: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:8471 +//line mysql_sql.y:8474 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } case 1247: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8477 +//line mysql_sql.y:8480 { yyLOCAL = tree.NewCreateProcedure( yyDollar[2].sourceOptionalUnion(), yyDollar[4].procNameUnion(), yyDollar[6].procArgsUnion(), yyDollar[8].str, yyDollar[9].str, @@ -24586,7 +24647,7 @@ yydefault: case 1248: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.ProcedureName -//line mysql_sql.y:8485 +//line mysql_sql.y:8488 { prefix := tree.ObjectNamePrefix{ExplicitSchema: false} yyLOCAL = tree.NewProcedureName(tree.Identifier(yyDollar[1].cstrUnion().Compare()), prefix) @@ -24595,7 +24656,7 @@ yydefault: case 1249: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ProcedureName -//line mysql_sql.y:8490 +//line mysql_sql.y:8493 { dbName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) prefix := tree.ObjectNamePrefix{SchemaName: tree.Identifier(dbName), ExplicitSchema: true} @@ -24605,7 +24666,7 @@ yydefault: case 1250: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.ProcedureArgs -//line mysql_sql.y:8497 +//line mysql_sql.y:8500 { yyLOCAL = tree.ProcedureArgs(nil) } @@ -24613,7 +24674,7 @@ yydefault: case 1252: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ProcedureArgs -//line mysql_sql.y:8504 +//line mysql_sql.y:8507 { yyLOCAL = tree.ProcedureArgs{yyDollar[1].procArgUnion()} } @@ -24621,7 +24682,7 @@ yydefault: case 1253: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.ProcedureArgs -//line mysql_sql.y:8508 +//line mysql_sql.y:8511 { yyLOCAL = append(yyDollar[1].procArgsUnion(), yyDollar[3].procArgUnion()) } @@ -24629,7 +24690,7 @@ yydefault: case 1254: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ProcedureArg -//line mysql_sql.y:8514 +//line mysql_sql.y:8517 { yyLOCAL = tree.ProcedureArg(yyDollar[1].procArgDeclUnion()) } @@ -24637,7 +24698,7 @@ yydefault: case 1255: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ProcedureArgDecl -//line mysql_sql.y:8520 +//line mysql_sql.y:8523 { yyLOCAL = tree.NewProcedureArgDecl(yyDollar[1].procArgTypeUnion(), yyDollar[2].unresolvedNameUnion(), yyDollar[3].columnTypeUnion()) } @@ -24645,7 +24706,7 @@ yydefault: case 1256: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.InOutArgType -//line mysql_sql.y:8525 +//line mysql_sql.y:8528 { yyLOCAL = tree.TYPE_IN } @@ -24653,7 +24714,7 @@ yydefault: case 1257: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.InOutArgType -//line mysql_sql.y:8529 +//line mysql_sql.y:8532 { yyLOCAL = tree.TYPE_IN } @@ -24661,7 +24722,7 @@ yydefault: case 1258: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.InOutArgType -//line mysql_sql.y:8533 +//line mysql_sql.y:8536 { yyLOCAL = tree.TYPE_OUT } @@ -24669,27 +24730,27 @@ yydefault: case 1259: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.InOutArgType -//line mysql_sql.y:8537 +//line mysql_sql.y:8540 { yyLOCAL = tree.TYPE_INOUT } yyVAL.union = yyLOCAL case 1260: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:8542 +//line mysql_sql.y:8545 { yyVAL.str = "sql" } case 1261: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:8546 +//line mysql_sql.y:8549 { yyVAL.str = yyDollar[2].str } case 1262: - yyDollar = yyS[yypt-14 : yypt+1] + yyDollar = yyS[yypt-15 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8552 +//line mysql_sql.y:8555 { if yyDollar[13].str == "" { yylex.Error("no function body error") @@ -24708,8 +24769,9 @@ yydefault: var Import = yyDollar[12].boolValUnion() var Body = yyDollar[13].str var Handler = yyDollar[14].str + var Options = yyDollar[15].pythonFunctionOptionsUnion() - yyLOCAL = tree.NewCreateFunction( + node := tree.NewCreateFunction( Replace, Name, Args, @@ -24719,12 +24781,15 @@ yydefault: Body, Handler, ) + node.Mode = Options.Mode + node.NullPolicy = Options.NullPolicy + yyLOCAL = node } yyVAL.union = yyLOCAL case 1263: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.FunctionName -//line mysql_sql.y:8585 +//line mysql_sql.y:8592 { prefix := tree.ObjectNamePrefix{ExplicitSchema: false} yyLOCAL = tree.NewFuncName(tree.Identifier(yyDollar[1].cstrUnion().Compare()), prefix) @@ -24733,7 +24798,7 @@ yydefault: case 1264: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.FunctionName -//line mysql_sql.y:8590 +//line mysql_sql.y:8597 { dbName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) prefix := tree.ObjectNamePrefix{SchemaName: tree.Identifier(dbName), ExplicitSchema: true} @@ -24743,7 +24808,7 @@ yydefault: case 1265: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.FunctionArgs -//line mysql_sql.y:8597 +//line mysql_sql.y:8604 { yyLOCAL = tree.FunctionArgs(nil) } @@ -24751,7 +24816,7 @@ yydefault: case 1267: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FunctionArgs -//line mysql_sql.y:8604 +//line mysql_sql.y:8611 { yyLOCAL = tree.FunctionArgs{yyDollar[1].funcArgUnion()} } @@ -24759,7 +24824,7 @@ yydefault: case 1268: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.FunctionArgs -//line mysql_sql.y:8608 +//line mysql_sql.y:8615 { yyLOCAL = append(yyDollar[1].funcArgsUnion(), yyDollar[3].funcArgUnion()) } @@ -24767,7 +24832,7 @@ yydefault: case 1269: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FunctionArg -//line mysql_sql.y:8614 +//line mysql_sql.y:8621 { yyLOCAL = tree.FunctionArg(yyDollar[1].funcArgDeclUnion()) } @@ -24775,7 +24840,7 @@ yydefault: case 1270: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.FunctionArgDecl -//line mysql_sql.y:8620 +//line mysql_sql.y:8627 { yyLOCAL = tree.NewFunctionArgDecl(nil, yyDollar[1].columnTypeUnion(), nil) } @@ -24783,7 +24848,7 @@ yydefault: case 1271: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FunctionArgDecl -//line mysql_sql.y:8624 +//line mysql_sql.y:8631 { yyLOCAL = tree.NewFunctionArgDecl(yyDollar[1].unresolvedNameUnion(), yyDollar[2].columnTypeUnion(), nil) } @@ -24791,21 +24856,21 @@ yydefault: case 1272: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FunctionArgDecl -//line mysql_sql.y:8628 +//line mysql_sql.y:8635 { yyLOCAL = tree.NewFunctionArgDecl(yyDollar[1].unresolvedNameUnion(), yyDollar[2].columnTypeUnion(), yyDollar[4].exprUnion()) } yyVAL.union = yyLOCAL case 1273: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:8634 +//line mysql_sql.y:8641 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } case 1274: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.ReturnType -//line mysql_sql.y:8640 +//line mysql_sql.y:8647 { yyLOCAL = tree.NewReturnType(yyDollar[1].columnTypeUnion()) } @@ -24813,7 +24878,7 @@ yydefault: case 1275: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8646 +//line mysql_sql.y:8653 { yyLOCAL = false } @@ -24821,27 +24886,91 @@ yydefault: case 1276: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8650 +//line mysql_sql.y:8657 { yyLOCAL = true } yyVAL.union = yyLOCAL case 1277: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:8655 +//line mysql_sql.y:8662 { yyVAL.str = "" } case 1279: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:8662 +//line mysql_sql.y:8669 { yyVAL.str = yyDollar[2].str } case 1280: + yyDollar = yyS[yypt-0 : yypt+1] + var yyLOCAL tree.PythonFunctionOptions +//line mysql_sql.y:8674 + { + yyLOCAL = tree.PythonFunctionOptions{} + } + yyVAL.union = yyLOCAL + case 1281: + yyDollar = yyS[yypt-2 : yypt+1] + var yyLOCAL tree.PythonFunctionOptions +//line mysql_sql.y:8678 + { + yyLOCAL = tree.PythonFunctionOptions{Mode: yyDollar[2].str} + } + yyVAL.union = yyLOCAL + case 1282: + yyDollar = yyS[yypt-1 : yypt+1] + var yyLOCAL tree.PythonFunctionOptions +//line mysql_sql.y:8682 + { + yyLOCAL = tree.PythonFunctionOptions{NullPolicy: yyDollar[1].str} + } + yyVAL.union = yyLOCAL + case 1283: + yyDollar = yyS[yypt-3 : yypt+1] + var yyLOCAL tree.PythonFunctionOptions +//line mysql_sql.y:8686 + { + yyLOCAL = tree.PythonFunctionOptions{Mode: yyDollar[2].str, NullPolicy: yyDollar[3].str} + } + yyVAL.union = yyLOCAL + case 1284: + yyDollar = yyS[yypt-3 : yypt+1] + var yyLOCAL tree.PythonFunctionOptions +//line mysql_sql.y:8690 + { + yyLOCAL = tree.PythonFunctionOptions{Mode: yyDollar[3].str, NullPolicy: yyDollar[1].str} + } + yyVAL.union = yyLOCAL + case 1285: + yyDollar = yyS[yypt-1 : yypt+1] +//line mysql_sql.y:8696 + { + yyVAL.str = "SCALAR" + } + case 1286: + yyDollar = yyS[yypt-1 : yypt+1] +//line mysql_sql.y:8700 + { + yyVAL.str = "VECTOR" + } + case 1287: + yyDollar = yyS[yypt-4 : yypt+1] +//line mysql_sql.y:8706 + { + yyVAL.str = "CALLED_ON_NULL_INPUT" + } + case 1288: + yyDollar = yyS[yypt-5 : yypt+1] +//line mysql_sql.y:8710 + { + yyVAL.str = "RETURNS_NULL_ON_NULL_INPUT" + } + case 1289: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8668 +//line mysql_sql.y:8716 { var Replace bool var Name = yyDollar[5].tableNameUnion() @@ -24861,10 +24990,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1281: + case 1290: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8687 +//line mysql_sql.y:8735 { var Replace = yyDollar[2].sourceOptionalUnion() var Name = yyDollar[5].tableNameUnion() @@ -24884,10 +25013,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1282: + case 1291: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8708 +//line mysql_sql.y:8756 { var IfNotExists = yyDollar[3].ifNotExistsUnion() var Name = yyDollar[4].exprUnion() @@ -24903,10 +25032,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1283: + case 1292: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8723 +//line mysql_sql.y:8771 { var FromUri = yyDollar[4].str var SubscriptionAccountName = yyDollar[5].cstrUnion().Compare() @@ -24924,81 +25053,81 @@ yydefault: yyLOCAL = cs } yyVAL.union = yyLOCAL - case 1284: + case 1293: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:8742 +//line mysql_sql.y:8790 { yyVAL.str = yyDollar[1].str } - case 1285: + case 1294: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:8746 +//line mysql_sql.y:8794 { yyVAL.str = yyVAL.str + yyDollar[2].str } - case 1286: + case 1295: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:8752 +//line mysql_sql.y:8800 { yyVAL.str = "ALGORITHM = " + yyDollar[3].str } - case 1287: + case 1296: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:8756 +//line mysql_sql.y:8804 { yyVAL.str = "DEFINER = " } - case 1288: + case 1297: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:8760 +//line mysql_sql.y:8808 { yyVAL.str = "SQL SECURITY " + yyDollar[3].str } - case 1289: + case 1298: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:8765 +//line mysql_sql.y:8813 { yyVAL.str = "" } - case 1290: + case 1299: yyDollar = yyS[yypt-4 : yypt+1] -//line mysql_sql.y:8769 +//line mysql_sql.y:8817 { yyVAL.str = "WITH " + yyDollar[2].str + " CHECK OPTION" } - case 1296: + case 1305: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:8783 +//line mysql_sql.y:8831 { yyVAL.str = "" } - case 1299: + case 1308: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:8791 +//line mysql_sql.y:8839 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } - case 1300: + case 1309: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:8797 +//line mysql_sql.y:8845 { var str = yyDollar[1].cstrUnion().Compare() yyLOCAL = tree.NewNumVal(str, str, false, tree.P_char) } yyVAL.union = yyLOCAL - case 1301: + case 1310: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:8802 +//line mysql_sql.y:8850 { yyLOCAL = tree.NewParamExpr(yylex.(*Lexer).GetParamIndex()) } yyVAL.union = yyLOCAL - case 1302: + case 1311: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.AccountAuthOption -//line mysql_sql.y:8808 +//line mysql_sql.y:8856 { var Equal = yyDollar[2].str var AdminName = yyDollar[3].exprUnion() @@ -25010,36 +25139,36 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1303: + case 1312: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:8821 +//line mysql_sql.y:8869 { var str = yyDollar[1].str yyLOCAL = tree.NewNumVal(str, str, false, tree.P_char) } yyVAL.union = yyLOCAL - case 1304: + case 1313: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:8826 +//line mysql_sql.y:8874 { var str = yyDollar[1].cstrUnion().Compare() yyLOCAL = tree.NewNumVal(str, str, false, tree.P_char) } yyVAL.union = yyLOCAL - case 1305: + case 1314: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:8831 +//line mysql_sql.y:8879 { yyLOCAL = tree.NewParamExpr(yylex.(*Lexer).GetParamIndex()) } yyVAL.union = yyLOCAL - case 1306: + case 1315: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AccountIdentified -//line mysql_sql.y:8837 +//line mysql_sql.y:8885 { yyLOCAL = *tree.NewAccountIdentified( tree.AccountIdentifiedByPassword, @@ -25047,10 +25176,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1307: + case 1316: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AccountIdentified -//line mysql_sql.y:8844 +//line mysql_sql.y:8892 { yyLOCAL = *tree.NewAccountIdentified( tree.AccountIdentifiedByPassword, @@ -25058,10 +25187,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1308: + case 1317: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.AccountIdentified -//line mysql_sql.y:8851 +//line mysql_sql.y:8899 { yyLOCAL = *tree.NewAccountIdentified( tree.AccountIdentifiedByRandomPassword, @@ -25069,10 +25198,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1309: + case 1318: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AccountIdentified -//line mysql_sql.y:8858 +//line mysql_sql.y:8906 { yyLOCAL = *tree.NewAccountIdentified( tree.AccountIdentifiedWithSSL, @@ -25080,10 +25209,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1310: + case 1319: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.AccountIdentified -//line mysql_sql.y:8865 +//line mysql_sql.y:8913 { yyLOCAL = *tree.NewAccountIdentified( tree.AccountIdentifiedWithSSL, @@ -25091,20 +25220,20 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1311: + case 1320: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.AccountStatus -//line mysql_sql.y:8873 +//line mysql_sql.y:8921 { as := tree.NewAccountStatus() as.Exist = false yyLOCAL = *as } yyVAL.union = yyLOCAL - case 1312: + case 1321: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.AccountStatus -//line mysql_sql.y:8879 +//line mysql_sql.y:8927 { as := tree.NewAccountStatus() as.Exist = true @@ -25112,10 +25241,10 @@ yydefault: yyLOCAL = *as } yyVAL.union = yyLOCAL - case 1313: + case 1322: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.AccountStatus -//line mysql_sql.y:8886 +//line mysql_sql.y:8934 { as := tree.NewAccountStatus() as.Exist = true @@ -25123,10 +25252,10 @@ yydefault: yyLOCAL = *as } yyVAL.union = yyLOCAL - case 1314: + case 1323: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.AccountStatus -//line mysql_sql.y:8893 +//line mysql_sql.y:8941 { as := tree.NewAccountStatus() as.Exist = true @@ -25134,20 +25263,20 @@ yydefault: yyLOCAL = *as } yyVAL.union = yyLOCAL - case 1315: + case 1324: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.AccountComment -//line mysql_sql.y:8901 +//line mysql_sql.y:8949 { ac := tree.NewAccountComment() ac.Exist = false yyLOCAL = *ac } yyVAL.union = yyLOCAL - case 1316: + case 1325: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AccountComment -//line mysql_sql.y:8907 +//line mysql_sql.y:8955 { ac := tree.NewAccountComment() ac.Exist = true @@ -25155,10 +25284,10 @@ yydefault: yyLOCAL = *ac } yyVAL.union = yyLOCAL - case 1317: + case 1326: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8916 +//line mysql_sql.y:8964 { var IfNotExists = yyDollar[3].ifNotExistsUnion() var Users = yyDollar[4].usersUnion() @@ -25174,10 +25303,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1318: + case 1327: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8933 +//line mysql_sql.y:8981 { var IfNotExists = yyDollar[3].ifNotExistsUnion() var Name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) @@ -25194,10 +25323,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1319: + case 1328: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8949 +//line mysql_sql.y:8997 { var IfNotExists = yyDollar[3].ifNotExistsUnion() var Name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) @@ -25215,10 +25344,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1320: + case 1329: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8966 +//line mysql_sql.y:9014 { var IfNotExists = yyDollar[3].ifNotExistsUnion() var Name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) @@ -25235,30 +25364,30 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1321: + case 1330: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.AccountsSetOption -//line mysql_sql.y:8984 +//line mysql_sql.y:9032 { yyLOCAL = &tree.AccountsSetOption{ All: true, } } yyVAL.union = yyLOCAL - case 1322: + case 1331: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.AccountsSetOption -//line mysql_sql.y:8990 +//line mysql_sql.y:9038 { yyLOCAL = &tree.AccountsSetOption{ SetAccounts: yyDollar[2].identifierListUnion(), } } yyVAL.union = yyLOCAL - case 1323: + case 1332: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8998 +//line mysql_sql.y:9046 { var IfNotExists = yyDollar[3].ifNotExistsUnion() var Name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) @@ -25276,20 +25405,20 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1324: + case 1333: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.StageStatus -//line mysql_sql.y:9016 +//line mysql_sql.y:9064 { yyLOCAL = tree.StageStatus{ Exist: false, } } yyVAL.union = yyLOCAL - case 1325: + case 1334: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.StageStatus -//line mysql_sql.y:9022 +//line mysql_sql.y:9070 { yyLOCAL = tree.StageStatus{ Exist: true, @@ -25297,10 +25426,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1326: + case 1335: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.StageStatus -//line mysql_sql.y:9029 +//line mysql_sql.y:9077 { yyLOCAL = tree.StageStatus{ Exist: true, @@ -25308,20 +25437,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1327: + case 1336: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.StageComment -//line mysql_sql.y:9037 +//line mysql_sql.y:9085 { yyLOCAL = tree.StageComment{ Exist: false, } } yyVAL.union = yyLOCAL - case 1328: + case 1337: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.StageComment -//line mysql_sql.y:9043 +//line mysql_sql.y:9091 { yyLOCAL = tree.StageComment{ Exist: true, @@ -25329,18 +25458,18 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1329: + case 1338: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:9052 +//line mysql_sql.y:9100 { yyLOCAL = int64(0) } yyVAL.union = yyLOCAL - case 1330: + case 1339: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:9056 +//line mysql_sql.y:9104 { switch v := yyDollar[3].item.(type) { case int64: @@ -25352,20 +25481,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1331: + case 1340: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.StageUrl -//line mysql_sql.y:9068 +//line mysql_sql.y:9116 { yyLOCAL = tree.StageUrl{ Exist: false, } } yyVAL.union = yyLOCAL - case 1332: + case 1341: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.StageUrl -//line mysql_sql.y:9074 +//line mysql_sql.y:9122 { yyLOCAL = tree.StageUrl{ Exist: true, @@ -25373,20 +25502,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1333: + case 1342: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.StageCredentials -//line mysql_sql.y:9082 +//line mysql_sql.y:9130 { yyLOCAL = tree.StageCredentials{ Exist: false, } } yyVAL.union = yyLOCAL - case 1334: + case 1343: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.StageCredentials -//line mysql_sql.y:9088 +//line mysql_sql.y:9136 { yyLOCAL = tree.StageCredentials{ Exist: true, @@ -25394,61 +25523,61 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1335: + case 1344: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:9097 +//line mysql_sql.y:9145 { yyLOCAL = yyDollar[1].strsUnion() } yyVAL.union = yyLOCAL - case 1336: + case 1345: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:9101 +//line mysql_sql.y:9149 { yyLOCAL = append(yyDollar[1].strsUnion(), yyDollar[3].strsUnion()...) } yyVAL.union = yyLOCAL - case 1337: + case 1346: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:9106 +//line mysql_sql.y:9154 { yyLOCAL = []string{} } yyVAL.union = yyLOCAL - case 1338: + case 1347: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:9110 +//line mysql_sql.y:9158 { yyLOCAL = append(yyLOCAL, yyDollar[1].str) yyLOCAL = append(yyLOCAL, yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1339: + case 1348: yyDollar = yyS[yypt-3 : yypt+1] -//line mysql_sql.y:9117 +//line mysql_sql.y:9165 { yyVAL.str = yyDollar[3].str } - case 1340: + case 1349: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:9122 +//line mysql_sql.y:9170 { yyVAL.str = "" } - case 1341: + case 1350: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:9126 +//line mysql_sql.y:9174 { yyVAL.str = yyDollar[2].str } - case 1342: + case 1351: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:9132 +//line mysql_sql.y:9180 { var ifNotExists = yyDollar[3].boolValUnion() var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) @@ -25459,10 +25588,10 @@ yydefault: yyLOCAL = tree.NewAlterStage(ifNotExists, name, urlOption, credentialsOption, statusOption, comment) } yyVAL.union = yyLOCAL - case 1343: + case 1352: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:9144 +//line mysql_sql.y:9192 { var ifExists = yyDollar[3].boolValUnion() var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) @@ -25473,154 +25602,154 @@ yydefault: yyLOCAL = tree.NewAlterPublication(ifExists, name, accountsSet, dbName, table, comment) } yyVAL.union = yyLOCAL - case 1344: + case 1353: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.AccountsSetOption -//line mysql_sql.y:9155 +//line mysql_sql.y:9203 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1345: + case 1354: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.AccountsSetOption -//line mysql_sql.y:9159 +//line mysql_sql.y:9207 { yyLOCAL = &tree.AccountsSetOption{ All: true, } } yyVAL.union = yyLOCAL - case 1346: + case 1355: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.AccountsSetOption -//line mysql_sql.y:9165 +//line mysql_sql.y:9213 { yyLOCAL = &tree.AccountsSetOption{ SetAccounts: yyDollar[2].identifierListUnion(), } } yyVAL.union = yyLOCAL - case 1347: + case 1356: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.AccountsSetOption -//line mysql_sql.y:9171 +//line mysql_sql.y:9219 { yyLOCAL = &tree.AccountsSetOption{ AddAccounts: yyDollar[3].identifierListUnion(), } } yyVAL.union = yyLOCAL - case 1348: + case 1357: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.AccountsSetOption -//line mysql_sql.y:9177 +//line mysql_sql.y:9225 { yyLOCAL = &tree.AccountsSetOption{ DropAccounts: yyDollar[3].identifierListUnion(), } } yyVAL.union = yyLOCAL - case 1349: + case 1358: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:9184 +//line mysql_sql.y:9232 { yyVAL.str = "" } - case 1350: + case 1359: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:9188 +//line mysql_sql.y:9236 { yyVAL.str = yyDollar[2].str } - case 1351: + case 1360: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.TableNames -//line mysql_sql.y:9193 +//line mysql_sql.y:9241 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1352: + case 1361: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.TableNames -//line mysql_sql.y:9197 +//line mysql_sql.y:9245 { yyLOCAL = yyDollar[2].tableNamesUnion() } yyVAL.union = yyLOCAL - case 1353: + case 1362: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:9203 +//line mysql_sql.y:9251 { var ifExists = yyDollar[3].boolValUnion() var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) yyLOCAL = tree.NewDropPublication(ifExists, name) } yyVAL.union = yyLOCAL - case 1354: + case 1363: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:9211 +//line mysql_sql.y:9259 { var ifExists = yyDollar[4].boolValUnion() var taskID = yyDollar[5].str yyLOCAL = tree.NewDropCcprSubscription(ifExists, taskID) } yyVAL.union = yyLOCAL - case 1355: + case 1364: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:9219 +//line mysql_sql.y:9267 { var taskID = yyDollar[4].str yyLOCAL = tree.NewResumeCcprSubscription(taskID) } yyVAL.union = yyLOCAL - case 1356: + case 1365: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:9226 +//line mysql_sql.y:9274 { var taskID = yyDollar[4].str yyLOCAL = tree.NewPauseCcprSubscription(taskID) } yyVAL.union = yyLOCAL - case 1357: + case 1366: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:9233 +//line mysql_sql.y:9281 { var ifNotExists = yyDollar[3].boolValUnion() var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) yyLOCAL = tree.NewDropStage(ifNotExists, name) } yyVAL.union = yyLOCAL - case 1358: + case 1367: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:9241 +//line mysql_sql.y:9289 { var ifExists = yyDollar[5].boolValUnion() var path = yyDollar[6].str yyLOCAL = tree.NewRemoveStageFiles(ifExists, path) } yyVAL.union = yyLOCAL - case 1359: + case 1368: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:9249 +//line mysql_sql.y:9297 { var ifExists = yyDollar[3].boolValUnion() var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) yyLOCAL = tree.NewDropSnapShot(ifExists, name, "", "") } yyVAL.union = yyLOCAL - case 1360: + case 1369: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:9255 +//line mysql_sql.y:9303 { var ifExists = yyDollar[3].boolValUnion() var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) @@ -25629,10 +25758,10 @@ yydefault: yyLOCAL = tree.NewDropSnapShot(ifExists, name, accountName, pubName) } yyVAL.union = yyLOCAL - case 1361: + case 1370: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:9265 +//line mysql_sql.y:9313 { var ifExists = yyDollar[3].boolValUnion() var name = tree.Identifier(yyDollar[4].cstrUnion().Compare()) @@ -25644,16 +25773,16 @@ yydefault: } yyVAL.union = yyLOCAL - case 1362: + case 1371: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:9278 +//line mysql_sql.y:9326 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } - case 1363: + case 1372: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.AccountCommentOrAttribute -//line mysql_sql.y:9283 +//line mysql_sql.y:9331 { var Exist = false var IsComment bool @@ -25666,10 +25795,10 @@ yydefault: } yyVAL.union = yyLOCAL - case 1364: + case 1373: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AccountCommentOrAttribute -//line mysql_sql.y:9295 +//line mysql_sql.y:9343 { var Exist = true var IsComment = true @@ -25681,10 +25810,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1365: + case 1374: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.AccountCommentOrAttribute -//line mysql_sql.y:9306 +//line mysql_sql.y:9354 { var Exist = true var IsComment = false @@ -25696,26 +25825,26 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1366: + case 1375: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.User -//line mysql_sql.y:9414 +//line mysql_sql.y:9462 { yyLOCAL = []*tree.User{yyDollar[1].userUnion()} } yyVAL.union = yyLOCAL - case 1367: + case 1376: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.User -//line mysql_sql.y:9418 +//line mysql_sql.y:9466 { yyLOCAL = append(yyDollar[1].usersUnion(), yyDollar[3].userUnion()) } yyVAL.union = yyLOCAL - case 1368: + case 1377: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.User -//line mysql_sql.y:9424 +//line mysql_sql.y:9472 { var Username = yyDollar[1].usernameRecordUnion().Username var Hostname = yyDollar[1].usernameRecordUnion().Hostname @@ -25727,26 +25856,26 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1369: + case 1378: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.User -//line mysql_sql.y:9437 +//line mysql_sql.y:9485 { yyLOCAL = []*tree.User{yyDollar[1].userUnion()} } yyVAL.union = yyLOCAL - case 1370: + case 1379: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.User -//line mysql_sql.y:9441 +//line mysql_sql.y:9489 { yyLOCAL = append(yyDollar[1].usersUnion(), yyDollar[3].userUnion()) } yyVAL.union = yyLOCAL - case 1371: + case 1380: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.User -//line mysql_sql.y:9447 +//line mysql_sql.y:9495 { var Username = yyDollar[1].usernameRecordUnion().Username var Hostname = yyDollar[1].usernameRecordUnion().Hostname @@ -25758,50 +25887,50 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1372: + case 1381: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UsernameRecord -//line mysql_sql.y:9460 +//line mysql_sql.y:9508 { yyLOCAL = &tree.UsernameRecord{Username: yyDollar[1].str, Hostname: "%"} } yyVAL.union = yyLOCAL - case 1373: + case 1382: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UsernameRecord -//line mysql_sql.y:9464 +//line mysql_sql.y:9512 { yyLOCAL = &tree.UsernameRecord{Username: yyDollar[1].str, Hostname: yyDollar[3].str} } yyVAL.union = yyLOCAL - case 1374: + case 1383: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.UsernameRecord -//line mysql_sql.y:9468 +//line mysql_sql.y:9516 { yyLOCAL = &tree.UsernameRecord{Username: yyDollar[1].str, Hostname: yyDollar[2].str} } yyVAL.union = yyLOCAL - case 1375: + case 1384: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.AccountIdentified -//line mysql_sql.y:9473 +//line mysql_sql.y:9521 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1376: + case 1385: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.AccountIdentified -//line mysql_sql.y:9477 +//line mysql_sql.y:9525 { yyLOCAL = yyDollar[1].userIdentifiedUnion() } yyVAL.union = yyLOCAL - case 1377: + case 1386: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.AccountIdentified -//line mysql_sql.y:9483 +//line mysql_sql.y:9531 { yyLOCAL = &tree.AccountIdentified{ Typ: tree.AccountIdentifiedByPassword, @@ -25809,20 +25938,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1378: + case 1387: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.AccountIdentified -//line mysql_sql.y:9490 +//line mysql_sql.y:9538 { yyLOCAL = &tree.AccountIdentified{ Typ: tree.AccountIdentifiedByRandomPassword, } } yyVAL.union = yyLOCAL - case 1379: + case 1388: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.AccountIdentified -//line mysql_sql.y:9496 +//line mysql_sql.y:9544 { yyLOCAL = &tree.AccountIdentified{ Typ: tree.AccountIdentifiedWithSSL, @@ -25830,16 +25959,16 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1380: + case 1389: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:9505 +//line mysql_sql.y:9553 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } - case 1382: + case 1391: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:9512 +//line mysql_sql.y:9560 { var IfNotExists = yyDollar[3].ifNotExistsUnion() var Roles = yyDollar[4].rolesUnion() @@ -25849,26 +25978,26 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1383: + case 1392: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.Role -//line mysql_sql.y:9523 +//line mysql_sql.y:9571 { yyLOCAL = []*tree.Role{yyDollar[1].roleUnion()} } yyVAL.union = yyLOCAL - case 1384: + case 1393: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.Role -//line mysql_sql.y:9527 +//line mysql_sql.y:9575 { yyLOCAL = append(yyDollar[1].rolesUnion(), yyDollar[3].roleUnion()) } yyVAL.union = yyLOCAL - case 1385: + case 1394: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Role -//line mysql_sql.y:9533 +//line mysql_sql.y:9581 { var UserName = yyDollar[1].cstrUnion().Compare() yyLOCAL = tree.NewRole( @@ -25876,114 +26005,114 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1386: + case 1395: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:9542 +//line mysql_sql.y:9590 { yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 1387: + case 1396: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:9546 +//line mysql_sql.y:9594 { yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 1388: + case 1397: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:9550 +//line mysql_sql.y:9598 { yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 1389: + case 1398: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:9554 +//line mysql_sql.y:9602 { yyLOCAL = tree.NewCStr("lag", 1) } yyVAL.union = yyLOCAL - case 1390: + case 1399: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:9558 +//line mysql_sql.y:9606 { yyLOCAL = tree.NewCStr("lead", 1) } yyVAL.union = yyLOCAL - case 1391: + case 1400: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:9562 +//line mysql_sql.y:9610 { yyLOCAL = tree.NewCStr("first_value", 1) } yyVAL.union = yyLOCAL - case 1392: + case 1401: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:9566 +//line mysql_sql.y:9614 { yyLOCAL = tree.NewCStr("last_value", 1) } yyVAL.union = yyLOCAL - case 1393: + case 1402: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:9570 +//line mysql_sql.y:9618 { yyLOCAL = tree.NewCStr("nth_value", 1) } yyVAL.union = yyLOCAL - case 1394: + case 1403: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.IndexCategory -//line mysql_sql.y:9575 +//line mysql_sql.y:9623 { yyLOCAL = tree.INDEX_CATEGORY_NONE } yyVAL.union = yyLOCAL - case 1395: + case 1404: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IndexCategory -//line mysql_sql.y:9579 +//line mysql_sql.y:9627 { yyLOCAL = tree.INDEX_CATEGORY_FULLTEXT } yyVAL.union = yyLOCAL - case 1396: + case 1405: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IndexCategory -//line mysql_sql.y:9583 +//line mysql_sql.y:9631 { yyLOCAL = tree.INDEX_CATEGORY_FULLTEXT2 } yyVAL.union = yyLOCAL - case 1397: + case 1406: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IndexCategory -//line mysql_sql.y:9587 +//line mysql_sql.y:9635 { yyLOCAL = tree.INDEX_CATEGORY_SPATIAL } yyVAL.union = yyLOCAL - case 1398: + case 1407: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IndexCategory -//line mysql_sql.y:9591 +//line mysql_sql.y:9639 { yyLOCAL = tree.INDEX_CATEGORY_UNIQUE } yyVAL.union = yyLOCAL - case 1399: + case 1408: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:9597 +//line mysql_sql.y:9645 { var io *tree.IndexOption = nil if yyDollar[11].indexOptionUnion() == nil && yyDollar[5].indexTypeUnion() != tree.INDEX_TYPE_INVALID { @@ -26014,18 +26143,18 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1400: + case 1409: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9628 +//line mysql_sql.y:9676 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1401: + case 1410: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9632 +//line mysql_sql.y:9680 { // Merge the options if yyDollar[1].indexOptionUnion() == nil { @@ -26099,20 +26228,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1402: + case 1411: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9707 +//line mysql_sql.y:9755 { io := tree.NewIndexOption() io.KeyBlockSize = uint64(yyDollar[3].item.(int64)) yyLOCAL = io } yyVAL.union = yyLOCAL - case 1403: + case 1412: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9713 +//line mysql_sql.y:9761 { val := int64(yyDollar[3].item.(int64)) if val <= 0 { @@ -26125,60 +26254,60 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1404: + case 1413: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9725 +//line mysql_sql.y:9773 { io := tree.NewIndexOption() io.AlgoParamVectorOpType = yyDollar[2].str yyLOCAL = io } yyVAL.union = yyLOCAL - case 1405: + case 1414: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9731 +//line mysql_sql.y:9779 { io := tree.NewIndexOption() io.Comment = yyDollar[2].str yyLOCAL = io } yyVAL.union = yyLOCAL - case 1406: + case 1415: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9737 +//line mysql_sql.y:9785 { io := tree.NewIndexOption() io.ParserName = yyDollar[3].cstrUnion().Compare() yyLOCAL = io } yyVAL.union = yyLOCAL - case 1407: + case 1416: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9743 +//line mysql_sql.y:9791 { io := tree.NewIndexOption() io.Visible = tree.VISIBLE_TYPE_VISIBLE yyLOCAL = io } yyVAL.union = yyLOCAL - case 1408: + case 1417: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9749 +//line mysql_sql.y:9797 { io := tree.NewIndexOption() io.Visible = tree.VISIBLE_TYPE_INVISIBLE yyLOCAL = io } yyVAL.union = yyLOCAL - case 1409: + case 1418: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9755 +//line mysql_sql.y:9803 { val := int64(yyDollar[3].item.(int64)) if val <= 0 { @@ -26190,10 +26319,10 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1410: + case 1419: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9766 +//line mysql_sql.y:9814 { val := int64(yyDollar[3].item.(int64)) if val <= 0 { @@ -26205,10 +26334,10 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1411: + case 1420: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9777 +//line mysql_sql.y:9825 { val := int64(yyDollar[3].item.(int64)) if val <= 0 { @@ -26220,10 +26349,10 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1412: + case 1421: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9788 +//line mysql_sql.y:9836 { val := int64(yyDollar[3].item.(int64)) if val <= 0 { @@ -26235,10 +26364,10 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1413: + case 1422: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9799 +//line mysql_sql.y:9847 { val := int64(yyDollar[3].item.(int64)) if val <= 0 { @@ -26250,10 +26379,10 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1414: + case 1423: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9810 +//line mysql_sql.y:9858 { val := int64(yyDollar[3].item.(int64)) if val <= 0 { @@ -26265,40 +26394,40 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1415: + case 1424: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9821 +//line mysql_sql.y:9869 { io := tree.NewIndexOption() io.IncludeColumns = yyDollar[3].unresolveNamesUnion() yyLOCAL = io } yyVAL.union = yyLOCAL - case 1416: + case 1425: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9827 +//line mysql_sql.y:9875 { io := tree.NewIndexOption() io.Quantization = yyDollar[2].str yyLOCAL = io } yyVAL.union = yyLOCAL - case 1417: + case 1426: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9833 +//line mysql_sql.y:9881 { io := tree.NewIndexOption() io.DistributionMode = yyDollar[2].str yyLOCAL = io } yyVAL.union = yyLOCAL - case 1418: + case 1427: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9839 +//line mysql_sql.y:9887 { val := int64(yyDollar[3].item.(int64)) if val <= 0 { @@ -26310,10 +26439,10 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1419: + case 1428: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9850 +//line mysql_sql.y:9898 { val := int64(yyDollar[3].item.(int64)) if val <= 0 { @@ -26325,10 +26454,10 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1420: + case 1429: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9861 +//line mysql_sql.y:9909 { val := int64(yyDollar[3].item.(int64)) if val <= 0 { @@ -26340,10 +26469,10 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1421: + case 1430: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9872 +//line mysql_sql.y:9920 { val := int64(yyDollar[3].item.(int64)) if val <= 0 { @@ -26355,10 +26484,10 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1422: + case 1431: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9883 +//line mysql_sql.y:9931 { val := int64(yyDollar[3].item.(int64)) if val <= 0 { @@ -26370,10 +26499,10 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1423: + case 1432: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9894 +//line mysql_sql.y:9942 { val := int64(yyDollar[3].item.(int64)) if val <= 0 { @@ -26385,10 +26514,10 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1424: + case 1433: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9905 +//line mysql_sql.y:9953 { io := tree.NewIndexOption() io.PositionFree = true @@ -26396,10 +26525,10 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1425: + case 1434: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9912 +//line mysql_sql.y:9960 { io := tree.NewIndexOption() io.PositionFree = false @@ -26407,60 +26536,60 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1426: + case 1435: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9919 +//line mysql_sql.y:9967 { io := tree.NewIndexOption() io.Async = true yyLOCAL = io } yyVAL.union = yyLOCAL - case 1427: + case 1436: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9925 +//line mysql_sql.y:9973 { io := tree.NewIndexOption() io.ForceSync = true yyLOCAL = io } yyVAL.union = yyLOCAL - case 1428: + case 1437: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9931 +//line mysql_sql.y:9979 { io := tree.NewIndexOption() io.Merge = true yyLOCAL = io } yyVAL.union = yyLOCAL - case 1429: + case 1438: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9937 +//line mysql_sql.y:9985 { io := tree.NewIndexOption() io.AutoUpdate = true yyLOCAL = io } yyVAL.union = yyLOCAL - case 1430: + case 1439: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9943 +//line mysql_sql.y:9991 { io := tree.NewIndexOption() io.AutoUpdate = false yyLOCAL = io } yyVAL.union = yyLOCAL - case 1431: + case 1440: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9949 +//line mysql_sql.y:9997 { val := int64(yyDollar[3].item.(int64)) if val < 0 { @@ -26472,10 +26601,10 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1432: + case 1441: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9960 +//line mysql_sql.y:10008 { val := int64(yyDollar[3].item.(int64)) if val < 0 || val > 23 { @@ -26487,10 +26616,10 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1433: + case 1442: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IndexOption -//line mysql_sql.y:9971 +//line mysql_sql.y:10019 { val := int64(yyDollar[3].item.(int64)) if val < 0 { @@ -26502,26 +26631,26 @@ yydefault: yyLOCAL = io } yyVAL.union = yyLOCAL - case 1434: + case 1443: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.KeyPart -//line mysql_sql.y:9985 +//line mysql_sql.y:10033 { yyLOCAL = []*tree.KeyPart{yyDollar[1].keyPartUnion()} } yyVAL.union = yyLOCAL - case 1435: + case 1444: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.KeyPart -//line mysql_sql.y:9989 +//line mysql_sql.y:10037 { yyLOCAL = append(yyDollar[1].keyPartsUnion(), yyDollar[3].keyPartUnion()) } yyVAL.union = yyLOCAL - case 1436: + case 1445: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.KeyPart -//line mysql_sql.y:9995 +//line mysql_sql.y:10043 { // Order is parsed but just ignored as MySQL dtree. var ColName = yyDollar[1].unresolvedNameUnion() @@ -26536,10 +26665,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1437: + case 1446: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.KeyPart -//line mysql_sql.y:10009 +//line mysql_sql.y:10057 { var ColName *tree.UnresolvedName var Length int @@ -26553,90 +26682,90 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1438: + case 1447: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.IndexType -//line mysql_sql.y:10023 +//line mysql_sql.y:10071 { yyLOCAL = tree.INDEX_TYPE_INVALID } yyVAL.union = yyLOCAL - case 1439: + case 1448: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexType -//line mysql_sql.y:10027 +//line mysql_sql.y:10075 { yyLOCAL = tree.INDEX_TYPE_BTREE } yyVAL.union = yyLOCAL - case 1440: + case 1449: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexType -//line mysql_sql.y:10031 +//line mysql_sql.y:10079 { yyLOCAL = tree.INDEX_TYPE_IVFFLAT } yyVAL.union = yyLOCAL - case 1441: + case 1450: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexType -//line mysql_sql.y:10035 +//line mysql_sql.y:10083 { yyLOCAL = tree.INDEX_TYPE_HNSW } yyVAL.union = yyLOCAL - case 1442: + case 1451: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexType -//line mysql_sql.y:10039 +//line mysql_sql.y:10087 { yyLOCAL = tree.INDEX_TYPE_IVFPQ } yyVAL.union = yyLOCAL - case 1443: + case 1452: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexType -//line mysql_sql.y:10043 +//line mysql_sql.y:10091 { yyLOCAL = tree.INDEX_TYPE_CAGRA } yyVAL.union = yyLOCAL - case 1444: + case 1453: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexType -//line mysql_sql.y:10047 +//line mysql_sql.y:10095 { yyLOCAL = tree.INDEX_TYPE_MASTER } yyVAL.union = yyLOCAL - case 1445: + case 1454: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexType -//line mysql_sql.y:10051 +//line mysql_sql.y:10099 { yyLOCAL = tree.INDEX_TYPE_HASH } yyVAL.union = yyLOCAL - case 1446: + case 1455: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexType -//line mysql_sql.y:10055 +//line mysql_sql.y:10103 { yyLOCAL = tree.INDEX_TYPE_RTREE } yyVAL.union = yyLOCAL - case 1447: + case 1456: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.IndexType -//line mysql_sql.y:10059 +//line mysql_sql.y:10107 { yyLOCAL = tree.INDEX_TYPE_BSI } yyVAL.union = yyLOCAL - case 1448: + case 1457: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10065 +//line mysql_sql.y:10113 { var IfNotExists = yyDollar[3].ifNotExistsUnion() var Name = tree.Identifier(yyDollar[4].str) @@ -26650,10 +26779,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1449: + case 1458: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10079 +//line mysql_sql.y:10127 { var t = tree.NewCloneDatabase() t.IfNotExists = yyDollar[3].ifNotExistsUnion() @@ -26664,10 +26793,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1450: + case 1459: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10089 +//line mysql_sql.y:10137 { var DbName = tree.Identifier(yyDollar[4].str) var FromUri = yyDollar[6].str @@ -26685,100 +26814,100 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1451: + case 1460: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.SubscriptionOption -//line mysql_sql.y:10107 +//line mysql_sql.y:10155 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1452: + case 1461: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.SubscriptionOption -//line mysql_sql.y:10111 +//line mysql_sql.y:10159 { var From = tree.Identifier(yyDollar[2].str) var Publication = tree.Identifier(yyDollar[4].cstrUnion().Compare()) yyLOCAL = tree.NewSubscriptionOption(From, Publication) } yyVAL.union = yyLOCAL - case 1455: + case 1464: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10122 +//line mysql_sql.y:10170 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1456: + case 1465: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10126 +//line mysql_sql.y:10174 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1457: + case 1466: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10130 +//line mysql_sql.y:10178 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1458: + case 1467: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10135 +//line mysql_sql.y:10183 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1459: + case 1468: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10139 +//line mysql_sql.y:10187 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1460: + case 1469: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []tree.CreateOption -//line mysql_sql.y:10144 +//line mysql_sql.y:10192 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1461: + case 1470: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.CreateOption -//line mysql_sql.y:10148 +//line mysql_sql.y:10196 { yyLOCAL = yyDollar[1].createOptionsUnion() } yyVAL.union = yyLOCAL - case 1462: + case 1471: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.CreateOption -//line mysql_sql.y:10154 +//line mysql_sql.y:10202 { yyLOCAL = []tree.CreateOption{yyDollar[1].createOptionUnion()} } yyVAL.union = yyLOCAL - case 1463: + case 1472: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []tree.CreateOption -//line mysql_sql.y:10158 +//line mysql_sql.y:10206 { yyLOCAL = append(yyDollar[1].createOptionsUnion(), yyDollar[2].createOptionUnion()) } yyVAL.union = yyLOCAL - case 1464: + case 1473: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.CreateOption -//line mysql_sql.y:10164 +//line mysql_sql.y:10212 { var IsDefault = yyDollar[1].defaultOptionalUnion() var Charset = yyDollar[4].str @@ -26788,10 +26917,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1465: + case 1474: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.CreateOption -//line mysql_sql.y:10173 +//line mysql_sql.y:10221 { var IsDefault = yyDollar[1].defaultOptionalUnion() var Collate = yyDollar[4].str @@ -26801,35 +26930,35 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1466: + case 1475: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.CreateOption -//line mysql_sql.y:10182 +//line mysql_sql.y:10230 { var Encrypt = yyDollar[4].str yyLOCAL = tree.NewCreateOptionEncryption(Encrypt) } yyVAL.union = yyLOCAL - case 1467: + case 1476: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10188 +//line mysql_sql.y:10236 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1468: + case 1477: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10192 +//line mysql_sql.y:10240 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1469: + case 1478: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10198 +//line mysql_sql.y:10246 { var taskID uint64 switch v := yyDollar[4].item.(type) { @@ -26846,10 +26975,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1470: + case 1479: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10216 +//line mysql_sql.y:10264 { var taskID uint64 switch v := yyDollar[4].item.(type) { @@ -26866,10 +26995,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1471: + case 1480: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10234 +//line mysql_sql.y:10282 { var taskID uint64 switch v := yyDollar[4].item.(type) { @@ -26886,26 +27015,26 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1472: + case 1481: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10251 +//line mysql_sql.y:10299 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1473: + case 1482: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10255 +//line mysql_sql.y:10303 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1474: + case 1483: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10261 +//line mysql_sql.y:10309 { t := tree.NewDataBranchCreateTable() t.CreateTable.Table = *yyDollar[5].tableNameUnion() @@ -26916,10 +27045,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1475: + case 1484: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10271 +//line mysql_sql.y:10319 { t := tree.NewDataBranchCreateDatabase() t.DstDatabase = tree.Identifier(yyDollar[5].str) @@ -26929,30 +27058,30 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1476: + case 1485: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10280 +//line mysql_sql.y:10328 { t := tree.NewDataBranchDeleteTable() t.TableName = *yyDollar[5].tableNameUnion() yyLOCAL = t } yyVAL.union = yyLOCAL - case 1477: + case 1486: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10286 +//line mysql_sql.y:10334 { t := tree.NewDataBranchDeleteDatabase() t.DatabaseName = tree.Identifier(yyDollar[5].str) yyLOCAL = t } yyVAL.union = yyLOCAL - case 1478: + case 1487: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10292 +//line mysql_sql.y:10340 { t := tree.NewDataBranchDiff() t.TargetTable = *yyDollar[4].tableNameUnion() @@ -26962,10 +27091,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1479: + case 1488: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10301 +//line mysql_sql.y:10349 { t := tree.NewDataBranchMerge() t.SrcTable = *yyDollar[4].tableNameUnion() @@ -26974,10 +27103,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1480: + case 1489: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10309 +//line mysql_sql.y:10357 { t := tree.NewDataBranchPick() t.SrcTable = *yyDollar[4].tableNameUnion() @@ -26987,10 +27116,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1481: + case 1490: yyDollar = yyS[yypt-12 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10318 +//line mysql_sql.y:10366 { t := tree.NewDataBranchPick() t.SrcTable = *yyDollar[4].tableNameUnion() @@ -27001,10 +27130,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1482: + case 1491: yyDollar = yyS[yypt-12 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10328 +//line mysql_sql.y:10376 { t := tree.NewDataBranchPick() t.SrcTable = *yyDollar[4].tableNameUnion() @@ -27015,10 +27144,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1483: + case 1492: yyDollar = yyS[yypt-13 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10338 +//line mysql_sql.y:10386 { t := tree.NewDataBranchPick() t.SrcTable = *yyDollar[4].tableNameUnion() @@ -27030,10 +27159,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1484: + case 1493: yyDollar = yyS[yypt-13 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10349 +//line mysql_sql.y:10397 { t := tree.NewDataBranchPick() t.SrcTable = *yyDollar[4].tableNameUnion() @@ -27045,54 +27174,54 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1485: + case 1494: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:10361 +//line mysql_sql.y:10409 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1486: + case 1495: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.IdentifierList -//line mysql_sql.y:10365 +//line mysql_sql.y:10413 { yyLOCAL = yyDollar[3].identifierListUnion() } yyVAL.union = yyLOCAL - case 1487: + case 1496: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.DiffOutputOpt -//line mysql_sql.y:10370 +//line mysql_sql.y:10418 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1488: + case 1497: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.DiffOutputOpt -//line mysql_sql.y:10374 +//line mysql_sql.y:10422 { yyLOCAL = &tree.DiffOutputOpt{ As: *yyDollar[3].tableNameUnion(), } } yyVAL.union = yyLOCAL - case 1489: + case 1498: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.DiffOutputOpt -//line mysql_sql.y:10380 +//line mysql_sql.y:10428 { yyLOCAL = &tree.DiffOutputOpt{ DirPath: yyDollar[3].str, } } yyVAL.union = yyLOCAL - case 1490: + case 1499: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.DiffOutputOpt -//line mysql_sql.y:10386 +//line mysql_sql.y:10434 { x, errStr := util.GetInt64(yyDollar[3].item) if errStr != "" { @@ -27104,68 +27233,68 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1491: + case 1500: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.DiffOutputOpt -//line mysql_sql.y:10393 +//line mysql_sql.y:10441 { yyLOCAL = &tree.DiffOutputOpt{ Count: true, } } yyVAL.union = yyLOCAL - case 1492: + case 1501: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.DiffOutputOpt -//line mysql_sql.y:10399 +//line mysql_sql.y:10447 { yyLOCAL = &tree.DiffOutputOpt{ Summary: true, } } yyVAL.union = yyLOCAL - case 1493: + case 1502: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.ConflictOpt -//line mysql_sql.y:10407 +//line mysql_sql.y:10455 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1494: + case 1503: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ConflictOpt -//line mysql_sql.y:10411 +//line mysql_sql.y:10459 { yyLOCAL = &tree.ConflictOpt{ Opt: tree.CONFLICT_FAIL, } } yyVAL.union = yyLOCAL - case 1495: + case 1504: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ConflictOpt -//line mysql_sql.y:10417 +//line mysql_sql.y:10465 { yyLOCAL = &tree.ConflictOpt{ Opt: tree.CONFLICT_SKIP, } } yyVAL.union = yyLOCAL - case 1496: + case 1505: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ConflictOpt -//line mysql_sql.y:10423 +//line mysql_sql.y:10471 { yyLOCAL = &tree.ConflictOpt{ Opt: tree.CONFLICT_ACCEPT, } } yyVAL.union = yyLOCAL - case 1497: + case 1506: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.PickKeys -//line mysql_sql.y:10431 +//line mysql_sql.y:10479 { yyLOCAL = &tree.PickKeys{ Type: tree.PickKeysValues, @@ -27173,10 +27302,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1498: + case 1507: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.PickKeys -//line mysql_sql.y:10438 +//line mysql_sql.y:10486 { yyLOCAL = &tree.PickKeys{ Type: tree.PickKeysSubquery, @@ -27184,74 +27313,74 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1499: + case 1508: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.ToAccountOpt -//line mysql_sql.y:10447 +//line mysql_sql.y:10495 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1500: + case 1509: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ToAccountOpt -//line mysql_sql.y:10451 +//line mysql_sql.y:10499 { yyLOCAL = &tree.ToAccountOpt{ AccountName: tree.Identifier(yyDollar[3].cstrUnion().Compare()), } } yyVAL.union = yyLOCAL - case 1501: + case 1510: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10459 +//line mysql_sql.y:10507 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1502: + case 1511: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10463 +//line mysql_sql.y:10511 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1503: + case 1512: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:10468 +//line mysql_sql.y:10516 { yyVAL.str = "" } - case 1504: + case 1513: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:10469 +//line mysql_sql.y:10517 { yyVAL.str = "ignore" } - case 1505: + case 1514: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:10470 +//line mysql_sql.y:10518 { yyVAL.str = "replace" } - case 1506: + case 1515: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:10473 +//line mysql_sql.y:10521 { yyVAL.str = "ignore" } - case 1507: + case 1516: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:10474 +//line mysql_sql.y:10522 { yyVAL.str = "replace" } - case 1508: + case 1517: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10478 +//line mysql_sql.y:10526 { t := tree.NewCreateTable() t.Temporary = yyDollar[2].boolValUnion() @@ -27264,10 +27393,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1509: + case 1518: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10490 +//line mysql_sql.y:10538 { t := tree.NewCreateTable() t.IfNotExists = yyDollar[4].ifNotExistsUnion() @@ -27277,10 +27406,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1510: + case 1519: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10499 +//line mysql_sql.y:10547 { t := tree.NewCreateTable() t.IfNotExists = yyDollar[4].ifNotExistsUnion() @@ -27290,10 +27419,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1511: + case 1520: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10508 +//line mysql_sql.y:10556 { t := tree.NewCreateTable() t.IfNotExists = yyDollar[4].ifNotExistsUnion() @@ -27303,10 +27432,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1512: + case 1521: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10517 +//line mysql_sql.y:10565 { t := tree.NewCreateTable() t.IfNotExists = yyDollar[4].ifNotExistsUnion() @@ -27316,10 +27445,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1513: + case 1522: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10526 +//line mysql_sql.y:10574 { t := tree.NewCreateTable() t.IfNotExists = yyDollar[4].ifNotExistsUnion() @@ -27329,10 +27458,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1514: + case 1523: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10535 +//line mysql_sql.y:10583 { t := tree.NewCreateTable() t.IfNotExists = yyDollar[4].ifNotExistsUnion() @@ -27342,10 +27471,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1515: + case 1524: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10544 +//line mysql_sql.y:10592 { t := tree.NewCreateTable() t.IfNotExists = yyDollar[4].ifNotExistsUnion() @@ -27354,10 +27483,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1516: + case 1525: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10552 +//line mysql_sql.y:10600 { t := tree.NewCreateTable() t.IsClusterTable = true @@ -27370,10 +27499,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1517: + case 1526: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10564 +//line mysql_sql.y:10612 { if intoErr := tree.ValidateSelectIntoNotAllowed(yyDollar[6].selectUnion()); intoErr != "" { yylex.Error(intoErr) @@ -27388,10 +27517,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1518: + case 1527: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10578 +//line mysql_sql.y:10626 { if intoErr := tree.ValidateSelectIntoNotAllowed(yyDollar[9].selectUnion()); intoErr != "" { yylex.Error(intoErr) @@ -27407,10 +27536,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1519: + case 1528: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10593 +//line mysql_sql.y:10641 { if intoErr := tree.ValidateSelectIntoNotAllowed(yyDollar[7].selectUnion()); intoErr != "" { yylex.Error(intoErr) @@ -27426,10 +27555,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1520: + case 1529: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10598 +//line mysql_sql.y:10646 { if intoErr := tree.ValidateSelectIntoNotAllowed(yyDollar[10].selectUnion()); intoErr != "" { yylex.Error(intoErr) @@ -27446,10 +27575,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1521: + case 1530: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10603 +//line mysql_sql.y:10651 { if intoErr := tree.ValidateSelectIntoNotAllowed(yyDollar[8].selectUnion()); intoErr != "" { yylex.Error(intoErr) @@ -27465,10 +27594,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1522: + case 1531: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10608 +//line mysql_sql.y:10656 { if intoErr := tree.ValidateSelectIntoNotAllowed(yyDollar[11].selectUnion()); intoErr != "" { yylex.Error(intoErr) @@ -27485,10 +27614,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1523: + case 1532: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10613 +//line mysql_sql.y:10661 { t := tree.NewCreateTable() t.IsAsLike = true @@ -27499,10 +27628,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1524: + case 1533: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10623 +//line mysql_sql.y:10671 { t := tree.NewCreateTable() t.Temporary = yyDollar[2].boolValUnion() @@ -27512,10 +27641,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1525: + case 1534: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10632 +//line mysql_sql.y:10680 { t := tree.NewCloneTable() t.CreateTable.Temporary = yyDollar[2].boolValUnion() @@ -27529,10 +27658,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1526: + case 1535: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10645 +//line mysql_sql.y:10693 { var TableName = yyDollar[5].tableNameUnion() var FromUri = yyDollar[7].str @@ -27556,19 +27685,19 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1527: + case 1536: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.ExternParam -//line mysql_sql.y:10670 +//line mysql_sql.y:10718 { yyLOCAL = yyDollar[1].loadParamUnion() yyLOCAL.Tail = yyDollar[2].tailParamUnion() } yyVAL.union = yyLOCAL - case 1528: + case 1537: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.ExternParam -//line mysql_sql.y:10677 +//line mysql_sql.y:10725 { yyLOCAL = &tree.ExternParam{ ExParamConst: tree.ExParamConst{ @@ -27579,10 +27708,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1529: + case 1538: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL *tree.ExternParam -//line mysql_sql.y:10687 +//line mysql_sql.y:10735 { yyLOCAL = &tree.ExternParam{ ExParamConst: tree.ExParamConst{ @@ -27596,10 +27725,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1530: + case 1539: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.ExternParam -//line mysql_sql.y:10700 +//line mysql_sql.y:10748 { yyLOCAL = &tree.ExternParam{ ExParamConst: tree.ExParamConst{ @@ -27608,10 +27737,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1531: + case 1540: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.ExternParam -//line mysql_sql.y:10708 +//line mysql_sql.y:10756 { yyLOCAL = &tree.ExternParam{ ExParamConst: tree.ExParamConst{ @@ -27621,10 +27750,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1532: + case 1541: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ExternParam -//line mysql_sql.y:10717 +//line mysql_sql.y:10765 { yyLOCAL = &tree.ExternParam{ ExParamConst: tree.ExParamConst{ @@ -27633,55 +27762,55 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1533: + case 1542: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:10726 +//line mysql_sql.y:10774 { yyVAL.str = "" } - case 1534: + case 1543: yyDollar = yyS[yypt-4 : yypt+1] -//line mysql_sql.y:10730 +//line mysql_sql.y:10778 { yyVAL.str = yyDollar[4].str } - case 1535: + case 1544: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:10736 +//line mysql_sql.y:10784 { yyLOCAL = yyDollar[1].strsUnion() } yyVAL.union = yyLOCAL - case 1536: + case 1545: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:10740 +//line mysql_sql.y:10788 { yyLOCAL = append(yyDollar[1].strsUnion(), yyDollar[3].strsUnion()...) } yyVAL.union = yyLOCAL - case 1537: + case 1546: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:10745 +//line mysql_sql.y:10793 { yyLOCAL = []string{} } yyVAL.union = yyLOCAL - case 1538: + case 1547: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:10749 +//line mysql_sql.y:10797 { yyLOCAL = append(yyLOCAL, yyDollar[1].str) yyLOCAL = append(yyLOCAL, yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1539: + case 1548: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.TailParameter -//line mysql_sql.y:10756 +//line mysql_sql.y:10804 { yyLOCAL = &tree.TailParameter{ Charset: yyDollar[1].str, @@ -27693,22 +27822,22 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1540: + case 1549: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:10768 +//line mysql_sql.y:10816 { yyVAL.str = "" } - case 1541: + case 1550: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:10772 +//line mysql_sql.y:10820 { yyVAL.str = yyDollar[2].str } - case 1542: + case 1551: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:10778 +//line mysql_sql.y:10826 { var Name = yyDollar[4].tableNameUnion() var Type = yyDollar[5].columnTypeUnion() @@ -27730,10 +27859,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1543: + case 1552: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10799 +//line mysql_sql.y:10847 { locale := "" fstr := "bigint" @@ -27748,44 +27877,44 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1544: + case 1553: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10813 +//line mysql_sql.y:10861 { yyLOCAL = yyDollar[2].columnTypeUnion() } yyVAL.union = yyLOCAL - case 1545: + case 1554: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.TypeOption -//line mysql_sql.y:10817 +//line mysql_sql.y:10865 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1546: + case 1555: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.TypeOption -//line mysql_sql.y:10821 +//line mysql_sql.y:10869 { yyLOCAL = &tree.TypeOption{ Type: yyDollar[2].columnTypeUnion(), } } yyVAL.union = yyLOCAL - case 1547: + case 1556: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.IncrementByOption -//line mysql_sql.y:10827 +//line mysql_sql.y:10875 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1548: + case 1557: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IncrementByOption -//line mysql_sql.y:10831 +//line mysql_sql.y:10879 { yyLOCAL = &tree.IncrementByOption{ Minus: false, @@ -27793,10 +27922,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1549: + case 1558: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.IncrementByOption -//line mysql_sql.y:10838 +//line mysql_sql.y:10886 { yyLOCAL = &tree.IncrementByOption{ Minus: false, @@ -27804,10 +27933,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1550: + case 1559: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.IncrementByOption -//line mysql_sql.y:10845 +//line mysql_sql.y:10893 { yyLOCAL = &tree.IncrementByOption{ Minus: true, @@ -27815,10 +27944,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1551: + case 1560: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IncrementByOption -//line mysql_sql.y:10852 +//line mysql_sql.y:10900 { yyLOCAL = &tree.IncrementByOption{ Minus: true, @@ -27826,42 +27955,42 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1552: + case 1561: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10859 +//line mysql_sql.y:10907 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1553: + case 1562: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10863 +//line mysql_sql.y:10911 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1554: + case 1563: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10867 +//line mysql_sql.y:10915 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1555: + case 1564: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.MinValueOption -//line mysql_sql.y:10871 +//line mysql_sql.y:10919 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1556: + case 1565: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.MinValueOption -//line mysql_sql.y:10875 +//line mysql_sql.y:10923 { yyLOCAL = &tree.MinValueOption{ Minus: false, @@ -27869,10 +27998,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1557: + case 1566: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.MinValueOption -//line mysql_sql.y:10882 +//line mysql_sql.y:10930 { yyLOCAL = &tree.MinValueOption{ Minus: true, @@ -27880,18 +28009,18 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1558: + case 1567: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.MaxValueOption -//line mysql_sql.y:10889 +//line mysql_sql.y:10937 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1559: + case 1568: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.MaxValueOption -//line mysql_sql.y:10893 +//line mysql_sql.y:10941 { yyLOCAL = &tree.MaxValueOption{ Minus: false, @@ -27899,10 +28028,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1560: + case 1569: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.MaxValueOption -//line mysql_sql.y:10900 +//line mysql_sql.y:10948 { yyLOCAL = &tree.MaxValueOption{ Minus: true, @@ -27910,46 +28039,46 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1561: + case 1570: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.CycleOption -//line mysql_sql.y:10907 +//line mysql_sql.y:10955 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1562: + case 1571: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.CycleOption -//line mysql_sql.y:10911 +//line mysql_sql.y:10959 { yyLOCAL = &tree.CycleOption{ Cycle: false, } } yyVAL.union = yyLOCAL - case 1563: + case 1572: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CycleOption -//line mysql_sql.y:10917 +//line mysql_sql.y:10965 { yyLOCAL = &tree.CycleOption{ Cycle: true, } } yyVAL.union = yyLOCAL - case 1564: + case 1573: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.StartWithOption -//line mysql_sql.y:10923 +//line mysql_sql.y:10971 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1565: + case 1574: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.StartWithOption -//line mysql_sql.y:10927 +//line mysql_sql.y:10975 { yyLOCAL = &tree.StartWithOption{ Minus: false, @@ -27957,10 +28086,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1566: + case 1575: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.StartWithOption -//line mysql_sql.y:10934 +//line mysql_sql.y:10982 { yyLOCAL = &tree.StartWithOption{ Minus: false, @@ -27968,10 +28097,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1567: + case 1576: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.StartWithOption -//line mysql_sql.y:10941 +//line mysql_sql.y:10989 { yyLOCAL = &tree.StartWithOption{ Minus: true, @@ -27979,10 +28108,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1568: + case 1577: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.StartWithOption -//line mysql_sql.y:10948 +//line mysql_sql.y:10996 { yyLOCAL = &tree.StartWithOption{ Minus: true, @@ -27990,58 +28119,58 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1569: + case 1578: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10955 +//line mysql_sql.y:11003 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1570: + case 1579: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10959 +//line mysql_sql.y:11007 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1571: + case 1580: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10964 +//line mysql_sql.y:11012 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1572: + case 1581: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10968 +//line mysql_sql.y:11016 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1573: + case 1582: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:10972 +//line mysql_sql.y:11020 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1574: + case 1583: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.PartitionOption -//line mysql_sql.y:10977 +//line mysql_sql.y:11025 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1575: + case 1584: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.PartitionOption -//line mysql_sql.y:10981 +//line mysql_sql.y:11029 { yyDollar[3].partitionByUnion().Num = uint64(yyDollar[4].int64ValUnion()) var PartBy = yyDollar[3].partitionByUnion() @@ -28054,18 +28183,18 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1576: + case 1585: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.ClusterByOption -//line mysql_sql.y:10994 +//line mysql_sql.y:11042 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1577: + case 1586: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ClusterByOption -//line mysql_sql.y:10998 +//line mysql_sql.y:11046 { var ColumnList = []*tree.UnresolvedName{yyDollar[3].unresolvedNameUnion()} yyLOCAL = tree.NewClusterByOption( @@ -28074,10 +28203,10 @@ yydefault: } yyVAL.union = yyLOCAL - case 1578: + case 1587: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.ClusterByOption -//line mysql_sql.y:11006 +//line mysql_sql.y:11054 { var ColumnList = yyDollar[4].unresolveNamesUnion() yyLOCAL = tree.NewClusterByOption( @@ -28085,18 +28214,18 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1579: + case 1588: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:11014 +//line mysql_sql.y:11062 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1580: + case 1589: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:11018 +//line mysql_sql.y:11066 { var IsSubPartition = true var PType = yyDollar[3].partitionByUnion().PType @@ -28110,42 +28239,42 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1581: + case 1590: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*tree.Partition -//line mysql_sql.y:11032 +//line mysql_sql.y:11080 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1582: + case 1591: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.Partition -//line mysql_sql.y:11036 +//line mysql_sql.y:11084 { yyLOCAL = yyDollar[2].partitionsUnion() } yyVAL.union = yyLOCAL - case 1583: + case 1592: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.Partition -//line mysql_sql.y:11042 +//line mysql_sql.y:11090 { yyLOCAL = []*tree.Partition{yyDollar[1].partitionUnion()} } yyVAL.union = yyLOCAL - case 1584: + case 1593: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.Partition -//line mysql_sql.y:11046 +//line mysql_sql.y:11094 { yyLOCAL = append(yyDollar[1].partitionsUnion(), yyDollar[3].partitionUnion()) } yyVAL.union = yyLOCAL - case 1585: + case 1594: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Partition -//line mysql_sql.y:11052 +//line mysql_sql.y:11100 { var Name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) var Values = yyDollar[3].valuesUnion() @@ -28159,10 +28288,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1586: + case 1595: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.Partition -//line mysql_sql.y:11065 +//line mysql_sql.y:11113 { var Name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) var Values = yyDollar[3].valuesUnion() @@ -28176,42 +28305,42 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1587: + case 1596: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*tree.SubPartition -//line mysql_sql.y:11079 +//line mysql_sql.y:11127 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1588: + case 1597: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.SubPartition -//line mysql_sql.y:11083 +//line mysql_sql.y:11131 { yyLOCAL = yyDollar[2].subPartitionsUnion() } yyVAL.union = yyLOCAL - case 1589: + case 1598: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.SubPartition -//line mysql_sql.y:11089 +//line mysql_sql.y:11137 { yyLOCAL = []*tree.SubPartition{yyDollar[1].subPartitionUnion()} } yyVAL.union = yyLOCAL - case 1590: + case 1599: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.SubPartition -//line mysql_sql.y:11093 +//line mysql_sql.y:11141 { yyLOCAL = append(yyDollar[1].subPartitionsUnion(), yyDollar[3].subPartitionUnion()) } yyVAL.union = yyLOCAL - case 1591: + case 1600: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.SubPartition -//line mysql_sql.y:11099 +//line mysql_sql.y:11147 { var Name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) var Options []tree.TableOption @@ -28221,10 +28350,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1592: + case 1601: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.SubPartition -//line mysql_sql.y:11108 +//line mysql_sql.y:11156 { var Name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) var Options = yyDollar[3].tableOptionsUnion() @@ -28234,26 +28363,26 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1593: + case 1602: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:11119 +//line mysql_sql.y:11167 { yyLOCAL = []tree.TableOption{yyDollar[1].tableOptionUnion()} } yyVAL.union = yyLOCAL - case 1594: + case 1603: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:11123 +//line mysql_sql.y:11171 { yyLOCAL = append(yyDollar[1].tableOptionsUnion(), yyDollar[2].tableOptionUnion()) } yyVAL.union = yyLOCAL - case 1595: + case 1604: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11129 +//line mysql_sql.y:11177 { if option, ok := yyDollar[1].tableOptionUnion().(*tree.TableOptionAutoIDCache); ok { option.Free() @@ -28263,37 +28392,37 @@ yydefault: yyLOCAL = yyDollar[1].tableOptionUnion() } yyVAL.union = yyLOCAL - case 1596: + case 1605: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Values -//line mysql_sql.y:11139 +//line mysql_sql.y:11187 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1597: + case 1606: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Values -//line mysql_sql.y:11143 +//line mysql_sql.y:11191 { expr := tree.NewMaxValue() var valueList = tree.Exprs{expr} yyLOCAL = tree.NewValuesLessThan(valueList) } yyVAL.union = yyLOCAL - case 1598: + case 1607: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Values -//line mysql_sql.y:11149 +//line mysql_sql.y:11197 { var valueList = yyDollar[5].exprsUnion() yyLOCAL = tree.NewValuesLessThan(valueList) } yyVAL.union = yyLOCAL - case 1599: + case 1608: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Values -//line mysql_sql.y:11154 +//line mysql_sql.y:11202 { var valueList = yyDollar[4].exprsUnion() yyLOCAL = tree.NewValuesIn( @@ -28301,18 +28430,18 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1600: + case 1609: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:11162 +//line mysql_sql.y:11210 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 1601: + case 1610: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:11166 +//line mysql_sql.y:11214 { res := yyDollar[2].item.(int64) if res == 0 { @@ -28322,18 +28451,18 @@ yydefault: yyLOCAL = res } yyVAL.union = yyLOCAL - case 1602: + case 1611: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:11176 +//line mysql_sql.y:11224 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 1603: + case 1612: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:11180 +//line mysql_sql.y:11228 { res := yyDollar[2].item.(int64) if res == 0 { @@ -28343,10 +28472,10 @@ yydefault: yyLOCAL = res } yyVAL.union = yyLOCAL - case 1604: + case 1613: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:11191 +//line mysql_sql.y:11239 { rangeTyp := tree.NewRangeType() rangeTyp.Expr = yyDollar[3].exprUnion() @@ -28355,10 +28484,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1605: + case 1614: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:11199 +//line mysql_sql.y:11247 { rangeTyp := tree.NewRangeType() rangeTyp.ColumnList = yyDollar[4].unresolveNamesUnion() @@ -28367,10 +28496,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1606: + case 1615: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:11207 +//line mysql_sql.y:11255 { listTyp := tree.NewListType() listTyp.Expr = yyDollar[3].exprUnion() @@ -28379,10 +28508,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1607: + case 1616: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:11215 +//line mysql_sql.y:11263 { listTyp := tree.NewListType() listTyp.ColumnList = yyDollar[4].unresolveNamesUnion() @@ -28391,10 +28520,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1609: + case 1618: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:11226 +//line mysql_sql.y:11274 { keyTyp := tree.NewKeyType() keyTyp.Linear = yyDollar[1].boolValUnion() @@ -28404,10 +28533,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1610: + case 1619: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:11235 +//line mysql_sql.y:11283 { keyTyp := tree.NewKeyType() keyTyp.Linear = yyDollar[1].boolValUnion() @@ -28418,10 +28547,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1611: + case 1620: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:11245 +//line mysql_sql.y:11293 { Linear := yyDollar[1].boolValUnion() Expr := yyDollar[4].exprUnion() @@ -28431,728 +28560,728 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1612: + case 1621: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:11255 +//line mysql_sql.y:11303 { yyLOCAL = 2 } yyVAL.union = yyLOCAL - case 1613: + case 1622: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:11259 +//line mysql_sql.y:11307 { yyLOCAL = yyDollar[3].item.(int64) } yyVAL.union = yyLOCAL - case 1614: + case 1623: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:11264 +//line mysql_sql.y:11312 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1615: + case 1624: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:11268 +//line mysql_sql.y:11316 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1616: + case 1625: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.IcebergTableParam -//line mysql_sql.y:11274 +//line mysql_sql.y:11322 { yyLOCAL = tree.NewIcebergTableParam(yyDollar[4].icebergOptionsUnion()) } yyVAL.union = yyLOCAL - case 1617: + case 1626: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.IcebergOptions -//line mysql_sql.y:11279 +//line mysql_sql.y:11327 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1618: + case 1627: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.IcebergOptions -//line mysql_sql.y:11283 +//line mysql_sql.y:11331 { yyLOCAL = yyDollar[3].icebergOptionsUnion() } yyVAL.union = yyLOCAL - case 1619: + case 1628: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.IcebergOptions -//line mysql_sql.y:11289 +//line mysql_sql.y:11337 { yyLOCAL = tree.IcebergOptions{yyDollar[1].icebergOptionUnion()} } yyVAL.union = yyLOCAL - case 1620: + case 1629: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.IcebergOptions -//line mysql_sql.y:11293 +//line mysql_sql.y:11341 { yyLOCAL = append(yyDollar[1].icebergOptionsUnion(), yyDollar[3].icebergOptionUnion()) } yyVAL.union = yyLOCAL - case 1621: + case 1630: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IcebergOption -//line mysql_sql.y:11299 +//line mysql_sql.y:11347 { yyLOCAL = tree.NewIcebergOption(tree.Identifier(yyDollar[1].str), yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1622: + case 1631: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:11305 +//line mysql_sql.y:11353 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } - case 1623: + case 1632: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:11309 +//line mysql_sql.y:11357 { yyVAL.str = yyDollar[1].str } - case 1624: + case 1633: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:11315 +//line mysql_sql.y:11363 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } - case 1625: + case 1634: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:11319 +//line mysql_sql.y:11367 { yyVAL.str = yyDollar[1].str } - case 1626: + case 1635: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.MongoDBTableParam -//line mysql_sql.y:11325 +//line mysql_sql.y:11373 { yyLOCAL = tree.NewMongoDBTableParam(yyDollar[4].mongodbOptionsUnion()) } yyVAL.union = yyLOCAL - case 1627: + case 1636: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.MongoDBOptions -//line mysql_sql.y:11330 +//line mysql_sql.y:11378 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1628: + case 1637: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.MongoDBOptions -//line mysql_sql.y:11334 +//line mysql_sql.y:11382 { yyLOCAL = yyDollar[3].mongodbOptionsUnion() } yyVAL.union = yyLOCAL - case 1629: + case 1638: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.MongoDBOptions -//line mysql_sql.y:11340 +//line mysql_sql.y:11388 { yyLOCAL = tree.MongoDBOptions{yyDollar[1].mongodbOptionUnion()} } yyVAL.union = yyLOCAL - case 1630: + case 1639: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.MongoDBOptions -//line mysql_sql.y:11344 +//line mysql_sql.y:11392 { yyLOCAL = append(yyDollar[1].mongodbOptionsUnion(), yyDollar[3].mongodbOptionUnion()) } yyVAL.union = yyLOCAL - case 1631: + case 1640: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.MongoDBOption -//line mysql_sql.y:11350 +//line mysql_sql.y:11398 { yyLOCAL = tree.NewMongoDBOption(tree.Identifier(yyDollar[1].str), yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1632: + case 1641: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:11356 +//line mysql_sql.y:11404 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } - case 1633: + case 1642: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:11360 +//line mysql_sql.y:11408 { yyVAL.str = yyDollar[1].str } - case 1634: + case 1643: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:11366 +//line mysql_sql.y:11414 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } - case 1635: + case 1644: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:11370 +//line mysql_sql.y:11418 { yyVAL.str = yyDollar[1].str } - case 1636: + case 1645: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.DataStreamTableParam -//line mysql_sql.y:11376 +//line mysql_sql.y:11424 { yyLOCAL = tree.NewDataStreamTableParam(yyDollar[4].datastreamOptionsUnion()) } yyVAL.union = yyLOCAL - case 1637: + case 1646: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.DataStreamOptions -//line mysql_sql.y:11381 +//line mysql_sql.y:11429 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1638: + case 1647: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.DataStreamOptions -//line mysql_sql.y:11385 +//line mysql_sql.y:11433 { yyLOCAL = yyDollar[3].datastreamOptionsUnion() } yyVAL.union = yyLOCAL - case 1639: + case 1648: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.DataStreamOptions -//line mysql_sql.y:11391 +//line mysql_sql.y:11439 { yyLOCAL = tree.DataStreamOptions{yyDollar[1].datastreamOptionUnion()} } yyVAL.union = yyLOCAL - case 1640: + case 1649: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.DataStreamOptions -//line mysql_sql.y:11395 +//line mysql_sql.y:11443 { yyLOCAL = append(yyDollar[1].datastreamOptionsUnion(), yyDollar[3].datastreamOptionUnion()) } yyVAL.union = yyLOCAL - case 1641: + case 1650: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.DataStreamOption -//line mysql_sql.y:11401 +//line mysql_sql.y:11449 { yyLOCAL = tree.NewDataStreamOption(tree.Identifier(yyDollar[1].str), yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1642: + case 1651: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.ForeignTableParam -//line mysql_sql.y:11407 +//line mysql_sql.y:11455 { yyLOCAL = tree.NewForeignTableParam(yyDollar[3].str, yyDollar[4].foreignTableOptionsUnion()) } yyVAL.union = yyLOCAL - case 1643: + case 1652: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.KafkaTableParam -//line mysql_sql.y:11413 +//line mysql_sql.y:11461 { yyLOCAL = tree.NewKafkaTableParam(yyDollar[4].kafkaTableOptionsUnion()) } yyVAL.union = yyLOCAL - case 1644: + case 1653: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.KafkaTableOptions -//line mysql_sql.y:11418 +//line mysql_sql.y:11466 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1645: + case 1654: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.KafkaTableOptions -//line mysql_sql.y:11422 +//line mysql_sql.y:11470 { yyLOCAL = yyDollar[3].kafkaTableOptionsUnion() } yyVAL.union = yyLOCAL - case 1646: + case 1655: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.KafkaTableOptions -//line mysql_sql.y:11428 +//line mysql_sql.y:11476 { yyLOCAL = tree.KafkaTableOptions{yyDollar[1].kafkaTableOptionUnion()} } yyVAL.union = yyLOCAL - case 1647: + case 1656: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.KafkaTableOptions -//line mysql_sql.y:11432 +//line mysql_sql.y:11480 { yyLOCAL = append(yyDollar[1].kafkaTableOptionsUnion(), yyDollar[3].kafkaTableOptionUnion()) } yyVAL.union = yyLOCAL - case 1648: + case 1657: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.KafkaTableOption -//line mysql_sql.y:11438 +//line mysql_sql.y:11486 { yyLOCAL = tree.NewKafkaTableOption(tree.Identifier(yyDollar[1].str), yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1649: + case 1658: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:11444 +//line mysql_sql.y:11492 { yyVAL.str = "esql" } - case 1650: + case 1659: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:11448 +//line mysql_sql.y:11496 { yyVAL.str = "sql" } - case 1651: + case 1660: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.ForeignTableOptions -//line mysql_sql.y:11453 +//line mysql_sql.y:11501 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1652: + case 1661: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.ForeignTableOptions -//line mysql_sql.y:11457 +//line mysql_sql.y:11505 { yyLOCAL = yyDollar[3].foreignTableOptionsUnion() } yyVAL.union = yyLOCAL - case 1653: + case 1662: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ForeignTableOptions -//line mysql_sql.y:11463 +//line mysql_sql.y:11511 { yyLOCAL = tree.ForeignTableOptions{yyDollar[1].foreignTableOptionUnion()} } yyVAL.union = yyLOCAL - case 1654: + case 1663: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.ForeignTableOptions -//line mysql_sql.y:11467 +//line mysql_sql.y:11515 { yyLOCAL = append(yyDollar[1].foreignTableOptionsUnion(), yyDollar[3].foreignTableOptionUnion()) } yyVAL.union = yyLOCAL - case 1655: + case 1664: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.ForeignTableOption -//line mysql_sql.y:11473 +//line mysql_sql.y:11521 { yyLOCAL = tree.NewForeignTableOption(tree.Identifier(yyDollar[1].str), yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1656: + case 1665: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:11479 +//line mysql_sql.y:11527 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } - case 1657: + case 1666: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:11483 +//line mysql_sql.y:11531 { yyVAL.str = yyDollar[1].str } - case 1658: + case 1667: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:11489 +//line mysql_sql.y:11537 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } - case 1659: + case 1668: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:11493 +//line mysql_sql.y:11541 { yyVAL.str = yyDollar[1].str } - case 1660: + case 1669: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:11498 +//line mysql_sql.y:11546 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1661: + case 1670: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:11502 +//line mysql_sql.y:11550 { yyLOCAL = yyDollar[1].tableOptionsUnion() } yyVAL.union = yyLOCAL - case 1662: + case 1671: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:11508 +//line mysql_sql.y:11556 { yyLOCAL = []tree.TableOption{yyDollar[1].tableOptionUnion()} } yyVAL.union = yyLOCAL - case 1663: + case 1672: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:11512 +//line mysql_sql.y:11560 { yyLOCAL = append(yyDollar[1].tableOptionsUnion(), yyDollar[3].tableOptionUnion()) } yyVAL.union = yyLOCAL - case 1664: + case 1673: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:11516 +//line mysql_sql.y:11564 { yyLOCAL = append(yyDollar[1].tableOptionsUnion(), yyDollar[2].tableOptionUnion()) } yyVAL.union = yyLOCAL - case 1665: + case 1674: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11522 +//line mysql_sql.y:11570 { yyLOCAL = tree.NewTableOptionAUTOEXTEND_SIZE(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1666: + case 1675: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11526 +//line mysql_sql.y:11574 { yyLOCAL = tree.NewTableOptionAutoIncrement(integralToUint64(yyDollar[3].item)) } yyVAL.union = yyLOCAL - case 1667: + case 1676: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11530 +//line mysql_sql.y:11578 { yyLOCAL = tree.NewTableOptionAutoIDCache(integralToUint64(yyDollar[3].item)) } yyVAL.union = yyLOCAL - case 1668: + case 1677: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11534 +//line mysql_sql.y:11582 { yyLOCAL = tree.NewTableOptionAvgRowLength(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1669: + case 1678: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11538 +//line mysql_sql.y:11586 { yyLOCAL = tree.NewTableOptionCharset(yyDollar[4].str) } yyVAL.union = yyLOCAL - case 1670: + case 1679: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11542 +//line mysql_sql.y:11590 { yyLOCAL = tree.NewTableOptionCollate(yyDollar[4].str) } yyVAL.union = yyLOCAL - case 1671: + case 1680: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11546 +//line mysql_sql.y:11594 { yyLOCAL = tree.NewTableOptionChecksum(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1672: + case 1681: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11550 +//line mysql_sql.y:11598 { str := util.DealCommentString(yyDollar[3].str) yyLOCAL = tree.NewTableOptionComment(str) } yyVAL.union = yyLOCAL - case 1673: + case 1682: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11555 +//line mysql_sql.y:11603 { yyLOCAL = tree.NewTableOptionCompression(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1674: + case 1683: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11559 +//line mysql_sql.y:11607 { yyLOCAL = tree.NewTableOptionConnection(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1675: + case 1684: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11563 +//line mysql_sql.y:11611 { yyLOCAL = tree.NewTableOptionDataDirectory(yyDollar[4].str) } yyVAL.union = yyLOCAL - case 1676: + case 1685: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11567 +//line mysql_sql.y:11615 { yyLOCAL = tree.NewTableOptionIndexDirectory(yyDollar[4].str) } yyVAL.union = yyLOCAL - case 1677: + case 1686: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11571 +//line mysql_sql.y:11619 { yyLOCAL = tree.NewTableOptionDelayKeyWrite(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1678: + case 1687: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11575 +//line mysql_sql.y:11623 { yyLOCAL = tree.NewTableOptionEncryption(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1679: + case 1688: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11579 +//line mysql_sql.y:11627 { yyLOCAL = tree.NewTableOptionEngine(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1680: + case 1689: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11583 +//line mysql_sql.y:11631 { yyLOCAL = tree.NewTableOptionEngineAttr(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1681: + case 1690: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11587 +//line mysql_sql.y:11635 { yyLOCAL = tree.NewTableOptionInsertMethod(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1682: + case 1691: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11591 +//line mysql_sql.y:11639 { yyLOCAL = tree.NewTableOptionKeyBlockSize(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1683: + case 1692: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11595 +//line mysql_sql.y:11643 { yyLOCAL = tree.NewTableOptionMaxRows(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1684: + case 1693: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11599 +//line mysql_sql.y:11647 { yyLOCAL = tree.NewTableOptionMinRows(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1685: + case 1694: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11603 +//line mysql_sql.y:11651 { t := tree.NewTableOptionPackKeys() t.Value = yyDollar[3].item.(int64) yyLOCAL = t } yyVAL.union = yyLOCAL - case 1686: + case 1695: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11609 +//line mysql_sql.y:11657 { t := tree.NewTableOptionPackKeys() t.Default = true yyLOCAL = t } yyVAL.union = yyLOCAL - case 1687: + case 1696: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11615 +//line mysql_sql.y:11663 { yyLOCAL = tree.NewTableOptionPassword(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1688: + case 1697: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11619 +//line mysql_sql.y:11667 { yyLOCAL = tree.NewTableOptionRowFormat(yyDollar[3].rowFormatTypeUnion()) } yyVAL.union = yyLOCAL - case 1689: + case 1698: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11623 +//line mysql_sql.y:11671 { yyLOCAL = tree.NewTTableOptionStartTrans(true) } yyVAL.union = yyLOCAL - case 1690: + case 1699: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11627 +//line mysql_sql.y:11675 { yyLOCAL = tree.NewTTableOptionSecondaryEngineAttr(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1691: + case 1700: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11631 +//line mysql_sql.y:11679 { t := tree.NewTableOptionStatsAutoRecalc() t.Value = uint64(yyDollar[3].item.(int64)) yyLOCAL = t } yyVAL.union = yyLOCAL - case 1692: + case 1701: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11637 +//line mysql_sql.y:11685 { t := tree.NewTableOptionStatsAutoRecalc() t.Default = true yyLOCAL = t } yyVAL.union = yyLOCAL - case 1693: + case 1702: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11643 +//line mysql_sql.y:11691 { t := tree.NewTableOptionStatsPersistent() t.Value = uint64(yyDollar[3].item.(int64)) yyLOCAL = t } yyVAL.union = yyLOCAL - case 1694: + case 1703: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11649 +//line mysql_sql.y:11697 { t := tree.NewTableOptionStatsPersistent() t.Default = true yyLOCAL = t } yyVAL.union = yyLOCAL - case 1695: + case 1704: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11655 +//line mysql_sql.y:11703 { t := tree.NewTableOptionStatsSamplePages() t.Value = uint64(yyDollar[3].item.(int64)) yyLOCAL = t } yyVAL.union = yyLOCAL - case 1696: + case 1705: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11661 +//line mysql_sql.y:11709 { t := tree.NewTableOptionStatsSamplePages() t.Default = true yyLOCAL = t } yyVAL.union = yyLOCAL - case 1697: + case 1706: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11667 +//line mysql_sql.y:11715 { yyLOCAL = tree.NewTableOptionTablespace(yyDollar[3].cstrUnion().Compare(), "") } yyVAL.union = yyLOCAL - case 1698: + case 1707: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11671 +//line mysql_sql.y:11719 { yyLOCAL = tree.NewTableOptionTablespace("", yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1699: + case 1708: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11675 +//line mysql_sql.y:11723 { yyLOCAL = tree.NewTableOptionUnion(yyDollar[4].tableNamesUnion()) } yyVAL.union = yyLOCAL - case 1700: + case 1709: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:11679 +//line mysql_sql.y:11727 { var Preperties = yyDollar[3].propertiesUnion() yyLOCAL = tree.NewTableOptionProperties(Preperties) } yyVAL.union = yyLOCAL - case 1701: + case 1710: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.Property -//line mysql_sql.y:11686 +//line mysql_sql.y:11734 { yyLOCAL = []tree.Property{yyDollar[1].propertyUnion()} } yyVAL.union = yyLOCAL - case 1702: + case 1711: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.Property -//line mysql_sql.y:11690 +//line mysql_sql.y:11738 { yyLOCAL = append(yyDollar[1].propertiesUnion(), yyDollar[3].propertyUnion()) } yyVAL.union = yyLOCAL - case 1703: + case 1712: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Property -//line mysql_sql.y:11696 +//line mysql_sql.y:11744 { var Key = yyDollar[1].str var Value = yyDollar[3].str @@ -29162,86 +29291,86 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1704: + case 1713: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:11707 +//line mysql_sql.y:11755 { yyVAL.str = " " + yyDollar[1].str + " " + yyDollar[2].str } - case 1705: + case 1714: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:11711 +//line mysql_sql.y:11759 { yyVAL.str = " " + yyDollar[1].str + " " + yyDollar[2].str } - case 1706: + case 1715: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.RowFormatType -//line mysql_sql.y:11717 +//line mysql_sql.y:11765 { yyLOCAL = tree.ROW_FORMAT_DEFAULT } yyVAL.union = yyLOCAL - case 1707: + case 1716: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.RowFormatType -//line mysql_sql.y:11721 +//line mysql_sql.y:11769 { yyLOCAL = tree.ROW_FORMAT_DYNAMIC } yyVAL.union = yyLOCAL - case 1708: + case 1717: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.RowFormatType -//line mysql_sql.y:11725 +//line mysql_sql.y:11773 { yyLOCAL = tree.ROW_FORMAT_FIXED } yyVAL.union = yyLOCAL - case 1709: + case 1718: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.RowFormatType -//line mysql_sql.y:11729 +//line mysql_sql.y:11777 { yyLOCAL = tree.ROW_FORMAT_COMPRESSED } yyVAL.union = yyLOCAL - case 1710: + case 1719: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.RowFormatType -//line mysql_sql.y:11733 +//line mysql_sql.y:11781 { yyLOCAL = tree.ROW_FORMAT_REDUNDANT } yyVAL.union = yyLOCAL - case 1711: + case 1720: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.RowFormatType -//line mysql_sql.y:11737 +//line mysql_sql.y:11785 { yyLOCAL = tree.ROW_FORMAT_COMPACT } yyVAL.union = yyLOCAL - case 1716: + case 1725: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableNames -//line mysql_sql.y:11751 +//line mysql_sql.y:11799 { yyLOCAL = tree.TableNames{yyDollar[1].tableNameUnion()} } yyVAL.union = yyLOCAL - case 1717: + case 1726: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableNames -//line mysql_sql.y:11755 +//line mysql_sql.y:11803 { yyLOCAL = append(yyDollar[1].tableNamesUnion(), yyDollar[3].tableNameUnion()) } yyVAL.union = yyLOCAL - case 1718: + case 1727: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.TableName -//line mysql_sql.y:11764 +//line mysql_sql.y:11812 { tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) prefix := tree.ObjectNamePrefix{ExplicitSchema: false} @@ -29249,10 +29378,10 @@ yydefault: yyLOCAL.IcebergRef = yyDollar[3].icebergRefSpecUnion() } yyVAL.union = yyLOCAL - case 1719: + case 1728: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.TableName -//line mysql_sql.y:11771 +//line mysql_sql.y:11819 { dbName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[3].cstrUnion().Origin()) @@ -29261,85 +29390,85 @@ yydefault: yyLOCAL.IcebergRef = yyDollar[5].icebergRefSpecUnion() } yyVAL.union = yyLOCAL - case 1720: + case 1729: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.IcebergRefSpec -//line mysql_sql.y:11780 +//line mysql_sql.y:11828 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1721: + case 1730: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IcebergRefSpec -//line mysql_sql.y:11784 +//line mysql_sql.y:11832 { raw := fmt.Sprintf("%v", yyDollar[3].item) yyLOCAL = tree.NewIcebergSnapshotRef(tree.NewNumVal(raw, raw, false, tree.P_int64)) } yyVAL.union = yyLOCAL - case 1722: + case 1731: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IcebergRefSpec -//line mysql_sql.y:11789 +//line mysql_sql.y:11837 { yyLOCAL = tree.NewIcebergSnapshotRef(tree.NewNumVal(yyDollar[3].str, yyDollar[3].str, false, tree.P_char)) } yyVAL.union = yyLOCAL - case 1723: + case 1732: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.IcebergRefSpec -//line mysql_sql.y:11793 +//line mysql_sql.y:11841 { yyLOCAL = tree.NewIcebergTimestampRef(tree.NewNumVal(yyDollar[6].str, yyDollar[6].str, false, tree.P_char)) } yyVAL.union = yyLOCAL - case 1724: + case 1733: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.IcebergRefSpec -//line mysql_sql.y:11797 +//line mysql_sql.y:11845 { yyLOCAL = tree.NewIcebergTimestampRef(tree.NewNumVal(yyDollar[5].str, yyDollar[5].str, false, tree.P_char)) } yyVAL.union = yyLOCAL - case 1725: + case 1734: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IcebergRefSpec -//line mysql_sql.y:11801 +//line mysql_sql.y:11849 { yyLOCAL = tree.NewIcebergNamedRef(tree.Identifier(yyDollar[3].str)) } yyVAL.union = yyLOCAL - case 1726: + case 1735: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:11807 +//line mysql_sql.y:11855 { yyVAL.str = yyDollar[1].str } - case 1727: + case 1736: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:11811 +//line mysql_sql.y:11859 { yyVAL.str = yyDollar[1].str } - case 1728: + case 1737: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:11815 +//line mysql_sql.y:11863 { yyVAL.str = yyDollar[1].str } - case 1729: + case 1738: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.AtTimeStamp -//line mysql_sql.y:11820 +//line mysql_sql.y:11868 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1730: + case 1739: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.AtTimeStamp -//line mysql_sql.y:11824 +//line mysql_sql.y:11872 { yyLOCAL = &tree.AtTimeStamp{ Type: tree.ATTIMESTAMPTIME, @@ -29347,10 +29476,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1731: + case 1740: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.AtTimeStamp -//line mysql_sql.y:11831 +//line mysql_sql.y:11879 { var str = yyDollar[4].cstrUnion().Compare() yyLOCAL = &tree.AtTimeStamp{ @@ -29360,10 +29489,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1732: + case 1741: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.AtTimeStamp -//line mysql_sql.y:11840 +//line mysql_sql.y:11888 { yyLOCAL = &tree.AtTimeStamp{ Type: tree.ATTIMESTAMPSNAPSHOT, @@ -29372,10 +29501,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1733: + case 1742: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.AtTimeStamp -//line mysql_sql.y:11848 +//line mysql_sql.y:11896 { yyLOCAL = &tree.AtTimeStamp{ Type: tree.ATMOTIMESTAMP, @@ -29383,10 +29512,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1734: + case 1743: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.AtTimeStamp -//line mysql_sql.y:11855 +//line mysql_sql.y:11903 { yyLOCAL = &tree.AtTimeStamp{ Type: tree.ASOFTIMESTAMP, @@ -29394,74 +29523,74 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1735: + case 1744: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.TableDefs -//line mysql_sql.y:11863 +//line mysql_sql.y:11911 { yyLOCAL = tree.TableDefs(nil) } yyVAL.union = yyLOCAL - case 1737: + case 1746: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDefs -//line mysql_sql.y:11870 +//line mysql_sql.y:11918 { yyLOCAL = tree.TableDefs{yyDollar[1].tableDefUnion()} } yyVAL.union = yyLOCAL - case 1738: + case 1747: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableDefs -//line mysql_sql.y:11874 +//line mysql_sql.y:11922 { yyLOCAL = append(yyDollar[1].tableDefsUnion(), yyDollar[3].tableDefUnion()) } yyVAL.union = yyLOCAL - case 1739: + case 1748: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:11880 +//line mysql_sql.y:11928 { yyLOCAL = tree.TableDef(yyDollar[1].columnTableDefUnion()) } yyVAL.union = yyLOCAL - case 1740: + case 1749: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:11884 +//line mysql_sql.y:11932 { yyLOCAL = yyDollar[1].tableDefUnion() } yyVAL.union = yyLOCAL - case 1741: + case 1750: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:11888 +//line mysql_sql.y:11936 { yyLOCAL = yyDollar[1].tableDefUnion() } yyVAL.union = yyLOCAL - case 1742: + case 1751: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:11894 +//line mysql_sql.y:11942 { yyLOCAL = yyDollar[1].tableDefUnion() } yyVAL.union = yyLOCAL - case 1743: + case 1752: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:11898 +//line mysql_sql.y:11946 { yyLOCAL = yyDollar[1].tableDefUnion() } yyVAL.union = yyLOCAL - case 1744: + case 1753: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:11904 +//line mysql_sql.y:11952 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].str @@ -29475,10 +29604,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1745: + case 1754: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:11917 +//line mysql_sql.y:11965 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].str @@ -29492,10 +29621,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1746: + case 1755: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:11930 +//line mysql_sql.y:11978 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].str @@ -29511,10 +29640,10 @@ yydefault: yyLOCAL = fti } yyVAL.union = yyLOCAL - case 1747: + case 1756: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:11945 +//line mysql_sql.y:11993 { keyTyp := tree.INDEX_TYPE_INVALID if yyDollar[3].strsUnion()[1] != "" { @@ -29560,10 +29689,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1748: + case 1757: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:11990 +//line mysql_sql.y:12038 { keyTyp := tree.INDEX_TYPE_INVALID if yyDollar[3].strsUnion()[1] != "" { @@ -29608,10 +29737,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1749: + case 1758: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:12035 +//line mysql_sql.y:12083 { if yyDollar[1].str != "" { switch v := yyDollar[2].tableDefUnion().(type) { @@ -29628,18 +29757,18 @@ yydefault: yyLOCAL = yyDollar[2].tableDefUnion() } yyVAL.union = yyLOCAL - case 1750: + case 1759: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:12050 +//line mysql_sql.y:12098 { yyLOCAL = yyDollar[1].tableDefUnion() } yyVAL.union = yyLOCAL - case 1751: + case 1760: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:12056 +//line mysql_sql.y:12104 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].strsUnion()[0] @@ -29653,10 +29782,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1752: + case 1761: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:12069 +//line mysql_sql.y:12117 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].strsUnion()[0] @@ -29670,10 +29799,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1753: + case 1762: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:12082 +//line mysql_sql.y:12130 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].strsUnion()[0] @@ -29687,10 +29816,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1754: + case 1763: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:12095 +//line mysql_sql.y:12143 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].strsUnion()[0] @@ -29704,10 +29833,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1755: + case 1764: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:12108 +//line mysql_sql.y:12156 { var IfNotExists = yyDollar[3].ifNotExistsUnion() var KeyParts = yyDollar[6].keyPartsUnion() @@ -29723,10 +29852,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1756: + case 1765: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:12123 +//line mysql_sql.y:12171 { var Expr = yyDollar[3].exprUnion() var Enforced = yyDollar[5].boolValUnion() @@ -29736,107 +29865,107 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1757: + case 1766: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:12133 +//line mysql_sql.y:12181 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1759: + case 1768: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:12139 +//line mysql_sql.y:12187 { yyVAL.str = "" } - case 1760: + case 1769: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:12143 +//line mysql_sql.y:12191 { yyVAL.str = yyDollar[1].str } - case 1763: + case 1772: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:12153 +//line mysql_sql.y:12201 { yyLOCAL = make([]string, 2) yyLOCAL[0] = yyDollar[1].str yyLOCAL[1] = "" } yyVAL.union = yyLOCAL - case 1764: + case 1773: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:12159 +//line mysql_sql.y:12207 { yyLOCAL = make([]string, 2) yyLOCAL[0] = yyDollar[1].str yyLOCAL[1] = yyDollar[3].str } yyVAL.union = yyLOCAL - case 1765: + case 1774: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:12165 +//line mysql_sql.y:12213 { yyLOCAL = make([]string, 2) yyLOCAL[0] = yyDollar[1].cstrUnion().Origin() yyLOCAL[1] = yyDollar[3].str } yyVAL.union = yyLOCAL - case 1780: + case 1789: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:12190 +//line mysql_sql.y:12238 { yyVAL.str = "" } - case 1781: + case 1790: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:12194 +//line mysql_sql.y:12242 { yyVAL.str = yyDollar[1].cstrUnion().Origin() } - case 1782: + case 1791: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ColumnTableDef -//line mysql_sql.y:12200 +//line mysql_sql.y:12248 { yyLOCAL = tree.NewColumnTableDef(yyDollar[1].unresolvedNameUnion(), yyDollar[2].columnTypeUnion(), yyDollar[3].columnAttributesUnion()) } yyVAL.union = yyLOCAL - case 1783: + case 1792: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:12206 +//line mysql_sql.y:12254 { yyLOCAL = tree.NewUnresolvedName(yyDollar[1].cstrUnion()) } yyVAL.union = yyLOCAL - case 1784: + case 1793: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:12210 +//line mysql_sql.y:12258 { tblNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) yyLOCAL = tree.NewUnresolvedName(tblNameCStr, yyDollar[3].cstrUnion()) } yyVAL.union = yyLOCAL - case 1785: + case 1794: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:12215 +//line mysql_sql.y:12263 { 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 1786: + case 1795: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:12223 +//line mysql_sql.y:12271 { if rejectSQLModeReservedFunctionName(yylex, yyDollar[1].str) { goto ret1 @@ -29844,18 +29973,18 @@ yydefault: yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 1787: + case 1796: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:12227 +//line mysql_sql.y:12275 { yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 1788: + case 1797: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:12231 +//line mysql_sql.y:12279 { if rejectSQLModeReservedFunctionName(yylex, yyDollar[1].str) { goto ret1 @@ -29863,10 +29992,10 @@ yydefault: yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 1789: + case 1798: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:12235 +//line mysql_sql.y:12283 { if rejectSQLModeReservedFunctionName(yylex, yyDollar[1].str) { goto ret1 @@ -29874,222 +30003,222 @@ yydefault: yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 1790: + case 1799: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:12241 +//line mysql_sql.y:12289 { yyLOCAL = yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) } yyVAL.union = yyLOCAL - case 1791: + case 1800: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:12247 +//line mysql_sql.y:12295 { yyLOCAL = tree.NewUnresolvedName(yyDollar[1].cstrUnion()) } yyVAL.union = yyLOCAL - case 1792: + case 1801: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:12251 +//line mysql_sql.y:12299 { tblNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) yyLOCAL = tree.NewUnresolvedName(tblNameCStr, yyDollar[3].cstrUnion()) } yyVAL.union = yyLOCAL - case 1793: + case 1802: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:12256 +//line mysql_sql.y:12304 { 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 1794: + case 1803: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []tree.ColumnAttribute -//line mysql_sql.y:12263 +//line mysql_sql.y:12311 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1795: + case 1804: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.ColumnAttribute -//line mysql_sql.y:12267 +//line mysql_sql.y:12315 { yyLOCAL = yyDollar[1].columnAttributesUnion() } yyVAL.union = yyLOCAL - case 1796: + case 1805: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.ColumnAttribute -//line mysql_sql.y:12273 +//line mysql_sql.y:12321 { yyLOCAL = []tree.ColumnAttribute{yyDollar[1].columnAttributeUnion()} } yyVAL.union = yyLOCAL - case 1797: + case 1806: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []tree.ColumnAttribute -//line mysql_sql.y:12277 +//line mysql_sql.y:12325 { yyLOCAL = append(yyDollar[1].columnAttributesUnion(), yyDollar[2].columnAttributeUnion()) } yyVAL.union = yyLOCAL - case 1798: + case 1807: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12283 +//line mysql_sql.y:12331 { yyLOCAL = tree.NewAttributeNull(true) } yyVAL.union = yyLOCAL - case 1799: + case 1808: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12287 +//line mysql_sql.y:12335 { yyLOCAL = tree.NewAttributeNull(false) } yyVAL.union = yyLOCAL - case 1800: + case 1809: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12291 +//line mysql_sql.y:12339 { yyLOCAL = tree.NewAttributeNull(false) } yyVAL.union = yyLOCAL - case 1801: + case 1810: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12295 +//line mysql_sql.y:12343 { yyLOCAL = tree.NewAttributeDefault(yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1802: + case 1811: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12299 +//line mysql_sql.y:12347 { yyLOCAL = tree.NewAttributeAutoIncrement() } yyVAL.union = yyLOCAL - case 1803: + case 1812: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12303 +//line mysql_sql.y:12351 { yyLOCAL = yyDollar[1].columnAttributeUnion() } yyVAL.union = yyLOCAL - case 1804: + case 1813: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12307 +//line mysql_sql.y:12355 { str := util.DealCommentString(yyDollar[2].str) yyLOCAL = tree.NewAttributeComment(tree.NewNumVal(str, str, false, tree.P_char)) } yyVAL.union = yyLOCAL - case 1805: + case 1814: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12312 +//line mysql_sql.y:12360 { yyLOCAL = tree.NewAttributeMongoDBPath(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 1806: + case 1815: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12316 +//line mysql_sql.y:12364 { yyLOCAL = tree.NewAttributeMongoDBConvert(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 1807: + case 1816: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12320 +//line mysql_sql.y:12368 { yyLOCAL = tree.NewAttributeCollate(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 1808: + case 1817: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12324 +//line mysql_sql.y:12372 { yyLOCAL = tree.NewAttributeColumnFormat(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 1809: + case 1818: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12328 +//line mysql_sql.y:12376 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1810: + case 1819: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12332 +//line mysql_sql.y:12380 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1811: + case 1820: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12336 +//line mysql_sql.y:12384 { yyLOCAL = tree.NewAttributeStorage(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 1812: + case 1821: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12340 +//line mysql_sql.y:12388 { yyLOCAL = tree.NewAttributeAutoRandom(int(yyDollar[2].int64ValUnion())) } yyVAL.union = yyLOCAL - case 1813: + case 1822: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12344 +//line mysql_sql.y:12392 { yyLOCAL = yyDollar[1].attributeReferenceUnion() } yyVAL.union = yyLOCAL - case 1814: + case 1823: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12348 +//line mysql_sql.y:12396 { yyLOCAL = tree.NewAttributeCheckConstraint(yyDollar[4].exprUnion(), true, yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1815: + case 1824: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12352 +//line mysql_sql.y:12400 { yyLOCAL = tree.NewAttributeCheckConstraint(yyDollar[4].exprUnion(), yyDollar[6].boolValUnion(), yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1816: + case 1825: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12356 +//line mysql_sql.y:12404 { name := tree.NewUnresolvedColName(yyDollar[3].str) var es tree.Exprs = nil @@ -30104,10 +30233,10 @@ yydefault: yyLOCAL = tree.NewAttributeOnUpdate(expr) } yyVAL.union = yyLOCAL - case 1817: + case 1826: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12370 +//line mysql_sql.y:12418 { v, errStr := util.GetInt64(yyDollar[2].item) if errStr != "" { @@ -30121,130 +30250,130 @@ yydefault: yyLOCAL = tree.NewAttributeSRID(uint32(v)) } yyVAL.union = yyLOCAL - case 1818: + case 1827: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12383 +//line mysql_sql.y:12431 { yyLOCAL = tree.NewAttributeLowCardinality() } yyVAL.union = yyLOCAL - case 1819: + case 1828: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12387 +//line mysql_sql.y:12435 { yyLOCAL = tree.NewAttributeVisable(true) } yyVAL.union = yyLOCAL - case 1820: + case 1829: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12391 +//line mysql_sql.y:12439 { yyLOCAL = tree.NewAttributeVisable(false) } yyVAL.union = yyLOCAL - case 1821: + case 1830: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12395 +//line mysql_sql.y:12443 { yyLOCAL = tree.NewAttributeCharset(yyDollar[5].str) } yyVAL.union = yyLOCAL - case 1822: + case 1831: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12399 +//line mysql_sql.y:12447 { yyLOCAL = tree.NewAttributeGeneratedAlways(yyDollar[5].exprUnion(), yyDollar[7].boolValUnion()) } yyVAL.union = yyLOCAL - case 1823: + case 1832: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:12403 +//line mysql_sql.y:12451 { yyLOCAL = tree.NewAttributeGeneratedAlways(yyDollar[3].exprUnion(), yyDollar[5].boolValUnion()) } yyVAL.union = yyLOCAL - case 1824: + case 1833: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:12408 +//line mysql_sql.y:12456 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1825: + case 1834: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:12412 +//line mysql_sql.y:12460 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1826: + case 1835: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:12416 +//line mysql_sql.y:12464 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1827: + case 1836: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:12422 +//line mysql_sql.y:12470 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1828: + case 1837: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:12426 +//line mysql_sql.y:12474 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1829: + case 1838: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:12430 +//line mysql_sql.y:12478 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1830: + case 1839: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:12435 +//line mysql_sql.y:12483 { yyVAL.str = "" } - case 1831: + case 1840: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:12439 +//line mysql_sql.y:12487 { yyVAL.str = yyDollar[1].str } - case 1832: + case 1841: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:12445 +//line mysql_sql.y:12493 { yyVAL.str = "" } - case 1833: + case 1842: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:12449 +//line mysql_sql.y:12497 { yyVAL.str = yyDollar[2].cstrUnion().Compare() } - case 1834: + case 1843: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.AttributeReference -//line mysql_sql.y:12455 +//line mysql_sql.y:12503 { var TableName = yyDollar[2].tableNameUnion() var KeyParts = yyDollar[3].keyPartsUnion() @@ -30260,10 +30389,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1835: + case 1844: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.ReferenceOnRecord -//line mysql_sql.y:12472 +//line mysql_sql.y:12520 { yyLOCAL = &tree.ReferenceOnRecord{ OnDelete: tree.REFERENCE_OPTION_INVALID, @@ -30271,10 +30400,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1836: + case 1845: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.ReferenceOnRecord -//line mysql_sql.y:12479 +//line mysql_sql.y:12527 { yyLOCAL = &tree.ReferenceOnRecord{ OnDelete: yyDollar[1].referenceOptionTypeUnion(), @@ -30282,10 +30411,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1837: + case 1846: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.ReferenceOnRecord -//line mysql_sql.y:12486 +//line mysql_sql.y:12534 { yyLOCAL = &tree.ReferenceOnRecord{ OnDelete: tree.REFERENCE_OPTION_INVALID, @@ -30293,10 +30422,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1838: + case 1847: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.ReferenceOnRecord -//line mysql_sql.y:12493 +//line mysql_sql.y:12541 { yyLOCAL = &tree.ReferenceOnRecord{ OnDelete: yyDollar[1].referenceOptionTypeUnion(), @@ -30304,10 +30433,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1839: + case 1848: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.ReferenceOnRecord -//line mysql_sql.y:12500 +//line mysql_sql.y:12548 { yyLOCAL = &tree.ReferenceOnRecord{ OnDelete: yyDollar[2].referenceOptionTypeUnion(), @@ -30315,282 +30444,282 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1840: + case 1849: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:12509 +//line mysql_sql.y:12557 { yyLOCAL = yyDollar[3].referenceOptionTypeUnion() } yyVAL.union = yyLOCAL - case 1841: + case 1850: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:12515 +//line mysql_sql.y:12563 { yyLOCAL = yyDollar[3].referenceOptionTypeUnion() } yyVAL.union = yyLOCAL - case 1842: + case 1851: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:12521 +//line mysql_sql.y:12569 { yyLOCAL = tree.REFERENCE_OPTION_RESTRICT } yyVAL.union = yyLOCAL - case 1843: + case 1852: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:12525 +//line mysql_sql.y:12573 { yyLOCAL = tree.REFERENCE_OPTION_CASCADE } yyVAL.union = yyLOCAL - case 1844: + case 1853: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:12529 +//line mysql_sql.y:12577 { yyLOCAL = tree.REFERENCE_OPTION_SET_NULL } yyVAL.union = yyLOCAL - case 1845: + case 1854: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:12533 +//line mysql_sql.y:12581 { yyLOCAL = tree.REFERENCE_OPTION_NO_ACTION } yyVAL.union = yyLOCAL - case 1846: + case 1855: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:12537 +//line mysql_sql.y:12585 { yyLOCAL = tree.REFERENCE_OPTION_SET_DEFAULT } yyVAL.union = yyLOCAL - case 1847: + case 1856: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.MatchType -//line mysql_sql.y:12542 +//line mysql_sql.y:12590 { yyLOCAL = tree.MATCH_INVALID } yyVAL.union = yyLOCAL - case 1849: + case 1858: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.MatchType -//line mysql_sql.y:12549 +//line mysql_sql.y:12597 { yyLOCAL = tree.MATCH_FULL } yyVAL.union = yyLOCAL - case 1850: + case 1859: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.MatchType -//line mysql_sql.y:12553 +//line mysql_sql.y:12601 { yyLOCAL = tree.MATCH_PARTIAL } yyVAL.union = yyLOCAL - case 1851: + case 1860: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.MatchType -//line mysql_sql.y:12557 +//line mysql_sql.y:12605 { yyLOCAL = tree.MATCH_SIMPLE } yyVAL.union = yyLOCAL - case 1852: + case 1861: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.FullTextSearchType -//line mysql_sql.y:12562 +//line mysql_sql.y:12610 { yyLOCAL = tree.FULLTEXT_DEFAULT } yyVAL.union = yyLOCAL - case 1853: + case 1862: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.FullTextSearchType -//line mysql_sql.y:12566 +//line mysql_sql.y:12614 { yyLOCAL = tree.FULLTEXT_NL } yyVAL.union = yyLOCAL - case 1854: + case 1863: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.FullTextSearchType -//line mysql_sql.y:12570 +//line mysql_sql.y:12618 { yyLOCAL = tree.FULLTEXT_NL_QUERY_EXPANSION } yyVAL.union = yyLOCAL - case 1855: + case 1864: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.FullTextSearchType -//line mysql_sql.y:12574 +//line mysql_sql.y:12622 { yyLOCAL = tree.FULLTEXT_BOOLEAN } yyVAL.union = yyLOCAL - case 1856: + case 1865: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.FullTextSearchType -//line mysql_sql.y:12578 +//line mysql_sql.y:12626 { yyLOCAL = tree.FULLTEXT_QUERY_EXPANSION } yyVAL.union = yyLOCAL - case 1857: + case 1866: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.FullTextSearchType -//line mysql_sql.y:12582 +//line mysql_sql.y:12630 { yyLOCAL = tree.FULLTEXT_BM25 } yyVAL.union = yyLOCAL - case 1858: + case 1867: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*tree.KeyPart -//line mysql_sql.y:12587 +//line mysql_sql.y:12635 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1859: + case 1868: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.KeyPart -//line mysql_sql.y:12591 +//line mysql_sql.y:12639 { yyLOCAL = yyDollar[2].keyPartsUnion() } yyVAL.union = yyLOCAL - case 1860: + case 1869: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:12596 +//line mysql_sql.y:12644 { yyLOCAL = -1 } yyVAL.union = yyLOCAL - case 1861: + case 1870: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:12600 +//line mysql_sql.y:12648 { yyLOCAL = yyDollar[2].item.(int64) } yyVAL.union = yyLOCAL - case 1868: + case 1877: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Subquery -//line mysql_sql.y:12616 +//line mysql_sql.y:12664 { yyLOCAL = &tree.Subquery{Select: yyDollar[1].selectStatementUnion(), Exists: false} } yyVAL.union = yyLOCAL - case 1869: + case 1878: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12622 +//line mysql_sql.y:12670 { yyLOCAL = tree.NewBinaryExpr(tree.BIT_AND, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1870: + case 1879: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12626 +//line mysql_sql.y:12674 { yyLOCAL = tree.NewBinaryExpr(tree.BIT_OR, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1871: + case 1880: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12630 +//line mysql_sql.y:12678 { yyLOCAL = tree.NewBinaryExpr(tree.BIT_XOR, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1872: + case 1881: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12634 +//line mysql_sql.y:12682 { yyLOCAL = tree.NewBinaryExpr(tree.PLUS, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1873: + case 1882: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12638 +//line mysql_sql.y:12686 { yyLOCAL = tree.NewBinaryExpr(tree.MINUS, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1874: + case 1883: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12642 +//line mysql_sql.y:12690 { yyLOCAL = tree.NewBinaryExpr(tree.MULTI, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1875: + case 1884: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12646 +//line mysql_sql.y:12694 { yyLOCAL = tree.NewBinaryExpr(tree.DIV, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1876: + case 1885: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12650 +//line mysql_sql.y:12698 { yyLOCAL = tree.NewBinaryExpr(tree.INTEGER_DIV, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1877: + case 1886: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12654 +//line mysql_sql.y:12702 { yyLOCAL = tree.NewBinaryExpr(tree.MOD, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1878: + case 1887: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12658 +//line mysql_sql.y:12706 { yyLOCAL = tree.NewBinaryExpr(tree.MOD, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1879: + case 1888: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12662 +//line mysql_sql.y:12710 { yyLOCAL = tree.NewBinaryExpr(tree.LEFT_SHIFT, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1880: + case 1889: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12666 +//line mysql_sql.y:12714 { yyLOCAL = tree.NewBinaryExpr(tree.RIGHT_SHIFT, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1881: + case 1890: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12670 +//line mysql_sql.y:12718 { name := tree.NewUnresolvedColName("json_extract") yyLOCAL = &tree.FuncExpr{ @@ -30600,10 +30729,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1882: + case 1891: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12679 +//line mysql_sql.y:12727 { extractName := tree.NewUnresolvedColName("json_extract") inner := &tree.FuncExpr{ @@ -30619,42 +30748,42 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1883: + case 1892: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12694 +//line mysql_sql.y:12742 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1884: + case 1893: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12700 +//line mysql_sql.y:12748 { yyLOCAL = yyDollar[1].unresolvedNameUnion() } yyVAL.union = yyLOCAL - case 1885: + case 1894: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12704 +//line mysql_sql.y:12752 { yyLOCAL = yyDollar[1].varExprUnion() } yyVAL.union = yyLOCAL - case 1886: + case 1895: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12708 +//line mysql_sql.y:12756 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1887: + case 1896: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12712 +//line mysql_sql.y:12760 { name := tree.NewUnresolvedColName("concat") yyLOCAL = &tree.FuncExpr{ @@ -30664,66 +30793,66 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1888: + case 1897: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12721 +//line mysql_sql.y:12769 { yyLOCAL = tree.NewParentExpr(yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1889: + case 1898: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12725 +//line mysql_sql.y:12773 { yyLOCAL = tree.NewTuple(append(yyDollar[2].exprsUnion(), yyDollar[4].exprUnion())) } yyVAL.union = yyLOCAL - case 1890: + case 1899: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12729 +//line mysql_sql.y:12777 { yyLOCAL = tree.NewUnaryExpr(tree.UNARY_PLUS, yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1891: + case 1900: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12733 +//line mysql_sql.y:12781 { yyLOCAL = tree.NewUnaryExpr(tree.UNARY_MINUS, yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1892: + case 1901: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12737 +//line mysql_sql.y:12785 { yyLOCAL = tree.NewUnaryExpr(tree.UNARY_TILDE, yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1893: + case 1902: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12741 +//line mysql_sql.y:12789 { yyLOCAL = tree.NewUnaryExpr(tree.UNARY_MARK, yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1894: + case 1903: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12745 +//line mysql_sql.y:12793 { yyLOCAL = tree.NewNotExpr(yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1895: + case 1904: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12749 +//line mysql_sql.y:12797 { hint := strings.ToLower(yyDollar[2].cstrUnion().Compare()) switch hint { @@ -30766,35 +30895,35 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1896: + case 1905: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12791 +//line mysql_sql.y:12839 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1897: + case 1906: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12795 +//line mysql_sql.y:12843 { yyLOCAL = yyDollar[1].subqueryUnion() } yyVAL.union = yyLOCAL - case 1898: + case 1907: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12799 +//line mysql_sql.y:12847 { yyDollar[2].subqueryUnion().Exists = true yyLOCAL = yyDollar[2].subqueryUnion() } yyVAL.union = yyLOCAL - case 1899: + case 1908: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12804 +//line mysql_sql.y:12852 { yyLOCAL = &tree.CaseExpr{ Expr: yyDollar[2].exprUnion(), @@ -30803,50 +30932,50 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1900: + case 1909: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12812 +//line mysql_sql.y:12860 { yyLOCAL = tree.NewCastExpr(yyDollar[3].exprUnion(), yyDollar[5].columnTypeUnion()) } yyVAL.union = yyLOCAL - case 1901: + case 1910: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12816 +//line mysql_sql.y:12864 { yyLOCAL = tree.NewSerialExtractExpr(yyDollar[3].exprUnion(), yyDollar[5].exprUnion(), yyDollar[7].columnTypeUnion()) } yyVAL.union = yyLOCAL - case 1902: + case 1911: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12820 +//line mysql_sql.y:12868 { yyLOCAL = tree.NewBitCastExpr(yyDollar[3].exprUnion(), yyDollar[5].columnTypeUnion()) } yyVAL.union = yyLOCAL - case 1903: + case 1912: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12824 +//line mysql_sql.y:12872 { yyLOCAL = tree.NewCastExpr(yyDollar[1].exprUnion(), yyDollar[3].columnTypeUnion()) } yyVAL.union = yyLOCAL - case 1904: + case 1913: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12828 +//line mysql_sql.y:12876 { yyLOCAL = tree.NewCastExpr(yyDollar[3].exprUnion(), yyDollar[5].columnTypeUnion()) } yyVAL.union = yyLOCAL - case 1905: + case 1914: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12832 +//line mysql_sql.y:12880 { name := tree.NewUnresolvedColName(yyDollar[1].str) es := tree.NewNumVal(yyDollar[5].str, yyDollar[5].str, false, tree.P_char) @@ -30857,66 +30986,66 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1906: + case 1915: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12842 +//line mysql_sql.y:12890 { yyLOCAL = yyDollar[1].funcExprUnion() } yyVAL.union = yyLOCAL - case 1907: + case 1916: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12846 +//line mysql_sql.y:12894 { yyLOCAL = yyDollar[1].funcExprUnion() } yyVAL.union = yyLOCAL - case 1908: + case 1917: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12850 +//line mysql_sql.y:12898 { yyLOCAL = yyDollar[1].funcExprUnion() } yyVAL.union = yyLOCAL - case 1909: + case 1918: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12854 +//line mysql_sql.y:12902 { yyLOCAL = yyDollar[1].funcExprUnion() } yyVAL.union = yyLOCAL - case 1910: + case 1919: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12858 +//line mysql_sql.y:12906 { yyLOCAL = yyDollar[1].funcExprUnion() } yyVAL.union = yyLOCAL - case 1911: + case 1920: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12862 +//line mysql_sql.y:12910 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1912: + case 1921: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12866 +//line mysql_sql.y:12914 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1913: + case 1922: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12870 +//line mysql_sql.y:12918 { val, err := tree.NewFullTextMatchFuncExpression(yyDollar[3].keyPartsUnion(), yyDollar[7].exprUnion(), yyDollar[8].fullTextSearchTypeUnion()) if err != nil { @@ -30926,34 +31055,34 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1914: + case 1923: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12880 +//line mysql_sql.y:12928 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_char) } yyVAL.union = yyLOCAL - case 1915: + case 1924: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12884 +//line mysql_sql.y:12932 { yyLOCAL = tree.NewParamExpr(yylex.(*Lexer).GetParamIndex()) } yyVAL.union = yyLOCAL - case 1916: + case 1925: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12888 +//line mysql_sql.y:12936 { yyLOCAL = tree.NewUnresolvedName(yyDollar[1].cstrUnion()) } yyVAL.union = yyLOCAL - case 1917: + case 1926: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:12894 +//line mysql_sql.y:12942 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -30963,10 +31092,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1918: + case 1927: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:12903 +//line mysql_sql.y:12951 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -30976,10 +31105,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1919: + case 1928: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:12912 +//line mysql_sql.y:12960 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -30989,10 +31118,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1920: + case 1929: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:12921 +//line mysql_sql.y:12969 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31002,10 +31131,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1921: + case 1930: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:12930 +//line mysql_sql.y:12978 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31016,10 +31145,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1922: + case 1931: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:12940 +//line mysql_sql.y:12988 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31029,10 +31158,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1923: + case 1932: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:12949 +//line mysql_sql.y:12997 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31043,10 +31172,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1924: + case 1933: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:12959 +//line mysql_sql.y:13007 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31057,10 +31186,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1925: + case 1934: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:12969 +//line mysql_sql.y:13017 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31071,10 +31200,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1926: + case 1935: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:12979 +//line mysql_sql.y:13027 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31085,10 +31214,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1927: + case 1936: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:12989 +//line mysql_sql.y:13037 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31099,10 +31228,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1928: + case 1937: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:12999 +//line mysql_sql.y:13047 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31113,10 +31242,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1929: + case 1938: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13009 +//line mysql_sql.y:13057 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31127,10 +31256,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1930: + case 1939: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13019 +//line mysql_sql.y:13067 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31141,10 +31270,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1931: + case 1940: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13029 +//line mysql_sql.y:13077 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31155,10 +31284,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1932: + case 1941: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:13041 +//line mysql_sql.y:13089 { v := int(yyDollar[5].item.(int64)) val, err := tree.NewSampleRowsFuncExpression(v, true, nil, "block") @@ -31169,10 +31298,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1933: + case 1942: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:13051 +//line mysql_sql.y:13099 { v := int(yyDollar[5].item.(int64)) val, err := tree.NewSampleRowsFuncExpression(v, true, nil, yyDollar[8].str) @@ -31183,10 +31312,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1934: + case 1943: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:13061 +//line mysql_sql.y:13109 { val, err := tree.NewSamplePercentFuncExpression1(yyDollar[5].item.(int64), true, nil) if err != nil { @@ -31196,10 +31325,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1935: + case 1944: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:13070 +//line mysql_sql.y:13118 { val, err := tree.NewSamplePercentFuncExpression2(yyDollar[5].item.(float64), true, nil) if err != nil { @@ -31209,10 +31338,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1936: + case 1945: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:13080 +//line mysql_sql.y:13128 { v := int(yyDollar[5].item.(int64)) val, err := tree.NewSampleRowsFuncExpression(v, false, yyDollar[3].exprsUnion(), "block") @@ -31223,10 +31352,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1937: + case 1946: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:13090 +//line mysql_sql.y:13138 { v := int(yyDollar[5].item.(int64)) val, err := tree.NewSampleRowsFuncExpression(v, false, yyDollar[3].exprsUnion(), yyDollar[8].str) @@ -31237,10 +31366,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1938: + case 1947: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:13100 +//line mysql_sql.y:13148 { val, err := tree.NewSamplePercentFuncExpression1(yyDollar[5].item.(int64), false, yyDollar[3].exprsUnion()) if err != nil { @@ -31250,10 +31379,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1939: + case 1948: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:13109 +//line mysql_sql.y:13157 { val, err := tree.NewSamplePercentFuncExpression2(yyDollar[5].item.(float64), false, yyDollar[3].exprsUnion()) if err != nil { @@ -31263,58 +31392,58 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1940: + case 1949: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:13119 +//line mysql_sql.y:13167 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1941: + case 1950: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:13123 +//line mysql_sql.y:13171 { yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL - case 1942: + case 1951: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:13128 +//line mysql_sql.y:13176 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1943: + case 1952: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:13132 +//line mysql_sql.y:13180 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1944: + case 1953: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.When -//line mysql_sql.y:13138 +//line mysql_sql.y:13186 { yyLOCAL = []*tree.When{yyDollar[1].whenClauseUnion()} } yyVAL.union = yyLOCAL - case 1945: + case 1954: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*tree.When -//line mysql_sql.y:13142 +//line mysql_sql.y:13190 { yyLOCAL = append(yyDollar[1].whenClauseListUnion(), yyDollar[2].whenClauseUnion()) } yyVAL.union = yyLOCAL - case 1946: + case 1955: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.When -//line mysql_sql.y:13148 +//line mysql_sql.y:13196 { yyLOCAL = &tree.When{ Cond: yyDollar[2].exprUnion(), @@ -31322,9 +31451,9 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1947: + case 1956: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:13157 +//line mysql_sql.y:13205 { t := yyVAL.columnTypeUnion() str := strings.ToLower(t.InternalType.FamilyString) @@ -31337,10 +31466,10 @@ yydefault: } } } - case 1948: + case 1957: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:13169 +//line mysql_sql.y:13217 { name := yyDollar[1].str if yyDollar[2].str != "" { @@ -31358,10 +31487,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1949: + case 1958: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:13186 +//line mysql_sql.y:13234 { locale := "" yyLOCAL = &tree.T{ @@ -31376,10 +31505,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1951: + case 1960: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:13203 +//line mysql_sql.y:13251 { locale := "" yyLOCAL = &tree.T{ @@ -31392,10 +31521,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1952: + case 1961: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:13215 +//line mysql_sql.y:13263 { locale := "" yyLOCAL = &tree.T{ @@ -31410,10 +31539,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1953: + case 1962: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:13229 +//line mysql_sql.y:13277 { locale := "" oid := uint32(defines.MYSQL_TYPE_STRING) @@ -31433,10 +31562,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1954: + case 1963: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:13248 +//line mysql_sql.y:13296 { locale := "" yyLOCAL = &tree.T{ @@ -31449,10 +31578,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1955: + case 1964: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:13260 +//line mysql_sql.y:13308 { locale := "" yyLOCAL = &tree.T{ @@ -31467,10 +31596,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1956: + case 1965: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:13274 +//line mysql_sql.y:13322 { locale := "" yyLOCAL = &tree.T{ @@ -31486,10 +31615,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1957: + case 1966: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:13289 +//line mysql_sql.y:13337 { locale := "" yyLOCAL = &tree.T{ @@ -31505,10 +31634,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1958: + case 1967: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:13304 +//line mysql_sql.y:13352 { name := yyDollar[1].str if yyDollar[2].str != "" { @@ -31526,10 +31655,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1959: + case 1968: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:13321 +//line mysql_sql.y:13369 { locale := "" yyLOCAL = &tree.T{ @@ -31544,112 +31673,112 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1960: + case 1969: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:13337 +//line mysql_sql.y:13385 { yyVAL.str = "" } - case 1964: + case 1973: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:13346 +//line mysql_sql.y:13394 { yyLOCAL = &tree.FrameBound{Type: tree.Following, UnBounded: true} } yyVAL.union = yyLOCAL - case 1965: + case 1974: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:13350 +//line mysql_sql.y:13398 { yyLOCAL = &tree.FrameBound{Type: tree.Following, Expr: yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1966: + case 1975: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:13354 +//line mysql_sql.y:13402 { yyLOCAL = &tree.FrameBound{Type: tree.Following, Expr: tree.NewParamExpr(yylex.(*Lexer).GetParamIndex())} } yyVAL.union = yyLOCAL - case 1967: + case 1976: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:13358 +//line mysql_sql.y:13406 { yyLOCAL = &tree.FrameBound{Type: tree.Following, Expr: yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1968: + case 1977: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:13364 +//line mysql_sql.y:13412 { yyLOCAL = &tree.FrameBound{Type: tree.CurrentRow} } yyVAL.union = yyLOCAL - case 1969: + case 1978: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:13368 +//line mysql_sql.y:13416 { yyLOCAL = &tree.FrameBound{Type: tree.Preceding, UnBounded: true} } yyVAL.union = yyLOCAL - case 1970: + case 1979: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:13372 +//line mysql_sql.y:13420 { yyLOCAL = &tree.FrameBound{Type: tree.Preceding, Expr: yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1971: + case 1980: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:13376 +//line mysql_sql.y:13424 { yyLOCAL = &tree.FrameBound{Type: tree.Preceding, Expr: tree.NewParamExpr(yylex.(*Lexer).GetParamIndex())} } yyVAL.union = yyLOCAL - case 1972: + case 1981: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:13380 +//line mysql_sql.y:13428 { yyLOCAL = &tree.FrameBound{Type: tree.Preceding, Expr: yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1973: + case 1982: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FrameType -//line mysql_sql.y:13386 +//line mysql_sql.y:13434 { yyLOCAL = tree.Rows } yyVAL.union = yyLOCAL - case 1974: + case 1983: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FrameType -//line mysql_sql.y:13390 +//line mysql_sql.y:13438 { yyLOCAL = tree.Range } yyVAL.union = yyLOCAL - case 1975: + case 1984: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FrameType -//line mysql_sql.y:13394 +//line mysql_sql.y:13442 { yyLOCAL = tree.Groups } yyVAL.union = yyLOCAL - case 1976: + case 1985: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameClause -//line mysql_sql.y:13400 +//line mysql_sql.y:13448 { yyLOCAL = &tree.FrameClause{ Type: yyDollar[1].frameTypeUnion(), @@ -31658,10 +31787,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1977: + case 1986: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FrameClause -//line mysql_sql.y:13408 +//line mysql_sql.y:13456 { yyLOCAL = &tree.FrameClause{ Type: yyDollar[1].frameTypeUnion(), @@ -31671,163 +31800,163 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1978: + case 1987: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.FrameClause -//line mysql_sql.y:13418 +//line mysql_sql.y:13466 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1979: + case 1988: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.FrameClause -//line mysql_sql.y:13422 +//line mysql_sql.y:13470 { yyLOCAL = yyDollar[1].frameClauseUnion() } yyVAL.union = yyLOCAL - case 1980: + case 1989: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:13428 +//line mysql_sql.y:13476 { yyLOCAL = yyDollar[3].exprsUnion() } yyVAL.union = yyLOCAL - case 1981: + case 1990: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:13433 +//line mysql_sql.y:13481 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1982: + case 1991: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:13437 +//line mysql_sql.y:13485 { yyLOCAL = yyDollar[1].exprsUnion() } yyVAL.union = yyLOCAL - case 1983: + case 1992: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:13442 +//line mysql_sql.y:13490 { yyVAL.str = "," } - case 1984: + case 1993: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:13446 +//line mysql_sql.y:13494 { yyVAL.str = yyDollar[2].str } - case 1985: + case 1994: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:13451 +//line mysql_sql.y:13499 { yyVAL.str = "1,vector_l2_ops,random,false" } - case 1986: + case 1995: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:13455 +//line mysql_sql.y:13503 { yyVAL.str = yyDollar[2].str } - case 1987: + case 1996: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.WindowSpec -//line mysql_sql.y:13460 +//line mysql_sql.y:13508 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1989: + case 1998: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.WindowSpec -//line mysql_sql.y:13467 +//line mysql_sql.y:13515 { yyLOCAL = makeWindowSpec(yyDollar[2].cstrUnion(), nil, nil, nil) yyLOCAL.ReferencedOnly = true } yyVAL.union = yyLOCAL - case 1990: + case 1999: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.WindowSpec -//line mysql_sql.y:13472 +//line mysql_sql.y:13520 { yyLOCAL = yyDollar[3].windowSpecUnion() } yyVAL.union = yyLOCAL - case 1991: + case 2000: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.WindowSpec -//line mysql_sql.y:13478 +//line mysql_sql.y:13526 { yyLOCAL = makeWindowSpec(yyDollar[1].cstrUnion(), yyDollar[2].exprsUnion(), yyDollar[3].orderByUnion(), yyDollar[4].frameClauseUnion()) } yyVAL.union = yyLOCAL - case 1992: + case 2001: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:13487 +//line mysql_sql.y:13535 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1993: + case 2002: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:13491 +//line mysql_sql.y:13539 { yyLOCAL = yyDollar[1].cstrUnion() } yyVAL.union = yyLOCAL - case 1994: + case 2003: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.WindowDefinitions -//line mysql_sql.y:13496 +//line mysql_sql.y:13544 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1995: + case 2004: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.WindowDefinitions -//line mysql_sql.y:13500 +//line mysql_sql.y:13548 { yyLOCAL = yyDollar[2].windowDefinitionsUnion() } yyVAL.union = yyLOCAL - case 1996: + case 2005: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.WindowDefinitions -//line mysql_sql.y:13506 +//line mysql_sql.y:13554 { yyLOCAL = tree.WindowDefinitions{yyDollar[1].windowDefinitionUnion()} } yyVAL.union = yyLOCAL - case 1997: + case 2006: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.WindowDefinitions -//line mysql_sql.y:13510 +//line mysql_sql.y:13558 { yyLOCAL = append(yyDollar[1].windowDefinitionsUnion(), yyDollar[3].windowDefinitionUnion()) } yyVAL.union = yyLOCAL - case 1998: + case 2007: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.WindowDefinition -//line mysql_sql.y:13516 +//line mysql_sql.y:13564 { yyLOCAL = &tree.WindowDefinition{Name: yyDollar[1].cstrUnion(), Spec: yyDollar[4].windowSpecUnion()} } yyVAL.union = yyLOCAL - case 1999: + case 2008: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13522 +//line mysql_sql.y:13570 { functionName := yyDollar[1].str arguments := yyDollar[4].exprsUnion() @@ -31870,10 +31999,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2000: + case 2009: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13564 +//line mysql_sql.y:13612 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31886,10 +32015,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2001: + case 2010: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13576 +//line mysql_sql.y:13624 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31902,10 +32031,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2002: + case 2011: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13588 +//line mysql_sql.y:13636 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31918,10 +32047,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2003: + case 2012: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13600 +//line mysql_sql.y:13648 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31933,10 +32062,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2004: + case 2013: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13611 +//line mysql_sql.y:13659 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31948,10 +32077,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2005: + case 2014: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13622 +//line mysql_sql.y:13670 { name := tree.NewUnresolvedColName(yyDollar[1].str) es := tree.NewNumVal("*", "*", false, tree.P_star) @@ -31963,10 +32092,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2006: + case 2015: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13633 +//line mysql_sql.y:13681 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31977,10 +32106,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2007: + case 2016: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13643 +//line mysql_sql.y:13691 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -31993,10 +32122,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2008: + case 2017: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13655 +//line mysql_sql.y:13703 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32008,10 +32137,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2009: + case 2018: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13666 +//line mysql_sql.y:13714 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32023,10 +32152,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2010: + case 2019: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13677 +//line mysql_sql.y:13725 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32038,10 +32167,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2011: + case 2020: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13688 +//line mysql_sql.y:13736 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32053,10 +32182,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2012: + case 2021: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13699 +//line mysql_sql.y:13747 { name := tree.NewUnresolvedColName(yyDollar[1].str) es := tree.NewNumVal("*", "*", false, tree.P_star) @@ -32068,10 +32197,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2013: + case 2022: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13710 +//line mysql_sql.y:13758 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32083,10 +32212,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2014: + case 2023: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13721 +//line mysql_sql.y:13769 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32098,10 +32227,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2015: + case 2024: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13732 +//line mysql_sql.y:13780 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32113,10 +32242,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2016: + case 2025: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13743 +//line mysql_sql.y:13791 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32128,10 +32257,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2017: + case 2026: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13754 +//line mysql_sql.y:13802 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32143,10 +32272,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2018: + case 2027: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13765 +//line mysql_sql.y:13813 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32158,10 +32287,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2019: + case 2028: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13776 +//line mysql_sql.y:13824 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32173,10 +32302,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2020: + case 2029: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13787 +//line mysql_sql.y:13835 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32188,10 +32317,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2021: + case 2030: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13798 +//line mysql_sql.y:13846 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32203,10 +32332,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2022: + case 2031: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13809 +//line mysql_sql.y:13857 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32218,10 +32347,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2023: + case 2032: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13820 +//line mysql_sql.y:13868 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32233,10 +32362,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2024: + case 2033: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13831 +//line mysql_sql.y:13879 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32248,10 +32377,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2025: + case 2034: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13842 +//line mysql_sql.y:13890 { functionName := yyDollar[1].str if strings.EqualFold(functionName, "array_agg") { @@ -32269,10 +32398,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2026: + case 2035: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13859 +//line mysql_sql.y:13907 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32284,10 +32413,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2030: + case 2039: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13877 +//line mysql_sql.y:13925 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32298,10 +32427,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2031: + case 2040: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13887 +//line mysql_sql.y:13935 { name := tree.NewUnresolvedColName(yyDollar[1].str) exprs := tree.Exprs{yyDollar[3].exprUnion()} @@ -32313,10 +32442,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2032: + case 2041: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13898 +//line mysql_sql.y:13946 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32326,10 +32455,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2033: + case 2042: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13907 +//line mysql_sql.y:13955 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32339,10 +32468,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2034: + case 2043: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13916 +//line mysql_sql.y:13964 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32352,10 +32481,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2035: + case 2044: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13925 +//line mysql_sql.y:13973 { name := tree.NewUnresolvedColName(yyDollar[1].str) str := strings.ToLower(yyDollar[3].str) @@ -32367,10 +32496,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2036: + case 2045: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13936 +//line mysql_sql.y:13984 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32380,10 +32509,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2037: + case 2046: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13945 +//line mysql_sql.y:13993 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32393,10 +32522,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2038: + case 2047: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13954 +//line mysql_sql.y:14002 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32408,10 +32537,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2039: + case 2048: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13965 +//line mysql_sql.y:14013 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32421,10 +32550,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2040: + case 2049: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13974 +//line mysql_sql.y:14022 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32434,10 +32563,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2041: + case 2050: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13983 +//line mysql_sql.y:14031 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32447,10 +32576,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2042: + case 2051: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:13992 +//line mysql_sql.y:14040 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32460,10 +32589,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2043: + case 2052: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14001 +//line mysql_sql.y:14049 { name := tree.NewUnresolvedColName(yyDollar[1].str) arg0 := tree.NewNumVal(int64(0), "0", false, tree.P_int64) @@ -32476,10 +32605,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2044: + case 2053: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14013 +//line mysql_sql.y:14061 { name := tree.NewUnresolvedColName(yyDollar[1].str) arg0 := tree.NewNumVal(int64(1), "1", false, tree.P_int64) @@ -32491,10 +32620,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2045: + case 2054: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14024 +//line mysql_sql.y:14072 { name := tree.NewUnresolvedColName(yyDollar[1].str) arg0 := tree.NewNumVal(int64(2), "2", false, tree.P_int64) @@ -32508,10 +32637,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2046: + case 2055: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14037 +//line mysql_sql.y:14085 { name := tree.NewUnresolvedColName(yyDollar[1].str) arg0 := tree.NewNumVal(int64(3), "3", false, tree.P_int64) @@ -32524,10 +32653,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2047: + case 2056: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14049 +//line mysql_sql.y:14097 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32537,16 +32666,16 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2054: + case 2063: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:14070 +//line mysql_sql.y:14118 { yyVAL.str = yyDollar[1].str } - case 2087: + case 2096: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14112 +//line mysql_sql.y:14160 { name := tree.NewUnresolvedColName(yyDollar[1].str) var es tree.Exprs = nil @@ -32560,10 +32689,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2088: + case 2097: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14125 +//line mysql_sql.y:14173 { name := tree.NewUnresolvedColName(yyDollar[1].str) var es tree.Exprs = nil @@ -32577,10 +32706,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2089: + case 2098: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14138 +//line mysql_sql.y:14186 { name := tree.NewUnresolvedColName(yyDollar[1].str) str := strings.ToLower(yyDollar[3].str) @@ -32592,10 +32721,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2090: + case 2099: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14149 +//line mysql_sql.y:14197 { name := tree.NewUnresolvedColName(yyDollar[1].str) str := strings.ToLower(yyDollar[3].str) @@ -32607,10 +32736,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2091: + case 2100: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14160 +//line mysql_sql.y:14208 { name := tree.NewUnresolvedColName(yyDollar[1].str) str := strings.ToUpper(yyDollar[3].str) @@ -32622,10 +32751,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2092: + case 2101: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14172 +//line mysql_sql.y:14220 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32635,10 +32764,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2093: + case 2102: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14181 +//line mysql_sql.y:14229 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32647,10 +32776,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2094: + case 2103: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14189 +//line mysql_sql.y:14237 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32659,10 +32788,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2095: + case 2104: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14197 +//line mysql_sql.y:14245 { name := tree.NewUnresolvedColName(yyDollar[1].str) var es tree.Exprs = nil @@ -32676,10 +32805,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2096: + case 2105: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14210 +//line mysql_sql.y:14258 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32689,10 +32818,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2097: + case 2106: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14219 +//line mysql_sql.y:14267 { name := tree.NewUnresolvedColName(yyDollar[1].str) exprs := make([]tree.Expr, 1) @@ -32704,10 +32833,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2098: + case 2107: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14230 +//line mysql_sql.y:14278 { name := tree.NewUnresolvedColName(yyDollar[1].str) exprs := make([]tree.Expr, 1) @@ -32719,10 +32848,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2099: + case 2108: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14241 +//line mysql_sql.y:14289 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32732,10 +32861,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2100: + case 2109: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14250 +//line mysql_sql.y:14298 { charName := tree.NewUnresolvedColName(yyDollar[1].str) charExpr := &tree.FuncExpr{ @@ -32752,10 +32881,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2101: + case 2110: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14266 +//line mysql_sql.y:14314 { val := tree.NewNumVal(yyDollar[2].str, yyDollar[2].str, false, tree.P_char) name := tree.NewUnresolvedColName(yyDollar[1].str) @@ -32766,10 +32895,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2102: + case 2111: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14276 +//line mysql_sql.y:14324 { val := tree.NewNumVal(yyDollar[2].str, yyDollar[2].str, false, tree.P_char) name := tree.NewUnresolvedColName(yyDollar[1].str) @@ -32780,10 +32909,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2103: + case 2112: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14286 +//line mysql_sql.y:14334 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32793,10 +32922,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2104: + case 2113: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14295 +//line mysql_sql.y:14343 { es := tree.Exprs{yyDollar[3].exprUnion()} es = append(es, yyDollar[5].exprUnion()) @@ -32808,10 +32937,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2105: + case 2114: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14306 +//line mysql_sql.y:14354 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32821,10 +32950,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2106: + case 2115: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14315 +//line mysql_sql.y:14363 { val := tree.NewNumVal(yyDollar[2].str, yyDollar[2].str, false, tree.P_char) name := tree.NewUnresolvedColName(yyDollar[1].str) @@ -32835,10 +32964,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2107: + case 2116: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14325 +//line mysql_sql.y:14373 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32848,10 +32977,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2108: + case 2117: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14334 +//line mysql_sql.y:14382 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32861,10 +32990,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2109: + case 2118: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:14343 +//line mysql_sql.y:14391 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -32874,34 +33003,34 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2110: + case 2119: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14353 +//line mysql_sql.y:14401 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 2111: + case 2120: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14357 +//line mysql_sql.y:14405 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 2112: + case 2121: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14363 +//line mysql_sql.y:14411 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 2113: + case 2122: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14367 +//line mysql_sql.y:14415 { ival, errStr := util.GetInt64(yyDollar[2].item) if errStr != "" { @@ -32912,20 +33041,20 @@ yydefault: yyLOCAL = tree.NewNumVal(ival, str, false, tree.P_int64) } yyVAL.union = yyLOCAL - case 2120: + case 2129: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:14386 +//line mysql_sql.y:14434 { } - case 2121: + case 2130: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:14388 +//line mysql_sql.y:14436 { } - case 2156: + case 2165: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14430 +//line mysql_sql.y:14478 { name := tree.NewUnresolvedColName(yyDollar[1].str) str := strings.ToLower(yyDollar[3].str) @@ -32937,531 +33066,531 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2157: + case 2166: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.FuncType -//line mysql_sql.y:14442 +//line mysql_sql.y:14490 { yyLOCAL = tree.FUNC_TYPE_DEFAULT } yyVAL.union = yyLOCAL - case 2158: + case 2167: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FuncType -//line mysql_sql.y:14446 +//line mysql_sql.y:14494 { yyLOCAL = tree.FUNC_TYPE_DISTINCT } yyVAL.union = yyLOCAL - case 2159: + case 2168: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FuncType -//line mysql_sql.y:14450 +//line mysql_sql.y:14498 { yyLOCAL = tree.FUNC_TYPE_ALL } yyVAL.union = yyLOCAL - case 2160: + case 2169: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Tuple -//line mysql_sql.y:14456 +//line mysql_sql.y:14504 { yyLOCAL = tree.NewTuple(yyDollar[2].exprsUnion()) } yyVAL.union = yyLOCAL - case 2161: + case 2170: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:14461 +//line mysql_sql.y:14509 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 2162: + case 2171: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:14465 +//line mysql_sql.y:14513 { yyLOCAL = yyDollar[1].exprsUnion() } yyVAL.union = yyLOCAL - case 2163: + case 2172: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:14471 +//line mysql_sql.y:14519 { yyLOCAL = tree.Exprs{yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 2164: + case 2173: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:14475 +//line mysql_sql.y:14523 { yyLOCAL = append(yyDollar[1].exprsUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 2165: + case 2174: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:14481 +//line mysql_sql.y:14529 { yyLOCAL = tree.Exprs{yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 2166: + case 2175: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:14485 +//line mysql_sql.y:14533 { yyLOCAL = append(yyDollar[1].exprsUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 2167: + case 2176: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14492 +//line mysql_sql.y:14540 { yyLOCAL = tree.NewAndExpr(yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 2168: + case 2177: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14496 +//line mysql_sql.y:14544 { yyLOCAL = tree.NewOrExpr(yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 2169: + case 2178: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14500 +//line mysql_sql.y:14548 { yyLOCAL = tree.NewXorExpr(yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 2170: + case 2179: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14504 +//line mysql_sql.y:14552 { yyLOCAL = tree.NewNotExpr(yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 2171: + case 2180: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14508 +//line mysql_sql.y:14556 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 2172: + case 2181: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14513 +//line mysql_sql.y:14561 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 2173: + case 2182: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14517 +//line mysql_sql.y:14565 { yyLOCAL = tree.NewMaxValue() } yyVAL.union = yyLOCAL - case 2174: + case 2183: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14523 +//line mysql_sql.y:14571 { yyLOCAL = tree.NewIsNullExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 2175: + case 2184: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14527 +//line mysql_sql.y:14575 { yyLOCAL = tree.NewIsNotNullExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 2176: + case 2185: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14531 +//line mysql_sql.y:14579 { yyLOCAL = tree.NewIsNotNullExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 2177: + case 2186: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14535 +//line mysql_sql.y:14583 { yyLOCAL = tree.NewIsUnknownExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 2178: + case 2187: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14539 +//line mysql_sql.y:14587 { yyLOCAL = tree.NewIsNotUnknownExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 2179: + case 2188: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14543 +//line mysql_sql.y:14591 { yyLOCAL = tree.NewIsNotUnknownExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 2180: + case 2189: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14547 +//line mysql_sql.y:14595 { yyLOCAL = tree.NewIsTrueExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 2181: + case 2190: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14551 +//line mysql_sql.y:14599 { yyLOCAL = tree.NewIsNotTrueExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 2182: + case 2191: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14555 +//line mysql_sql.y:14603 { yyLOCAL = tree.NewIsNotTrueExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 2183: + case 2192: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14559 +//line mysql_sql.y:14607 { yyLOCAL = tree.NewIsFalseExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 2184: + case 2193: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14563 +//line mysql_sql.y:14611 { yyLOCAL = tree.NewIsNotFalseExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 2185: + case 2194: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14567 +//line mysql_sql.y:14615 { yyLOCAL = tree.NewIsNotFalseExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 2186: + case 2195: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14571 +//line mysql_sql.y:14619 { yyLOCAL = tree.NewComparisonExpr(yyDollar[2].comparisonOpUnion(), yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 2187: + case 2196: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14575 +//line mysql_sql.y:14623 { 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 2189: + case 2198: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14583 +//line mysql_sql.y:14631 { yyLOCAL = tree.NewComparisonExpr(tree.IN, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 2190: + case 2199: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14587 +//line mysql_sql.y:14635 { yyLOCAL = tree.NewComparisonExpr(tree.NOT_IN, yyDollar[1].exprUnion(), yyDollar[4].exprUnion()) } yyVAL.union = yyLOCAL - case 2191: + case 2200: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14591 +//line mysql_sql.y:14639 { yyLOCAL = tree.NewComparisonExpr(tree.NOT_IN, yyDollar[1].exprUnion(), yyDollar[4].exprUnion()) } yyVAL.union = yyLOCAL - case 2192: + case 2201: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14595 +//line mysql_sql.y:14643 { yyLOCAL = tree.NewComparisonExpr(tree.MEMBER_OF, yyDollar[1].exprUnion(), yyDollar[5].exprUnion()) } yyVAL.union = yyLOCAL - case 2193: + case 2202: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14599 +//line mysql_sql.y:14647 { yyLOCAL = tree.NewComparisonExprWithEscape(tree.LIKE, yyDollar[1].exprUnion(), yyDollar[3].exprUnion(), yyDollar[4].exprUnion()) } yyVAL.union = yyLOCAL - case 2194: + case 2203: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14603 +//line mysql_sql.y:14651 { yyLOCAL = tree.NewComparisonExprWithEscape(tree.NOT_LIKE, yyDollar[1].exprUnion(), yyDollar[4].exprUnion(), yyDollar[5].exprUnion()) } yyVAL.union = yyLOCAL - case 2195: + case 2204: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14607 +//line mysql_sql.y:14655 { yyLOCAL = tree.NewComparisonExprWithEscape(tree.NOT_LIKE, yyDollar[1].exprUnion(), yyDollar[4].exprUnion(), yyDollar[5].exprUnion()) } yyVAL.union = yyLOCAL - case 2196: + case 2205: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14611 +//line mysql_sql.y:14659 { yyLOCAL = tree.NewComparisonExprWithEscape(tree.ILIKE, yyDollar[1].exprUnion(), yyDollar[3].exprUnion(), yyDollar[4].exprUnion()) } yyVAL.union = yyLOCAL - case 2197: + case 2206: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14615 +//line mysql_sql.y:14663 { yyLOCAL = tree.NewComparisonExprWithEscape(tree.NOT_ILIKE, yyDollar[1].exprUnion(), yyDollar[4].exprUnion(), yyDollar[5].exprUnion()) } yyVAL.union = yyLOCAL - case 2198: + case 2207: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14619 +//line mysql_sql.y:14667 { yyLOCAL = tree.NewComparisonExprWithEscape(tree.NOT_ILIKE, yyDollar[1].exprUnion(), yyDollar[4].exprUnion(), yyDollar[5].exprUnion()) } yyVAL.union = yyLOCAL - case 2199: + case 2208: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14623 +//line mysql_sql.y:14671 { yyLOCAL = tree.NewComparisonExpr(tree.REG_MATCH, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 2200: + case 2209: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14627 +//line mysql_sql.y:14675 { yyLOCAL = tree.NewComparisonExpr(tree.NOT_REG_MATCH, yyDollar[1].exprUnion(), yyDollar[4].exprUnion()) } yyVAL.union = yyLOCAL - case 2201: + case 2210: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14631 +//line mysql_sql.y:14679 { yyLOCAL = tree.NewComparisonExpr(tree.NOT_REG_MATCH, yyDollar[1].exprUnion(), yyDollar[4].exprUnion()) } yyVAL.union = yyLOCAL - case 2202: + case 2211: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14635 +//line mysql_sql.y:14683 { yyLOCAL = tree.NewRangeCond(false, yyDollar[1].exprUnion(), yyDollar[3].exprUnion(), yyDollar[5].exprUnion()) } yyVAL.union = yyLOCAL - case 2203: + case 2212: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14639 +//line mysql_sql.y:14687 { yyLOCAL = tree.NewRangeCond(true, yyDollar[1].exprUnion(), yyDollar[4].exprUnion(), yyDollar[6].exprUnion()) } yyVAL.union = yyLOCAL - case 2204: + case 2213: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14643 +//line mysql_sql.y:14691 { yyLOCAL = tree.NewRangeCond(true, yyDollar[1].exprUnion(), yyDollar[4].exprUnion(), yyDollar[6].exprUnion()) } yyVAL.union = yyLOCAL - case 2206: + case 2215: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14649 +//line mysql_sql.y:14697 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 2207: + case 2216: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14653 +//line mysql_sql.y:14701 { yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL - case 2210: + case 2219: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14663 +//line mysql_sql.y:14711 { yyLOCAL = yyDollar[1].tupleUnion() } yyVAL.union = yyLOCAL - case 2211: + case 2220: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14667 +//line mysql_sql.y:14715 { yyLOCAL = yyDollar[1].subqueryUnion() } yyVAL.union = yyLOCAL - case 2212: + case 2221: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:14674 +//line mysql_sql.y:14722 { yyLOCAL = tree.ALL } yyVAL.union = yyLOCAL - case 2213: + case 2222: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:14678 +//line mysql_sql.y:14726 { yyLOCAL = tree.ANY } yyVAL.union = yyLOCAL - case 2214: + case 2223: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:14682 +//line mysql_sql.y:14730 { yyLOCAL = tree.SOME } yyVAL.union = yyLOCAL - case 2215: + case 2224: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:14688 +//line mysql_sql.y:14736 { yyLOCAL = tree.EQUAL } yyVAL.union = yyLOCAL - case 2216: + case 2225: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:14692 +//line mysql_sql.y:14740 { yyLOCAL = tree.LESS_THAN } yyVAL.union = yyLOCAL - case 2217: + case 2226: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:14696 +//line mysql_sql.y:14744 { yyLOCAL = tree.GREAT_THAN } yyVAL.union = yyLOCAL - case 2218: + case 2227: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:14700 +//line mysql_sql.y:14748 { yyLOCAL = tree.LESS_THAN_EQUAL } yyVAL.union = yyLOCAL - case 2219: + case 2228: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:14704 +//line mysql_sql.y:14752 { yyLOCAL = tree.GREAT_THAN_EQUAL } yyVAL.union = yyLOCAL - case 2220: + case 2229: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:14708 +//line mysql_sql.y:14756 { yyLOCAL = tree.NOT_EQUAL } yyVAL.union = yyLOCAL - case 2221: + case 2230: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:14712 +//line mysql_sql.y:14760 { yyLOCAL = tree.NULL_SAFE_EQUAL } yyVAL.union = yyLOCAL - case 2222: + case 2231: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:14718 +//line mysql_sql.y:14766 { yyLOCAL = tree.NewAttributePrimaryKey() } yyVAL.union = yyLOCAL - case 2223: + case 2232: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:14722 +//line mysql_sql.y:14770 { yyLOCAL = tree.NewAttributeUniqueKey() } yyVAL.union = yyLOCAL - case 2224: + case 2233: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:14726 +//line mysql_sql.y:14774 { yyLOCAL = tree.NewAttributeUnique() } yyVAL.union = yyLOCAL - case 2225: + case 2234: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:14730 +//line mysql_sql.y:14778 { yyLOCAL = tree.NewAttributeKey() } yyVAL.union = yyLOCAL - case 2226: + case 2235: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14736 +//line mysql_sql.y:14784 { str := fmt.Sprintf("%v", yyDollar[1].item) switch v := yyDollar[1].item.(type) { @@ -33475,35 +33604,35 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2227: + case 2236: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14749 +//line mysql_sql.y:14797 { fval := yyDollar[1].item.(float64) yyLOCAL = tree.NewNumVal(fval, yylex.(*Lexer).scanner.LastToken, false, tree.P_float64) } yyVAL.union = yyLOCAL - case 2228: + case 2237: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14754 +//line mysql_sql.y:14802 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_decimal) } yyVAL.union = yyLOCAL - case 2229: + case 2238: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14760 +//line mysql_sql.y:14808 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_char) } yyVAL.union = yyLOCAL - case 2230: + case 2239: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14764 +//line mysql_sql.y:14812 { str := fmt.Sprintf("%v", yyDollar[1].item) switch v := yyDollar[1].item.(type) { @@ -33517,101 +33646,101 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2231: + case 2240: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14777 +//line mysql_sql.y:14825 { fval := yyDollar[1].item.(float64) yyLOCAL = tree.NewNumVal(fval, yylex.(*Lexer).scanner.LastToken, false, tree.P_float64) } yyVAL.union = yyLOCAL - case 2232: + case 2241: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14782 +//line mysql_sql.y:14830 { yyLOCAL = tree.NewNumVal(true, "true", false, tree.P_bool) } yyVAL.union = yyLOCAL - case 2233: + case 2242: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14786 +//line mysql_sql.y:14834 { yyLOCAL = tree.NewNumVal(false, "false", false, tree.P_bool) } yyVAL.union = yyLOCAL - case 2234: + case 2243: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14790 +//line mysql_sql.y:14838 { yyLOCAL = tree.NewNumVal("null", "null", false, tree.P_null) } yyVAL.union = yyLOCAL - case 2235: + case 2244: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14794 +//line mysql_sql.y:14842 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_hexnum) } yyVAL.union = yyLOCAL - case 2236: + case 2245: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14798 +//line mysql_sql.y:14846 { yyLOCAL = tree.NewNumVal(yyDollar[2].str, yyDollar[2].str, false, tree.P_ScoreBinaryHexnum) } yyVAL.union = yyLOCAL - case 2237: + case 2246: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14802 +//line mysql_sql.y:14850 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_decimal) } yyVAL.union = yyLOCAL - case 2238: + case 2247: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14806 +//line mysql_sql.y:14854 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_bit) } yyVAL.union = yyLOCAL - case 2239: + case 2248: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14810 +//line mysql_sql.y:14858 { yyLOCAL = tree.NewParamExpr(yylex.(*Lexer).GetParamIndex()) } yyVAL.union = yyLOCAL - case 2240: + case 2249: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:14814 +//line mysql_sql.y:14862 { yyLOCAL = tree.NewNumVal(yyDollar[2].str, yyDollar[2].str, false, tree.P_ScoreBinary) } yyVAL.union = yyLOCAL - case 2241: + case 2250: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:14820 +//line mysql_sql.y:14868 { yyLOCAL = yyDollar[1].columnTypeUnion() yyLOCAL.InternalType.Unsigned = yyDollar[2].unsignedOptUnion() yyLOCAL.InternalType.Zerofill = yyDollar[3].zeroFillOptUnion() } yyVAL.union = yyLOCAL - case 2245: + case 2254: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:14829 +//line mysql_sql.y:14877 { locale := "" yyLOCAL = &tree.T{ @@ -33625,27 +33754,27 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2246: + case 2255: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:14844 +//line mysql_sql.y:14892 { yyLOCAL = yyDollar[1].columnTypeUnion() yyLOCAL.InternalType.DisplayWith = yyDollar[2].lengthOptUnion() } yyVAL.union = yyLOCAL - case 2247: + case 2256: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:14849 +//line mysql_sql.y:14897 { yyLOCAL = yyDollar[1].columnTypeUnion() } yyVAL.union = yyLOCAL - case 2248: + case 2257: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:14855 +//line mysql_sql.y:14903 { locale := "" yyLOCAL = &tree.T{ @@ -33658,10 +33787,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2249: + case 2258: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:14867 +//line mysql_sql.y:14915 { locale := "" yyLOCAL = &tree.T{ @@ -33674,10 +33803,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2250: + case 2259: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:14879 +//line mysql_sql.y:14927 { locale := "" yyLOCAL = &tree.T{ @@ -33690,10 +33819,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2251: + case 2260: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:14891 +//line mysql_sql.y:14939 { locale := "" yyLOCAL = &tree.T{ @@ -33707,10 +33836,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2252: + case 2261: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:14904 +//line mysql_sql.y:14952 { locale := "" yyLOCAL = &tree.T{ @@ -33724,10 +33853,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2253: + case 2262: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:14917 +//line mysql_sql.y:14965 { locale := "" yyLOCAL = &tree.T{ @@ -33741,10 +33870,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2254: + case 2263: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:14930 +//line mysql_sql.y:14978 { locale := "" yyLOCAL = &tree.T{ @@ -33758,10 +33887,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2255: + case 2264: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:14943 +//line mysql_sql.y:14991 { locale := "" yyLOCAL = &tree.T{ @@ -33775,10 +33904,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2256: + case 2265: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:14956 +//line mysql_sql.y:15004 { locale := "" yyLOCAL = &tree.T{ @@ -33792,10 +33921,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2257: + case 2266: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:14969 +//line mysql_sql.y:15017 { locale := "" yyLOCAL = &tree.T{ @@ -33809,10 +33938,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2258: + case 2267: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:14982 +//line mysql_sql.y:15030 { locale := "" yyLOCAL = &tree.T{ @@ -33826,10 +33955,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2259: + case 2268: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:14995 +//line mysql_sql.y:15043 { locale := "" yyLOCAL = &tree.T{ @@ -33843,10 +33972,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2260: + case 2269: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15008 +//line mysql_sql.y:15056 { locale := "" yyLOCAL = &tree.T{ @@ -33860,10 +33989,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2261: + case 2270: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15021 +//line mysql_sql.y:15069 { locale := "" yyLOCAL = &tree.T{ @@ -33877,10 +34006,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2262: + case 2271: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15036 +//line mysql_sql.y:15084 { locale := "" if yyDollar[2].lengthScaleOptUnion().DisplayWith > 255 { @@ -33908,10 +34037,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2263: + case 2272: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15063 +//line mysql_sql.y:15111 { // DOUBLE PRECISION is the SQL-standard synonym for DOUBLE (float64). locale := "" @@ -33940,10 +34069,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2264: + case 2273: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15091 +//line mysql_sql.y:15139 { locale := "" if yyDollar[2].lengthScaleOptUnion().DisplayWith > 255 { @@ -33985,10 +34114,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2265: + case 2274: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15133 +//line mysql_sql.y:15181 { locale := "" if yyDollar[2].lengthScaleOptUnion().Scale != tree.NotDefineDec && yyDollar[2].lengthScaleOptUnion().Scale > yyDollar[2].lengthScaleOptUnion().DisplayWith { @@ -34037,10 +34166,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2266: + case 2275: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15181 +//line mysql_sql.y:15229 { locale := "" if yyDollar[2].lengthScaleOptUnion().Scale != tree.NotDefineDec && yyDollar[2].lengthScaleOptUnion().Scale > yyDollar[2].lengthScaleOptUnion().DisplayWith { @@ -34089,10 +34218,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2267: + case 2276: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15229 +//line mysql_sql.y:15277 { locale := "" width := int32(64) @@ -34114,10 +34243,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2268: + case 2277: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15252 +//line mysql_sql.y:15300 { locale := "" yyLOCAL = &tree.T{ @@ -34130,10 +34259,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2269: + case 2278: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15264 +//line mysql_sql.y:15312 { locale := "" if yyDollar[2].lengthOptUnion() < 0 || yyDollar[2].lengthOptUnion() > 6 { @@ -34154,10 +34283,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2270: + case 2279: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15284 +//line mysql_sql.y:15332 { locale := "" if yyDollar[2].lengthOptUnion() < 0 || yyDollar[2].lengthOptUnion() > 6 { @@ -34178,10 +34307,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2271: + case 2280: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15304 +//line mysql_sql.y:15352 { locale := "" if yyDollar[2].lengthOptUnion() < 0 || yyDollar[2].lengthOptUnion() > 6 { @@ -34202,10 +34331,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2272: + case 2281: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15324 +//line mysql_sql.y:15372 { locale := "" yyLOCAL = &tree.T{ @@ -34220,10 +34349,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2273: + case 2282: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15340 +//line mysql_sql.y:15388 { locale := "" yyLOCAL = &tree.T{ @@ -34237,10 +34366,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2274: + case 2283: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15353 +//line mysql_sql.y:15401 { locale := "" yyLOCAL = &tree.T{ @@ -34254,10 +34383,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2275: + case 2284: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15366 +//line mysql_sql.y:15414 { locale := "" yyLOCAL = &tree.T{ @@ -34271,10 +34400,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2276: + case 2285: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15379 +//line mysql_sql.y:15427 { locale := "" yyLOCAL = &tree.T{ @@ -34288,10 +34417,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2277: + case 2286: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15392 +//line mysql_sql.y:15440 { locale := "" yyLOCAL = &tree.T{ @@ -34304,10 +34433,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2278: + case 2287: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15404 +//line mysql_sql.y:15452 { locale := "" yyLOCAL = &tree.T{ @@ -34320,10 +34449,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2279: + case 2288: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15416 +//line mysql_sql.y:15464 { locale := "" yyLOCAL = &tree.T{ @@ -34336,10 +34465,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2280: + case 2289: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15428 +//line mysql_sql.y:15476 { locale := "" yyLOCAL = &tree.T{ @@ -34353,10 +34482,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2281: + case 2290: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15441 +//line mysql_sql.y:15489 { locale := "" yyLOCAL = &tree.T{ @@ -34369,10 +34498,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2282: + case 2291: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15453 +//line mysql_sql.y:15501 { locale := "" yyLOCAL = &tree.T{ @@ -34385,10 +34514,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2283: + case 2292: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15465 +//line mysql_sql.y:15513 { locale := "" yyLOCAL = &tree.T{ @@ -34401,10 +34530,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2284: + case 2293: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15477 +//line mysql_sql.y:15525 { locale := "" yyLOCAL = &tree.T{ @@ -34418,10 +34547,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2285: + case 2294: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15490 +//line mysql_sql.y:15538 { locale := "" yyLOCAL = &tree.T{ @@ -34434,10 +34563,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2286: + case 2295: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15502 +//line mysql_sql.y:15550 { locale := "" yyLOCAL = &tree.T{ @@ -34450,10 +34579,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2287: + case 2296: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15514 +//line mysql_sql.y:15562 { locale := "" yyLOCAL = &tree.T{ @@ -34466,10 +34595,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2288: + case 2297: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15526 +//line mysql_sql.y:15574 { locale := "" yyLOCAL = &tree.T{ @@ -34482,10 +34611,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2289: + case 2298: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15538 +//line mysql_sql.y:15586 { locale := "" yyLOCAL = &tree.T{ @@ -34499,10 +34628,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2290: + case 2299: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15551 +//line mysql_sql.y:15599 { locale := "" yyLOCAL = &tree.T{ @@ -34516,10 +34645,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2291: + case 2300: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15564 +//line mysql_sql.y:15612 { locale := "" yyLOCAL = &tree.T{ @@ -34533,10 +34662,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2292: + case 2301: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15577 +//line mysql_sql.y:15625 { locale := "" yyLOCAL = &tree.T{ @@ -34550,10 +34679,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2293: + case 2302: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15590 +//line mysql_sql.y:15638 { locale := "" yyLOCAL = &tree.T{ @@ -34567,10 +34696,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2294: + case 2303: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15603 +//line mysql_sql.y:15651 { locale := "" yyLOCAL = &tree.T{ @@ -34584,10 +34713,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2295: + case 2304: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15616 +//line mysql_sql.y:15664 { locale := "" yyLOCAL = &tree.T{ @@ -34601,10 +34730,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2296: + case 2305: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15629 +//line mysql_sql.y:15677 { locale := "" yyLOCAL = &tree.T{ @@ -34618,10 +34747,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2297: + case 2306: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15642 +//line mysql_sql.y:15690 { locale := "" yyLOCAL = &tree.T{ @@ -34635,20 +34764,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2298: + case 2307: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:15657 +//line mysql_sql.y:15705 { yyLOCAL = &tree.Do{ Exprs: yyDollar[2].exprsUnion(), } } yyVAL.union = yyLOCAL - case 2299: + case 2308: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:15665 +//line mysql_sql.y:15713 { yyDollar[2].selectUnion().IsPerform = true if intoErr := tree.ValidatePerformSelectIntoPlacement(yyDollar[2].selectUnion()); intoErr != "" { @@ -34658,10 +34787,10 @@ yydefault: yyLOCAL = yyDollar[2].selectUnion() } yyVAL.union = yyLOCAL - case 2300: + case 2309: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:15676 +//line mysql_sql.y:15724 { yyLOCAL = &tree.Select{Select: yyDollar[1].selectStatementUnion(), TimeWindow: yyDollar[2].timeWindowUnion(), OrderBy: yyDollar[3].orderByUnion(), Limit: yyDollar[4].limitUnion(), RankOption: yyDollar[5].rankOptionUnion(), Ep: tree.SelectIntoExportOr(yyDollar[1].selectStatementUnion(), yyDollar[6].selectIntoUnion().Export), IntoVars: yyDollar[6].selectIntoUnion().UserVars, SelectLockInfo: yyDollar[7].selectLockInfoUnion()} if intoErr := tree.ValidatePerformSelectIntoPlacement(yyLOCAL); intoErr != "" { @@ -34670,10 +34799,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2301: + case 2310: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.Select -//line mysql_sql.y:15684 +//line mysql_sql.y:15732 { yyLOCAL = &tree.Select{Select: yyDollar[2].selectStatementUnion(), TimeWindow: yyDollar[3].timeWindowUnion(), OrderBy: yyDollar[4].orderByUnion(), Limit: yyDollar[5].limitUnion(), RankOption: yyDollar[6].rankOptionUnion(), Ep: tree.SelectIntoExportOr(yyDollar[2].selectStatementUnion(), yyDollar[7].selectIntoUnion().Export), IntoVars: yyDollar[7].selectIntoUnion().UserVars, SelectLockInfo: yyDollar[8].selectLockInfoUnion(), With: yyDollar[1].withClauseUnion()} if intoErr := tree.ValidatePerformSelectIntoPlacement(yyLOCAL); intoErr != "" { @@ -34682,10 +34811,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2302: + case 2311: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:15694 +//line mysql_sql.y:15742 { yyLOCAL = &tree.Declare{ Variables: yyDollar[2].strsUnion(), @@ -34694,10 +34823,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2303: + case 2312: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:15703 +//line mysql_sql.y:15751 { yyLOCAL = &tree.Declare{ Variables: yyDollar[2].strsUnion(), @@ -34706,83 +34835,83 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2304: + case 2313: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:15713 +//line mysql_sql.y:15761 { yyLOCAL = tree.NewSpatialType(yyDollar[1].str) } yyVAL.union = yyLOCAL - case 2323: + case 2332: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:15741 +//line mysql_sql.y:15789 { yyLOCAL = make([]string, 0, 4) yyLOCAL = append(yyLOCAL, yyDollar[1].str) } yyVAL.union = yyLOCAL - case 2324: + case 2333: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:15746 +//line mysql_sql.y:15794 { yyLOCAL = append(yyDollar[1].strsUnion(), yyDollar[3].str) } yyVAL.union = yyLOCAL - case 2325: + case 2334: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int32 -//line mysql_sql.y:15752 +//line mysql_sql.y:15800 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 2327: + case 2336: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int32 -//line mysql_sql.y:15759 +//line mysql_sql.y:15807 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 2328: + case 2337: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int32 -//line mysql_sql.y:15763 +//line mysql_sql.y:15811 { yyLOCAL = int32(yyDollar[2].item.(int64)) } yyVAL.union = yyLOCAL - case 2329: + case 2338: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int32 -//line mysql_sql.y:15768 +//line mysql_sql.y:15816 { yyLOCAL = int32(-1) } yyVAL.union = yyLOCAL - case 2330: + case 2339: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int32 -//line mysql_sql.y:15772 +//line mysql_sql.y:15820 { yyLOCAL = int32(yyDollar[2].item.(int64)) } yyVAL.union = yyLOCAL - case 2331: + case 2340: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int32 -//line mysql_sql.y:15778 +//line mysql_sql.y:15826 { yyLOCAL = tree.GetDisplayWith(int32(yyDollar[2].item.(int64))) } yyVAL.union = yyLOCAL - case 2332: + case 2341: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.LengthScaleOpt -//line mysql_sql.y:15784 +//line mysql_sql.y:15832 { yyLOCAL = tree.LengthScaleOpt{ DisplayWith: tree.NotDefineDisplayWidth, @@ -34790,10 +34919,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2333: + case 2342: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.LengthScaleOpt -//line mysql_sql.y:15791 +//line mysql_sql.y:15839 { yyLOCAL = tree.LengthScaleOpt{ DisplayWith: tree.GetDisplayWith(int32(yyDollar[2].item.(int64))), @@ -34801,10 +34930,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2334: + case 2343: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.LengthScaleOpt -//line mysql_sql.y:15798 +//line mysql_sql.y:15846 { yyLOCAL = tree.LengthScaleOpt{ DisplayWith: tree.GetDisplayWith(int32(yyDollar[2].item.(int64))), @@ -34812,10 +34941,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2335: + case 2344: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.LengthScaleOpt -//line mysql_sql.y:15807 +//line mysql_sql.y:15855 { yyLOCAL = tree.LengthScaleOpt{ DisplayWith: 10, // MySQL default precision for DECIMAL/NUMERIC @@ -34823,10 +34952,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2336: + case 2345: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.LengthScaleOpt -//line mysql_sql.y:15814 +//line mysql_sql.y:15862 { yyLOCAL = tree.LengthScaleOpt{ DisplayWith: tree.GetDisplayWith(int32(yyDollar[2].item.(int64))), @@ -34834,10 +34963,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2337: + case 2346: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.LengthScaleOpt -//line mysql_sql.y:15821 +//line mysql_sql.y:15869 { yyLOCAL = tree.LengthScaleOpt{ DisplayWith: tree.GetDisplayWith(int32(yyDollar[2].item.(int64))), @@ -34845,73 +34974,73 @@ yydefault: } } yyVAL.union = yyLOCAL - case 2338: + case 2347: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:15830 +//line mysql_sql.y:15878 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 2339: + case 2348: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:15834 +//line mysql_sql.y:15882 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 2340: + case 2349: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:15838 +//line mysql_sql.y:15886 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 2341: + case 2350: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:15844 +//line mysql_sql.y:15892 { } - case 2342: + case 2351: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:15846 +//line mysql_sql.y:15894 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 2346: + case 2355: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:15856 +//line mysql_sql.y:15904 { yyVAL.str = "" } - case 2347: + case 2356: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:15860 +//line mysql_sql.y:15908 { yyVAL.str = string(yyDollar[1].str) } - case 2857: + case 2870: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:16573 +//line mysql_sql.y:16625 { } - case 2858: + case 2871: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:16576 +//line mysql_sql.y:16628 { } - case 2859: + case 2872: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:16580 +//line mysql_sql.y:16632 { } - case 2860: + case 2873: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:16583 +//line mysql_sql.y:16635 { } } diff --git a/pkg/sql/parsers/dialect/mysql/mysql_sql.y b/pkg/sql/parsers/dialect/mysql/mysql_sql.y index 54c21c13d959c..db8dfc565dca6 100644 --- a/pkg/sql/parsers/dialect/mysql/mysql_sql.y +++ b/pkg/sql/parsers/dialect/mysql/mysql_sql.y @@ -152,6 +152,7 @@ func makeWindowSpec(refName *tree.CStr, partitionBy tree.Exprs, orderBy tree.Ord funcArgs tree.FunctionArgs funcArgDecl *tree.FunctionArgDecl funcReturn *tree.ReturnType + pythonFunctionOptions tree.PythonFunctionOptions procName *tree.ProcedureName procArg tree.ProcedureArg @@ -505,6 +506,7 @@ func makeWindowSpec(refName *tree.CStr, partitionBy tree.Exprs, orderBy tree.Ord // Revoke %token REVOKE FUNCTION PRIVILEGES TABLESPACE EXECUTE SUPER GRANT OPTION REFERENCES REPLICATION %token SLAVE CLIENT USAGE RELOAD FILE FILES TEMPORARY ROUTINE EVENT SHUTDOWN +%token CALLED INPUT SCALAR VECTOR // Type Modifiers %token NULLX AUTO_INCREMENT APPROXNUM SIGNED UNSIGNED ZEROFILL ENGINES LOW_CARDINALITY AUTOEXTEND_SIZE @@ -762,7 +764,8 @@ func makeWindowSpec(refName *tree.CStr, partitionBy tree.Exprs, orderBy tree.Ord %type func_arg_decl %type func_return %type func_body_import internal_opt -%type func_lang extension_lang extension_name +%type func_lang extension_lang extension_name func_null_policy func_mode +%type func_python_options_opt %type proc_name %type proc_args_list_opt proc_args_list @@ -8548,7 +8551,7 @@ opt_lang: } create_function_stmt: - CREATE replace_opt FUNCTION func_name '(' func_args_list_opt ')' RETURNS func_return LANGUAGE func_lang func_body_import STRING func_handler_opt + CREATE replace_opt FUNCTION func_name '(' func_args_list_opt ')' RETURNS func_return LANGUAGE func_lang func_body_import STRING func_handler_opt func_python_options_opt { if $13 == "" { yylex.Error("no function body error") @@ -8567,8 +8570,9 @@ create_function_stmt: var Import = $12 var Body = $13 var Handler = $14 + var Options = $15 - $$ = tree.NewCreateFunction( + node := tree.NewCreateFunction( Replace, Name, Args, @@ -8578,6 +8582,9 @@ create_function_stmt: Body, Handler, ) + node.Mode = Options.Mode + node.NullPolicy = Options.NullPolicy + $$ = node } func_name: @@ -8663,6 +8670,47 @@ func_handler: $$ = $2 } +func_python_options_opt: + { + $$ = tree.PythonFunctionOptions{} + } +| MODE func_mode + { + $$ = tree.PythonFunctionOptions{Mode: $2} + } +| func_null_policy + { + $$ = tree.PythonFunctionOptions{NullPolicy: $1} + } +| MODE func_mode func_null_policy + { + $$ = tree.PythonFunctionOptions{Mode: $2, NullPolicy: $3} + } +| func_null_policy MODE func_mode + { + $$ = tree.PythonFunctionOptions{Mode: $3, NullPolicy: $1} + } + +func_mode: + SCALAR + { + $$ = "SCALAR" + } +| VECTOR + { + $$ = "VECTOR" + } + +func_null_policy: + CALLED ON NULL INPUT + { + $$ = "CALLED_ON_NULL_INPUT" + } +| RETURNS NULL ON NULL INPUT + { + $$ = "RETURNS_NULL_ON_NULL_INPUT" + } + create_view_stmt: CREATE view_list_opt VIEW not_exists_opt table_name column_list_opt AS ctas_select_stmt view_tail { @@ -16072,6 +16120,7 @@ non_reserved_keyword: | BLOB | BOOL | BITS_PER_CODE +| CALLED | BRANCH | CATALOG | CATALOGS @@ -16153,6 +16202,7 @@ non_reserved_keyword: | PERSIST | GRANT | INCLUDE +| INPUT | INT | INTEGER | INDEXES @@ -16244,6 +16294,7 @@ non_reserved_keyword: | PROFILES | PROFILE | ROLE +| SCALAR | RULE | RULES | RANGE @@ -16302,6 +16353,7 @@ non_reserved_keyword: | VARBINARY | VARCHAR | VARIABLES +| VECTOR | VIEW | VIRTUAL | WRITE diff --git a/pkg/sql/parsers/dialect/mysql/mysql_sql_test.go b/pkg/sql/parsers/dialect/mysql/mysql_sql_test.go index b213f10e239f3..2fdd99fe24272 100644 --- a/pkg/sql/parsers/dialect/mysql/mysql_sql_test.go +++ b/pkg/sql/parsers/dialect/mysql/mysql_sql_test.go @@ -104,6 +104,56 @@ func TestDiagnosticCountAndLimitSyntax(t *testing.T) { } } +func TestPythonFunctionOptions(t *testing.T) { + stmt, err := ParseOne(context.Background(), + "create function py (x int) returns int language python as 'def py(ctx, x): return x' handler 'py' mode vector returns null on null input", 1) + require.NoError(t, err) + defer stmt.Free() + + create, ok := stmt.(*tree.CreateFunction) + require.True(t, ok) + require.Equal(t, "VECTOR", create.Mode) + require.Equal(t, "RETURNS_NULL_ON_NULL_INPUT", create.NullPolicy) + require.NoError(t, create.Valid()) + require.Equal(t, + "create function py (x int) returns int language python as 'def py(ctx, x): return x' handler 'py' mode vector returns null on null input", + tree.String(stmt, dialect.MYSQL)) + + reversed, err := ParseOne(context.Background(), + "create function py (x int) returns int language python as 'def py(ctx, x): return x' handler 'py' returns null on null input mode scalar", 1) + require.NoError(t, err) + defer reversed.Free() + reversedCreate := reversed.(*tree.CreateFunction) + require.Equal(t, "SCALAR", reversedCreate.Mode) + require.Equal(t, "RETURNS_NULL_ON_NULL_INPUT", reversedCreate.NullPolicy) + + called, err := ParseOne(context.Background(), + "create function py (x int) returns int language python as 'def py(ctx, x): return x' handler 'py' mode vector called on null input", 1) + require.NoError(t, err) + defer called.Free() + calledCreate := called.(*tree.CreateFunction) + require.Equal(t, "VECTOR", calledCreate.Mode) + require.Equal(t, "CALLED_ON_NULL_INPUT", calledCreate.NullPolicy) + + sqlOptions, err := ParseOne(context.Background(), + "create function sql_fn (x int) returns int language sql as 'select $1' mode vector", 1) + require.NoError(t, err) + defer sqlOptions.Free() + require.ErrorContains(t, sqlOptions.(*tree.CreateFunction).Valid(), "require LANGUAGE PYTHON") +} + +func TestPythonFunctionImportIsRejectedBeforeExecution(t *testing.T) { + stmt, err := ParseOne(context.Background(), + "create function py (x int) returns int language python import 'udf.py' handler 'py'", 1) + require.NoError(t, err) + defer stmt.Free() + + create, ok := stmt.(*tree.CreateFunction) + require.True(t, ok) + require.True(t, create.Import) + require.ErrorContains(t, create.Valid(), "immutable artifact catalog") +} + func TestCreateTablePreservesIndexIdentifierCase(t *testing.T) { stmt, err := ParseOne(context.Background(), "create table t (id int, v varchar(20), key MixedCaseIdx(v), unique key `UniQue_Mix`(id))", 1) diff --git a/pkg/sql/parsers/tree/function.go b/pkg/sql/parsers/tree/function.go index 267509c212720..a1e225939ee92 100644 --- a/pkg/sql/parsers/tree/function.go +++ b/pkg/sql/parsers/tree/function.go @@ -179,6 +179,16 @@ type CreateFunction struct { Import bool Body string Handler string + // Mode and NullPolicy are Python routine options. Empty values mean that + // the language default applies; the frontend persists the resolved values + // in the routine body so execution never has to infer them later. + Mode string + NullPolicy string +} + +type PythonFunctionOptions struct { + Mode string + NullPolicy string } func NewCreateFunction(replace bool, name *FunctionName, args FunctionArgs, returnType *ReturnType, lang string, import_ bool, body string, handler string) *CreateFunction { @@ -201,8 +211,26 @@ func (node *CreateFunction) Valid() error { if node.Import { return moerr.NewInvalidInputNoCtx("import") } + if node.Mode != "" || node.NullPolicy != "" { + return moerr.NewInvalidInputNoCtx("Python function options require LANGUAGE PYTHON") + } return nil case string(PYTHON): + if node.Import { + return moerr.NewNotSupportedNoCtx("Python artifact import requires the immutable artifact catalog") + } + if node.Mode != "" { + node.Mode = strings.ToUpper(node.Mode) + if node.Mode != "SCALAR" && node.Mode != "VECTOR" { + return moerr.NewInvalidArgNoCtx("Python function mode", node.Mode) + } + } + if node.NullPolicy != "" { + node.NullPolicy = strings.ToUpper(node.NullPolicy) + if node.NullPolicy != "CALLED_ON_NULL_INPUT" && node.NullPolicy != "RETURNS_NULL_ON_NULL_INPUT" { + return moerr.NewInvalidArgNoCtx("Python function NULL policy", node.NullPolicy) + } + } return nil default: return moerr.NewInvalidArgNoCtx("function language", node.Language) @@ -251,6 +279,14 @@ func (node *CreateFunction) Format(ctx *FmtCtx) { ctx.WriteString(node.Handler) ctx.WriteString("'") } + if node.Mode != "" { + ctx.WriteString(" mode ") + ctx.WriteString(strings.ToLower(node.Mode)) + } + if node.NullPolicy != "" { + ctx.WriteByte(' ') + ctx.WriteString(strings.ToLower(strings.ReplaceAll(node.NullPolicy, "_", " "))) + } } func (node *CreateFunction) GetStatementType() string { return "CreateFunction" } diff --git a/pkg/sql/plan/base_binder.go b/pkg/sql/plan/base_binder.go index dfa53a9257bbe..673ae016cb82e 100644 --- a/pkg/sql/plan/base_binder.go +++ b/pkg/sql/plan/base_binder.go @@ -4291,8 +4291,24 @@ func bindFuncExprImplUdf( return nil, moerr.NewNotSupportedf(b.GetContext(), "function '%s'", name) } - switch udf.Language { - case string(tree.SQL): + switch strings.ToLower(udf.Language) { + case strings.ToLower(string(tree.SQL)): + // A current SQL revision enters the common dependency envelope before + // its compatibility lowering expands the body. Legacy rows have no + // revision and retain the old path until an explicit replacement + // publishes a current shared revision. + if b.builder != nil && udf.Revision != 0 { + routineCall, err := udf.GetRoutineCall() + if err != nil { + return nil, moerr.NewInvalidInputf(b.GetContext(), "SQL routine is not executable: %v", err) + } + if err := b.builder.assignRoutineCallsite(routineCall); err != nil { + return nil, moerr.NewInvalidInputf(b.GetContext(), "%v", err) + } + if err := b.builder.recordRoutinePlanDependency(routineCall); err != nil { + return nil, moerr.NewInvalidInputf(b.GetContext(), "%v", err) + } + } parserSQLMode := "PIPES_AS_CONCAT" if udf.SQLMode != nil { parserSQLMode = *udf.SQLMode @@ -4337,7 +4353,7 @@ func bindFuncExprImplUdf( } } return expr, nil - case string(tree.PYTHON): + case strings.ToLower(string(tree.PYTHON)): expr, err := b.bindPythonUdf(udf, astArgs, depth) if err != nil { return nil, err @@ -4519,31 +4535,60 @@ func correlateSQLUdfArgument(arg *plan.Expr, depth int32) (*plan.Expr, bool) { } func (b *baseBinder) bindPythonUdf(udf *function.Udf, astArgs []tree.Expr, depth int32) (*plan.Expr, error) { - args := make([]*Expr, 2*len(astArgs)+2) - - // python udf self info and query context - args[0] = udf.GetPlanExpr() - - // bind ast function's args + if len(astArgs) != len(udf.GetArgsType()) { + return nil, moerr.NewInvalidInputf(b.GetContext(), "Python routine %s expects %d arguments, got %d", udf.Db, len(udf.GetArgsType()), len(astArgs)) + } + args := make([]*Expr, len(astArgs)) for idx, arg := range astArgs { expr, err := b.impl.BindExpr(arg, depth, false) if err != nil { return nil, err } - args[idx+1] = expr + required := udf.GetArgsType()[idx] + actual := makeTypeByPlan2Expr(expr) + if !actual.Eq(required) { + canCast, _ := function.PythonUdfArgTypeMatch([]types.Type{actual}, []types.Type{required}) + if !canCast { + return nil, moerr.NewInvalidInputf(b.GetContext(), "Python routine argument %d has type %s, expected %s", idx+1, actual.String(), required.String()) + } + expr, err = appendCastBeforeExpr(b.GetContext(), expr, makePlan2Type(&required)) + if err != nil { + return nil, err + } + } + args[idx] = expr } - - // function args - fArgTypes := udf.GetArgsPlanType() - for i, t := range fArgTypes { - args[len(astArgs)+i+1] = &Expr{Typ: *t} + // Execution identity is intentionally absent from the persisted plan. A + // prepared plan can be executed many times; the physical evaluator creates + // a fresh statement fence from the current process/query identity. + routineCall, err := udf.GetRoutineCall() + if err != nil { + // RETURNING has its own semantic prohibition for external routines. + // Preserve that deterministic SQL diagnostic even when a test or a + // partially upgraded catalog supplies a Python descriptor without the + // executable identity that the normal path requires. + if b.builder != nil && b.builder.bindingReturningProjection && + strings.Contains(err.Error(), "stable catalog identity") { + return nil, returningNotSupported(b.builder, "external UDF in RETURNING expression") + } + return nil, moerr.NewInvalidInputf(b.GetContext(), "Python routine is not executable: %v", err) } - - // function ret - fRetType := udf.GetRetPlanType() - args[2*len(astArgs)+1] = &Expr{Typ: *fRetType} - - return BindFuncExprImplByPlanExpr(b.GetContext(), "python_user_defined_function", args) + if b.builder != nil { + if err := b.builder.assignRoutineCallsite(routineCall); err != nil { + return nil, moerr.NewInvalidInputf(b.GetContext(), "%v", err) + } + if err := b.builder.recordRoutinePlanDependency(routineCall); err != nil { + return nil, moerr.NewInvalidInputf(b.GetContext(), "%v", err) + } + } + return &plan.Expr{ + Typ: *udf.GetRetPlanType(), + Expr: &plan.Expr_F{F: &plan.Function{ + Func: &plan.ObjectRef{Obj: function.EncodeOverloadID(function.PYTHON_UDF, 0), ObjName: "python_user_defined_function"}, + Args: args, + RoutineCall: routineCall, + }}, + }, nil } func isFindInSetName(name string) bool { diff --git a/pkg/sql/plan/build_util.go b/pkg/sql/plan/build_util.go index 7138830a7cb81..138c9138c8b41 100644 --- a/pkg/sql/plan/build_util.go +++ b/pkg/sql/plan/build_util.go @@ -128,6 +128,17 @@ func GetFunctionArgTypeStrFromAst(arg tree.FunctionArg) (string, error) { return GetFunctionTypeStrFromAst(argDecl.Type) } +// GetFunctionTypeFromAst retains the full type attributes needed by external +// routine ABIs. GetFunctionTypeStrFromAst intentionally returns only the +// logical catalog name for legacy UDF overload identity. +func GetFunctionTypeFromAst(typRef tree.ResolvableTypeReference) (types.Type, error) { + typ, err := getTypeFromAst(moerr.Context(), typRef) + if err != nil { + return types.Type{}, err + } + return types.NewWithCharset(types.T(typ.Id), typ.Width, typ.Scale, uint8(typ.Charset)), nil +} + func GetFunctionTypeStrFromAst(typRef tree.ResolvableTypeReference) (string, error) { typ, err := getTypeFromAst(moerr.Context(), typRef) if err != nil { diff --git a/pkg/sql/plan/deepcopy.go b/pkg/sql/plan/deepcopy.go index 30000f0b55066..ea6a7c9dfb887 100644 --- a/pkg/sql/plan/deepcopy.go +++ b/pkg/sql/plan/deepcopy.go @@ -858,6 +858,7 @@ func DeepCopyQuery(qry *plan.Query) *plan.Query { ApplySqlSelectLimit: qry.ApplySqlSelectLimit, DetectSqls: slices.Clone(qry.DetectSqls), CatalogDependencies: make([]*plan.ObjectRef, len(qry.CatalogDependencies)), + RoutineDependencies: make([]*plan.RoutinePlanDependency, len(qry.RoutineDependencies)), } for idx, node := range qry.Nodes { newQry.Nodes[idx] = DeepCopyNode(node) @@ -875,6 +876,11 @@ func DeepCopyQuery(qry *plan.Query) *plan.Query { } } } + for idx, dependency := range qry.RoutineDependencies { + if dependency != nil { + newQry.RoutineDependencies[idx] = proto.Clone(dependency).(*plan.RoutinePlanDependency) + } + } return newQry } @@ -1262,6 +1268,10 @@ func DeepCopyExpr(expr *Expr) *Expr { for idx, arg := range item.F.Args { newArgs[idx] = DeepCopyExpr(arg) } + var routineCall *plan.RoutineCall + if item.F.RoutineCall != nil { + routineCall = proto.Clone(item.F.RoutineCall).(*plan.RoutineCall) + } newExpr.Expr = &plan.Expr_F{ F: &plan.Function{ Func: DeepCopyObjectRef(item.F.Func), @@ -1269,6 +1279,7 @@ func DeepCopyExpr(expr *Expr) *Expr { AggConfig: bytes.Clone(item.F.AggConfig), AggConfigType: item.F.AggConfigType, SyntaxExplicitCast: item.F.SyntaxExplicitCast, + RoutineCall: routineCall, }, } diff --git a/pkg/sql/plan/deepcopy_test.go b/pkg/sql/plan/deepcopy_test.go index 23e01990daaca..da683be38de7c 100644 --- a/pkg/sql/plan/deepcopy_test.go +++ b/pkg/sql/plan/deepcopy_test.go @@ -381,6 +381,20 @@ func TestDeepCopyQueryPreservesExecutionMetadata(t *testing.T) { StmtType: planpb.Query_SELECT, Headings: []string{"background"}, }}, + RoutineDependencies: []*planpb.RoutinePlanDependency{{ + FunctionRef: &planpb.FunctionRef{ + FunctionId: 41, + Revision: 7, + NamespaceVersion: 12, + AccountId: 9, + DatabaseId: 8, + }, + Language: "python", + ContractVersion: 1, + DefinitionFingerprint: "fingerprint", + ArtifactDigest: "artifact", + EnvironmentDigest: "environment", + }}, } cloned := DeepCopyQuery(source) @@ -398,13 +412,18 @@ func TestDeepCopyQueryPreservesExecutionMetadata(t *testing.T) { require.Equal(t, int64(8), cloned.MaxDop) require.Len(t, cloned.BackgroundQueries, 1) require.NotSame(t, source.BackgroundQueries[0], cloned.BackgroundQueries[0]) + require.Equal(t, source.RoutineDependencies, cloned.RoutineDependencies) + require.NotSame(t, source.RoutineDependencies[0], cloned.RoutineDependencies[0]) + require.NotSame(t, source.RoutineDependencies[0].FunctionRef, cloned.RoutineDependencies[0].FunctionRef) cloned.Steps[0] = 99 cloned.Headings[0] = "changed" cloned.BackgroundQueries[0].Headings[0] = "changed" + cloned.RoutineDependencies[0].FunctionRef.Revision = 99 require.Equal(t, int32(3), source.Steps[0]) require.Equal(t, "id", source.Headings[0]) require.Equal(t, "background", source.BackgroundQueries[0].Headings[0]) + require.Equal(t, uint64(7), source.RoutineDependencies[0].FunctionRef.Revision) } func TestDeepCopyDataDefinitionCreateTablePreservesExecutionFields(t *testing.T) { diff --git a/pkg/sql/plan/expr_hash.go b/pkg/sql/plan/expr_hash.go index 64b47b6556aed..6c2b716381732 100644 --- a/pkg/sql/plan/expr_hash.go +++ b/pkg/sql/plan/expr_hash.go @@ -127,6 +127,17 @@ func hashExprInto(h writeByter, expr *plan.Expr) { } else { writeUint32(h, 0) } + if v.F.RoutineCall == nil { + writeByte(h, 0) + } else { + writeByte(h, 1) + if b, err := v.F.RoutineCall.Marshal(); err == nil { + writeUint32(h, uint32(len(b))) + _, _ = h.Write(b) + } else { + writeUint32(h, 0) + } + } for _, a := range v.F.Args { hashExprInto(h, a) } @@ -337,6 +348,9 @@ func exprStructuralEqual(a, b *plan.Expr) bool { if !objectRefEqual(av.F.Func, bv.F.Func) { return false } + if !routineCallEqual(av.F.RoutineCall, bv.F.RoutineCall) { + return false + } if len(av.F.Args) != len(bv.F.Args) { return false } @@ -396,6 +410,21 @@ func exprStructuralEqual(a, b *plan.Expr) bool { } } +func routineCallEqual(a, b *plan.RoutineCall) bool { + if a == b { + return true + } + if a == nil || b == nil { + return false + } + ab, aerr := a.Marshal() + bb, berr := b.Marshal() + if aerr != nil || berr != nil { + return false + } + return bytes.Equal(ab, bb) +} + func literalEqual(typ plan.Type, a, b *plan.Literal) bool { if a == b { return true diff --git a/pkg/sql/plan/expr_hash_test.go b/pkg/sql/plan/expr_hash_test.go index 56f67ab0972be..70aa4e372116c 100644 --- a/pkg/sql/plan/expr_hash_test.go +++ b/pkg/sql/plan/expr_hash_test.go @@ -67,6 +67,42 @@ func TestExprStructuralHashDistinguishesObjectRef(t *testing.T) { require.True(t, exprStructuralEqual(a, c)) } +func TestExprStructuralHashIncludesRoutineIdentity(t *testing.T) { + call := func(revision uint64) *planpb.RoutineCall { + return &planpb.RoutineCall{ + ContractVersion: 1, + FunctionRef: &planpb.FunctionRef{ + FunctionId: 17, + Revision: revision, + NamespaceVersion: 1, + AccountId: 9, + DatabaseId: 11, + }, + Language: "python", + Volatility: "VOLATILE", + NullPolicy: "CALLED_ON_NULL_INPUT", + ReturnType: planpb.Type{Id: int32(types.T_int64)}, + } + } + mk := func(revision uint64) *planpb.Expr { + return &planpb.Expr{ + Typ: planpb.Type{Id: int32(types.T_int64)}, + Expr: &planpb.Expr_F{F: &planpb.Function{ + Func: &planpb.ObjectRef{ObjName: "python_user_defined_function", Obj: 1}, + RoutineCall: call(revision), + }}, + } + } + + a := mk(1) + b := mk(2) + c := mk(1) + require.NotEqual(t, exprStructuralHash(a), exprStructuralHash(b)) + require.False(t, exprStructuralEqual(a, b)) + require.Equal(t, exprStructuralHash(a), exprStructuralHash(c)) + require.True(t, exprStructuralEqual(a, c)) +} + func TestExprStructuralIdentityIncludesNegativeAuxID(t *testing.T) { a := int64Lit(1) a.AuxId = -1 diff --git a/pkg/sql/plan/function/list_builtIn.go b/pkg/sql/plan/function/list_builtIn.go index af94c6949f76b..d2471af43700e 100644 --- a/pkg/sql/plan/function/list_builtIn.go +++ b/pkg/sql/plan/function/list_builtIn.go @@ -16229,15 +16229,19 @@ var supportedOthersBuiltIns = []FuncNew{ // function `python_user_defined_function` { functionId: PYTHON_UDF, - class: plan.Function_INTERNAL | plan.Function_STRICT, + class: plan.Function_INTERNAL, layout: STANDARD_FUNCTION, checkFn: checkPythonUdf, Overloads: []overload{ { overloadId: 0, retType: pythonUdfRetType, + // A Python routine is user code. It may observe invocation + // context or maintain process-local state, so planning must never + // execute it once and broadcast the result to all rows. + volatile: true, newOp: func() executeLogicOfOverload { - return runPythonUdf + return rejectPythonJSONPlan }, }, }, diff --git a/pkg/sql/plan/function/python_udf.go b/pkg/sql/plan/function/python_udf.go index c26bdf63d7375..66d956168a843 100644 --- a/pkg/sql/plan/function/python_udf.go +++ b/pkg/sql/plan/function/python_udf.go @@ -1,10 +1,10 @@ -// Copyright 2023 Matrix Origin +// Copyright 2026 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 +// 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, @@ -15,11 +15,15 @@ package function import ( - "encoding/json" + "strconv" + "github.com/matrixorigin/matrixone/pkg/udf/udferr" + "github.com/matrixorigin/matrixone/pkg/util/errutil" + + "github.com/google/uuid" "github.com/matrixorigin/matrixone/pkg/container/types" "github.com/matrixorigin/matrixone/pkg/container/vector" - "github.com/matrixorigin/matrixone/pkg/udf" + "github.com/matrixorigin/matrixone/pkg/udf/protocol" "github.com/matrixorigin/matrixone/pkg/vm/process" ) @@ -42,8 +46,20 @@ func checkPythonUdf(overloads []overload, inputs []types.Type) checkResult { requiredArgs := inputs[size+1 : 2*size+1] needCast := false for i := 0; i < size; i++ { - if receivedArgs[i].Oid != requiredArgs[i].Oid { - canCast, _ := fixedImplicitTypeCast(receivedArgs[i], requiredArgs[i].Oid) + if !pythonTypesEqual(receivedArgs[i], requiredArgs[i]) { + canCast := false + if receivedArgs[i].Oid == requiredArgs[i].Oid { + canCast = pythonSameOIDCanNormalize(receivedArgs[i], requiredArgs[i]) + } else { + canCast, _ = fixedImplicitTypeCast(receivedArgs[i], requiredArgs[i].Oid) + } + if canCast && receivedArgs[i].Oid == requiredArgs[i].Oid { + // SQL's cast executor is also the type normalizer for Python's + // frozen descriptor. In particular, DECIMAL scale and precision + // must be normalized before Arrow encoding; comparing only OID + // would reinterpret the same coefficient at the wrong scale. + canCast = true + } if !canCast { return newCheckResultWithFailure(failedFunctionParametersWrong) } @@ -62,65 +78,205 @@ func checkPythonUdf(overloads []overload, inputs []types.Type) checkResult { return newCheckResultWithSuccess(0) } +func pythonTypesEqual(left, right types.Type) bool { + // Type.Eq applies SQL value semantics. In particular, integer display + // width and the legacy scale marker are not part of the value contract; + // CASE and table expressions are allowed to materialize those fields + // differently while retaining the same fixed-width Arrow type. Decimal, + // string, temporal, and vector metadata remain part of the comparison. + return left.Eq(right) +} + +// PythonUdfArgTypeMatch applies the ordinary implicit cast graph while also +// treating the complete frozen descriptor as the exact-match key. The shared +// UDF resolver historically compared only OIDs, which made two Python +// overloads such as DECIMAL(18,2) and DECIMAL(18,6) indistinguishable and +// allowed a non-exact candidate to win with the same cost as an exact one. +func PythonUdfArgTypeMatch(from, to []types.Type) (bool, int) { + if len(from) != len(to) { + return false, -1 + } + length := len(from) + cost := 0 + for index := range from { + if pythonTypesEqual(from[index], to[index]) { + continue + } + if pythonSameOIDCanNormalize(from[index], to[index]) { + // A same-OID descriptor change is a SQL cast to the declared + // width/scale. It is valid, but less specific than an exact match. + cost++ + continue + } + if from[index].Oid == to[index].Oid { + return false, -1 + } + canCast, castCost := fixedImplicitTypeCast(from[index], to[index].Oid) + if !canCast { + return false, -1 + } + if castCost == 1 { + cost += castCost + } else { + cost += castCost * length + } + } + return true, cost +} + +// pythonSameOIDCanNormalize reports whether a descriptor change with the same +// SQL OID has a meaningful SQL cast. Fixed-size vector dimensions are part of +// the value shape: the existing array->array cast preserves bytes when the +// element OID is unchanged, so accepting VECF32(4) for VECF32(3) would publish +// a value with a descriptor that lies about its child count. Other supported +// same-OID metadata (decimal precision/scale, text width/charset, and temporal +// scale) is normalized by the ordinary SQL cast executor. +func pythonSameOIDCanNormalize(from, to types.Type) bool { + if from.Oid != to.Oid || pythonTypesEqual(from, to) { + return false + } + switch from.Oid { + case types.T_array_float32, types.T_array_float64: + return false + default: + return true + } +} + +// PythonUdfArgTypeCast returns the exact descriptor that the Python handler +// declared for every argument. The generic UDF cast helper only receives an +// OID list, so it intentionally preserves a same-OID source type. That is +// unsafe for Python's frozen contract: DECIMAL(18,2) and DECIMAL(18,6) have +// the same OID but different Arrow interpretation. The SQL cast expression +// must therefore materialize the target descriptor even when only metadata +// differs. +func PythonUdfArgTypeCast(from, to []types.Type) []types.Type { + if len(from) != len(to) { + return nil + } + castTypes := make([]types.Type, len(from)) + for index := range from { + if pythonTypesEqual(from[index], to[index]) { + castTypes[index] = from[index] + continue + } + if from[index].Oid == to[index].Oid && !pythonSameOIDCanNormalize(from[index], to[index]) { + return nil + } + castTypes[index] = to[index] + } + return castTypes +} + // param parameters is same with param inputs in function checkPythonUdf func pythonUdfRetType(parameters []types.Type) types.Type { return parameters[len(parameters)-1] } -// param parameters has two parts: -// 1. parameters[0]: const vector udf -// 2. parameters[1:]: data vectors -func runPythonUdf(parameters []*vector.Vector, result vector.FunctionResultWrapper, proc *process.Process, length int, selectList *FunctionSelectList) error { - // udf with context - u := &UdfWithContext{} - bytes, _ := vector.GenerateFunctionStrParameter(parameters[0]).GetStrValue(0) - err := json.Unmarshal(bytes, u) - if err != nil { - return err +// rejectPythonJSONPlan is kept as the explicit stale-plan boundary for the +// historical overload id. Long-term execution enters through the typed +// RoutineCall field and ExternalRoutineEval. +func rejectPythonJSONPlan(_ []*vector.Vector, _ vector.FunctionResultWrapper, _ *process.Process, _ int, _ *FunctionSelectList) error { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python JSON plan execution is not supported; reprepare the statement") +} + +func validatePythonRoutineDescriptor(descriptor *vector.Vector) error { + if descriptor == nil { + return udferr.Newf("python udf: missing routine descriptor") } + if !descriptor.IsConst() { + return udferr.Newf("python udf: routine descriptor must be constant") + } + if descriptor.Length() == 0 { + return udferr.Newf("python udf: routine descriptor is empty") + } + return nil +} + +func validatePythonInputVectors(inputs []*vector.Vector, args []types.Type, length int) error { + if len(inputs) != len(args) { + return udferr.Newf("python udf: input column count %d does not match routine argument count %d", len(inputs), len(args)) + } + for index, input := range inputs { + if input == nil { + return udferr.Newf("python udf: input vector %d is nil", index) + } + if input.Length() == 0 { + return udferr.Newf("python udf: input vector %d is empty", index) + } + if !input.IsConst() && input.Length() < length { + return udferr.Newf("python udf: input vector %d is shorter than invocation length", index) + } + if input.GetType() == nil || !pythonTypesEqual(*input.GetType(), args[index]) { + actual := "" + if input.GetType() != nil { + actual = input.GetType().String() + } + return udferr.Newf("python udf: input vector %d type %s does not match %s", index, actual, args[index].String()) + } + } + return nil +} - // request - body := &NonSqlUdfBody{} - err = json.Unmarshal([]byte(u.Body), body) +func invocationTuple(context map[string]string, queryID string, accountID uint32) (protocol.FencingTuple, error) { + statementID := context["statement_id"] + if statementID == "" { + statementID = queryID + } + if statementID == "" { + id, err := uuid.NewV7() + if err != nil { + return protocol.FencingTuple{}, errutil.Wrapf(err, "python udf: create statement fence") + } + statementID = id.String() + } + invocationID, err := uuid.NewV7() if err != nil { - return err - } - request := &udf.Request{ - Udf: &udf.Udf{ - Handler: body.Handler, - IsImport: body.Import, - Body: body.Body, - RetType: t2DataType[u.GetRetType().Oid], - Language: udf.LanguagePython, - Db: u.Db, - ModifiedTime: u.ModifiedTime, - }, - Vectors: make([]*udf.DataVector, len(parameters)-1), - Length: int64(length), - Type: udf.RequestType_DataRequest, - Context: u.Context, - } - for i := 1; i < len(parameters); i++ { - dataVector, _ := vector2DataVector(parameters[i]) - request.Vectors[i-1] = dataVector - } - - // getPkg - reader := &DefaultPkgReader{ - Proc: proc, - } - - // run - response, err := proc.Base.UdfService.Run(proc.Ctx, request, reader) + return protocol.FencingTuple{}, errutil.Wrapf(err, "python udf: create invocation fence") + } + groupID := context["group_id"] + if groupID == "" { + // The current physical adapter owns one group per invocation. A stable + // statement-only group would reject the second batch or second routine + // in the same statement; the scheduler may supply a shared group and + // explicit epoch when it is introduced. + groupID = statementID + "/python/" + invocationID.String() + } else if context["group_epoch"] == "" { + return protocol.FencingTuple{}, udferr.Newf("python udf: explicit group_id requires group_epoch") + } + groupEpoch, err := positiveContextUint(context, "group_epoch", 1) if err != nil { - return err + return protocol.FencingTuple{}, err } - - // response - err = writeResponse(response, result) + leaseEpoch, err := positiveContextUint(context, "lease_epoch", 1) if err != nil { - return err + return protocol.FencingTuple{}, err } + return protocol.FencingTuple{ + AccountID: uint64(accountID), + StatementID: statementID, + GroupID: groupID, + GroupEpoch: groupEpoch, + InvocationID: invocationID.String(), + LeaseEpoch: leaseEpoch, + }, nil +} - return nil +// NewInvocationTuple is shared by the physical external evaluator and protocol +// tests. A prepared plan supplies no execution identity; the caller provides +// the current query id and this helper creates a fresh invocation fence. +func NewInvocationTuple(context map[string]string, queryID string, accountID uint32) (protocol.FencingTuple, error) { + return invocationTuple(context, queryID, accountID) +} + +func positiveContextUint(context map[string]string, key string, fallback uint64) (uint64, error) { + value := context[key] + if value == "" { + return fallback, nil + } + parsed, err := strconv.ParseUint(value, 10, 64) + if err != nil || parsed == 0 { + return 0, udferr.Newf("python udf: invalid %s %q", key, value) + } + return parsed, nil } diff --git a/pkg/sql/plan/function/udf.go b/pkg/sql/plan/function/udf.go index feb44e2f46227..121a09831321c 100644 --- a/pkg/sql/plan/function/udf.go +++ b/pkg/sql/plan/function/udf.go @@ -1,10 +1,10 @@ -// Copyright 2023 Matrix Origin +// Copyright 2026 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 +// 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, @@ -15,714 +15,581 @@ package function import ( - "context" + "crypto/sha256" + "encoding/hex" "encoding/json" "io" - "time" + "reflect" + "strings" + "unicode/utf8" + + "github.com/matrixorigin/matrixone/pkg/udf/udferr" + "github.com/matrixorigin/matrixone/pkg/util/errutil" - "github.com/google/uuid" - "github.com/matrixorigin/matrixone/pkg/common/moerr" - "github.com/matrixorigin/matrixone/pkg/container/bytejson" "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/pb/plan" "github.com/matrixorigin/matrixone/pkg/udf" - "github.com/matrixorigin/matrixone/pkg/vm/process" - "golang.org/x/sync/errgroup" + pythonudf "github.com/matrixorigin/matrixone/pkg/udf/python" ) type Udf struct { - // sql string, or json string of NonSqlUdfBody - Body string `json:"body"` - Language string `json:"language"` - RetType string `json:"rettype"` - Args []*Arg `json:"args"` - Db string `json:"db"` - ModifiedTime string `json:"modified_time"` - SQLMode *string `json:"-"` - - ArgsType []types.Type `json:"-"` + Body string `json:"body"` + Language string `json:"language"` + RetType string `json:"rettype"` + Args []*Arg `json:"args"` + Db string `json:"db"` + ModifiedTime string `json:"modified_time"` + // FunctionID and Revision are resolved from the shared catalog. They are + // part of the executable identity; the planner must never re-resolve a + // Python routine by name or latest revision at execution time. + FunctionID int64 `json:"function_id,omitempty"` + AccountID uint64 `json:"account_id,omitempty"` + DatabaseID uint64 `json:"database_id,omitempty"` + Revision uint64 `json:"revision,omitempty"` + NamespaceFingerprint string `json:"namespace_fingerprint,omitempty"` + NamespaceVersion uint64 `json:"namespace_version,omitempty"` + // SQL revisions use the same immutable identity envelope as Python. These + // fields are empty for legacy SQL rows, which intentionally remain on the + // historical text-expansion path until they are explicitly replaced. + DefinitionFingerprint string `json:"definition_fingerprint,omitempty"` + SemanticDefinitionSchemaVersion int `json:"semantic_definition_schema_version,omitempty"` + Volatility string `json:"volatility,omitempty"` + NullPolicy string `json:"null_policy,omitempty"` + SQLMode *string `json:"-"` + ArgsType []types.Type `json:"-"` + // PythonArgTypes and PythonReturnType preserve the exact SQL declaration + // for Python's Arrow contract. The legacy catalog's args/rettype columns + // intentionally keep only logical type names, which is insufficient for + // width and scale validation. + PythonArgTypes []PythonTypeDescriptor `json:"-"` + PythonReturnType *PythonTypeDescriptor `json:"-"` } type UdfWithContext struct { *Udf `json:"udf"` - Context map[string]string `json:"context"` // context map + Context map[string]string `json:"context"` + // PlanContractVersion is retained only for the guarded bridge while the + // typed RoutineCall plan node is rolled out. A missing or unknown value is + // rejected before the handler is reached. + PlanContractVersion int `json:"plan_contract_version"` } -type NonSqlUdfBody struct { - Handler string `json:"handler"` - Import bool `json:"import"` - Body string `json:"body"` +// PythonRoutineBody is the single supported Python routine definition. The +// catalog must persist mode and NULL policy with the source so execution does +// not infer either from a generic SQL function class bit. +type PythonRoutineBody struct { + DefinitionSchemaVersion int `json:"definition_schema_version"` + Handler string `json:"handler"` + Source string `json:"source,omitempty"` + Mode string `json:"mode"` + NullPolicy string `json:"null_policy"` + ABIContract string `json:"abi_contract"` + AdapterVersion string `json:"adapter_version"` + ArtifactDigest string `json:"artifact_digest"` + EnvironmentDigest string `json:"environment_digest"` + SDKVersion string `json:"sdk_version"` + ArgTypes []PythonTypeDescriptor `json:"arg_types,omitempty"` + ReturnType *PythonTypeDescriptor `json:"return_type,omitempty"` } -// Arg of Udf -type Arg struct { - Name string `json:"name"` - Type string `json:"type"` +// PythonSignatureMetadata is the canonical identity metadata for a Python +// routine. The input descriptor is the overload key; the return descriptor is +// persisted alongside it because it is immutable for the lifetime of the +// Function identity even though it does not participate in overload choice. +// Both JSON values are canonical encodings of the exact Arrow descriptors. +func PythonSignatureMetadata( + args []PythonTypeDescriptor, + returnType *PythonTypeDescriptor, +) (canonicalInput, canonicalReturn, fingerprint string, err error) { + if returnType == nil { + return "", "", "", udferr.Newf("python routine is missing return descriptor") + } + if args == nil { + args = []PythonTypeDescriptor{} + } + for index, descriptor := range args { + if err := validatePythonTypeDescriptor(descriptor); err != nil { + return "", "", "", errutil.Wrapf(err, "python routine argument descriptor %d", index) + } + } + if err := validatePythonTypeDescriptor(*returnType); err != nil { + return "", "", "", errutil.Wrapf(err, "python routine return descriptor") + } + inputBytes, err := json.Marshal(args) + if err != nil { + return "", "", "", errutil.Wrapf(err, "marshal Python input descriptor") + } + returnBytes, err := json.Marshal(returnType) + if err != nil { + return "", "", "", errutil.Wrapf(err, "marshal Python return descriptor") + } + if len(inputBytes) > types.MaxStringSize || len(returnBytes) > types.MaxStringSize { + return "", "", "", udferr.Newf("python signature descriptor exceeds the %d-byte catalog limit", types.MaxStringSize) + } + keyBytes, err := json.Marshal(struct { + SchemaVersion int `json:"schema_version"` + Input []PythonTypeDescriptor `json:"input_descriptor"` + Return PythonTypeDescriptor `json:"return_descriptor"` + }{ + SchemaVersion: udf.PythonSignatureKeySchemaVersion, + Input: args, + Return: *returnType, + }) + if err != nil { + return "", "", "", errutil.Wrapf(err, "marshal Python signature key") + } + digest := sha256.New() + digest.Write([]byte("matrixone-python-udf-signature\x00")) + digest.Write(keyBytes) + return string(inputBytes), string(returnBytes), hex.EncodeToString(digest.Sum(nil)), nil } -func (u *Udf) GetPlanExpr() *plan.Expr { - uid, _ := uuid.NewV7() - bytes, _ := json.Marshal(&UdfWithContext{ - Udf: u, - Context: map[string]string{ - "queryId": uid.String(), - }, - }) - return &plan.Expr{ - Typ: *type2PlanType(types.T_text.ToType()), - Expr: &plan.Expr_Lit{ - Lit: &plan.Literal{ - Isnull: false, - Value: &plan.Literal_Sval{ - Sval: string(bytes), - }, - }, - }, +// DecodePythonRoutineBody decodes the one catalog representation accepted by +// the Python execution path. Catalog data is an execution authority, so an +// unknown field or a second JSON value must be rejected instead of being +// silently ignored by encoding/json. +func DecodePythonRoutineBody(raw string) (PythonRoutineBody, error) { + decoder := json.NewDecoder(strings.NewReader(raw)) + decoder.DisallowUnknownFields() + var body PythonRoutineBody + if err := decoder.Decode(&body); err != nil { + return PythonRoutineBody{}, err } + var extra json.RawMessage + if err := decoder.Decode(&extra); err != io.EOF { + if err == nil { + return PythonRoutineBody{}, udferr.Newf("python routine body contains multiple JSON values") + } + return PythonRoutineBody{}, err + } + if err := body.Validate(); err != nil { + return PythonRoutineBody{}, err + } + return body, nil } -func (u *Udf) GetArgsPlanType() []*plan.Type { - typ := u.GetArgsType() - ptyp := make([]*plan.Type, len(typ)) - for i, t := range typ { - ptyp[i] = type2PlanType(t) +// PythonRoutineFingerprint returns the digest of the canonical current +// definition. The digest is persisted with an immutable revision and is +// checked before dispatch; source text alone is not an executable identity. +func PythonRoutineFingerprint(raw string) (string, error) { + body, err := DecodePythonRoutineBody(raw) + if err != nil { + return "", err } - return ptyp + return PythonRoutineBodyFingerprint(body) } -func (u *Udf) GetRetPlanType() *plan.Type { - typ := u.GetRetType() - return type2PlanType(typ) +func PythonRoutineBodyFingerprint(body PythonRoutineBody) (string, error) { + if err := body.Validate(); err != nil { + return "", err + } + return pythonudf.DefinitionFingerprint( + body.DefinitionSchemaVersion, + body.Handler, body.Mode, body.NullPolicy, + body.ABIContract, body.AdapterVersion, + body.ArtifactDigest, body.EnvironmentDigest, body.SDKVersion, + body.ArgTypes, *body.ReturnType, + ) } -func (u *Udf) GetArgsType() []types.Type { - return u.ArgsType +// SQLRoutineFingerprint is the integrity key for the current shared SQL +// revision row. The full typed SQL semantic IR is a later catalog field; +// until that field is published, the revision's canonical stored argument +// signature, return type, and SQL body form the bounded semantic definition +// accepted by the SQL binder. Keeping this encoding here makes the writer, +// resolver, and plan-cache validator use one implementation instead of +// independently hashing source text. +func SQLRoutineFingerprint(body, argTypes, returnType string) (string, error) { + if body == "" || returnType == "" { + return "", udferr.Newf("SQL routine definition is incomplete") + } + encoded, err := json.Marshal(struct { + SchemaVersion int `json:"schema_version"` + Body string `json:"body"` + ArgTypes string `json:"arg_types"` + ReturnType string `json:"return_type"` + }{ + SchemaVersion: udf.SQLDefinitionSchemaVersion, + Body: body, + ArgTypes: argTypes, + ReturnType: returnType, + }) + if err != nil { + return "", errutil.Wrapf(err, "marshal SQL routine definition") + } + digest := sha256.New() + digest.Write([]byte("matrixone-sql-udf-definition\x00")) + digest.Write(encoded) + return hex.EncodeToString(digest.Sum(nil)), nil } -func (u *Udf) GetRetType() types.Type { - return types.Types[u.RetType].ToType() +// DecodeUdfWithContext is retained only as a diagnostic boundary for old +// persisted/demo plans. JSON is not an executable representation of a new +// Python routine, so callers must rebind the statement from the current typed +// catalog contract instead of decoding and dispatching this payload. +func DecodeUdfWithContext(raw []byte) (UdfWithContext, error) { + _ = raw + return UdfWithContext{}, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python JSON plan is not executable; rebind the statement from the current typed catalog contract") } -func type2PlanType(typ types.Type) *plan.Type { - return &plan.Type{ - Id: int32(typ.Oid), - Width: typ.Width, - Scale: typ.Scale, - Charset: uint32(typ.Charset), +// Validate checks fields that are independent of the catalog argument list. +// The argument count is checked by Udf.ValidatePythonTypeContract after the +// legacy catalog args column has been decoded. +func (body PythonRoutineBody) Validate() error { + if body.DefinitionSchemaVersion != udf.PythonDefinitionSchemaVersion { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: python definition schema %d is not supported", body.DefinitionSchemaVersion) + } + if body.Handler == "" || body.Source == "" { + return udferr.Newf("python routine handler and source are required") + } + if !utf8.ValidString(body.Source) { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python source is not valid UTF-8") + } + if int64(len([]byte(body.Source))) > pythonudf.DefaultMaxArtifactBytes { + return udferr.Newf("RESOURCE_EXHAUSTED: Python source exceeds %d bytes", pythonudf.DefaultMaxArtifactBytes) + } + if strings.Contains(body.Handler, ":") { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python external handler import requires an immutable artifact catalog") + } + if body.Mode != "SCALAR" && body.Mode != "VECTOR" { + return udferr.Newf("python routine has unsupported mode %q", body.Mode) + } + if body.NullPolicy != udf.NullCallHandler && body.NullPolicy != udf.NullReturnNull { + return udferr.Newf("python routine has unsupported NULL policy %q", body.NullPolicy) + } + if body.ABIContract != udf.PythonABIContract || body.AdapterVersion != udf.PythonAdapterVersion { + return udferr.Newf("python routine has unsupported ABI contract %q/%q", body.ABIContract, body.AdapterVersion) + } + if body.SDKVersion != udf.PythonSDKVersion { + return udferr.Newf("python routine has unsupported SDK %q", body.SDKVersion) + } + if !udf.IsSHA256Digest(body.ArtifactDigest) || body.EnvironmentDigest == "" { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python definition has no immutable artifact/environment digest; use DROP and CREATE") + } + if body.ArtifactDigest != udf.PythonInlineArtifactDigest(body.Handler, body.Source) { + return udferr.Newf("python routine artifact digest does not match its source") + } + environmentDigest, err := udf.PythonEnvironmentDigest() + if err != nil { + return errutil.Wrapf(err, "python routine environment digest is unavailable") + } + if body.EnvironmentDigest != environmentDigest { + return udferr.Newf("python routine environment digest does not match the current contract") + } + if body.ReturnType == nil { + return udferr.Newf("python routine is missing return descriptor") } + for i, descriptor := range body.ArgTypes { + if err := validatePythonTypeDescriptor(descriptor); err != nil { + return errutil.Wrapf(err, "python routine argument descriptor %d", i) + } + } + if err := validatePythonTypeDescriptor(*body.ReturnType); err != nil { + return errutil.Wrapf(err, "python routine return descriptor") + } + return nil } -func UdfArgTypeMatch(from []types.Type, to []types.T) (bool, int) { - sta, cost := tryToMatch(from, to) - return sta != matchFailed, cost +// PythonTypeDescriptor is the single Arrow ABI descriptor used by both plan +// resolution and the Python adapter. The UDF package keeps it as an alias so +// the catalog body and the Arrow metadata cannot drift independently. +type PythonTypeDescriptor = pythonudf.TypeDescriptor + +func NewPythonTypeDescriptor(typ types.Type) (PythonTypeDescriptor, error) { + return pythonudf.NewTypeDescriptor(typ) } -func UdfArgTypeCast(from []types.Type, to []types.T) []types.Type { - castType := make([]types.Type, len(from)) - for i := range castType { - if to[i] == from[i].Oid { - castType[i] = from[i] - } else { - castType[i] = to[i].ToType() - SetTargetScaleFromSource(&from[i], &castType[i]) - } +type Arg struct { + Name string `json:"name"` + Type string `json:"type"` +} + +// GetRoutineCall materializes the immutable typed call metadata used by the +// physical external evaluator. Statement identity and session values are +// deliberately absent: a prepared plan may outlive the statement that bound +// it, so the physical evaluator must construct those values from the current +// process at execution time. +func (u *Udf) GetRoutineCall() (*plan.RoutineCall, error) { + if u == nil { + return nil, udferr.Newf("routine call requires a non-nil routine") } - return castType + if u.Language == udf.LanguageSQL { + return u.getSQLRoutineCall() + } + if u.Language != udf.LanguagePython { + return nil, udferr.Newf("routine call has unsupported language %q", u.Language) + } + if u.FunctionID <= 0 || u.DatabaseID == 0 || u.Revision == 0 || u.NamespaceVersion == 0 { + return nil, udferr.Newf("python routine has no stable catalog identity or revision") + } + body, err := DecodePythonRoutineBody(u.Body) + if err != nil { + return nil, err + } + fingerprint, err := PythonRoutineFingerprint(u.Body) + if err != nil { + return nil, err + } + // The decoded immutable body is the source of truth for the executable + // Arrow signature. Do not rebuild it from the mutable legacy Udf fields; + // doing so could produce a plan whose fingerprint describes one signature + // while its argument types describe another damaged catalog row. + argTypes := make([]types.Type, len(body.ArgTypes)) + for i, descriptor := range body.ArgTypes { + argTypes[i] = descriptor.Type() + } + arguments := make([]*plan.Type, len(argTypes)) + for i, typ := range argTypes { + arguments[i] = type2PlanType(typ) + } + returnType := type2PlanType(body.ReturnType.Type()) + return &plan.RoutineCall{ + ContractVersion: udf.PythonPlanContractVersion, + NamespaceFingerprint: u.NamespaceFingerprint, + FunctionRef: &plan.FunctionRef{ + FunctionId: uint64(u.FunctionID), + Revision: u.Revision, + NamespaceVersion: u.NamespaceVersion, + AccountId: u.AccountID, + DatabaseId: u.DatabaseID, + }, + Language: udf.LanguagePython, + ArgumentTypes: arguments, + ReturnType: *returnType, + Volatility: "VOLATILE", + NullPolicy: body.NullPolicy, + MayError: true, + SecurityMode: "INVOKER", + Leakproof: false, + Implementation: &plan.RoutineCall_Python{Python: &plan.PythonRoutineImplementation{ + Handler: body.Handler, + AbiContract: body.ABIContract, + AdapterVersion: body.AdapterVersion, + ArtifactDigest: body.ArtifactDigest, + EnvironmentDigest: body.EnvironmentDigest, + SdkVersion: body.SDKVersion, + DefinitionSchemaVersion: int32(body.DefinitionSchemaVersion), + Mode: body.Mode, + NullPolicy: body.NullPolicy, + DefinitionFingerprint: fingerprint, + }}, + }, nil } -func getDataFromDataVector(v *udf.DataVector, i int) *udf.Data { - if v == nil { - return nil +// getSQLRoutineCall builds the common catalog envelope for a current SQL +// revision. SQL's existing expression lowering still expands the body at +// bind time, but the exact revision and integrity key are retained in the +// plan dependency so replace/drop cannot silently reuse the old definition. +func (u *Udf) getSQLRoutineCall() (*plan.RoutineCall, error) { + if u.FunctionID <= 0 || u.DatabaseID == 0 || u.Revision == 0 || u.NamespaceVersion == 0 { + return nil, udferr.Newf("SQL routine has no stable catalog identity or revision") + } + if u.SemanticDefinitionSchemaVersion != udf.SQLDefinitionSchemaVersion || !udf.IsSHA256Digest(u.DefinitionFingerprint) { + return nil, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: SQL routine has no supported semantic definition") + } + argTypes := u.GetArgsType() + arguments := make([]*plan.Type, len(argTypes)) + for index, typ := range argTypes { + arguments[index] = type2PlanType(typ) + } + returnType := type2PlanType(u.GetRetType()) + volatility := u.Volatility + if volatility == "" { + volatility = "VOLATILE" } - if v.Const { - return v.Data[0] + nullPolicy := u.NullPolicy + if nullPolicy == "" { + nullPolicy = udf.NullCallHandler } - return v.Data[i] + return &plan.RoutineCall{ + ContractVersion: udf.RoutinePlanContractVersion, + NamespaceFingerprint: u.NamespaceFingerprint, + FunctionRef: &plan.FunctionRef{ + FunctionId: uint64(u.FunctionID), + Revision: u.Revision, + NamespaceVersion: u.NamespaceVersion, + AccountId: u.AccountID, + DatabaseId: u.DatabaseID, + }, + Language: udf.LanguageSQL, + ArgumentTypes: arguments, + ReturnType: *returnType, + Volatility: volatility, + NullPolicy: nullPolicy, + MayError: true, + SecurityMode: "DEFINER", + Leakproof: false, + Implementation: &plan.RoutineCall_Sql{Sql: &plan.SqlRoutineImplementation{ + DefinitionFingerprint: []byte(u.DefinitionFingerprint), + SemanticDefinitionSchemaVersion: int32(u.SemanticDefinitionSchemaVersion), + }}, + }, nil } -func vector2DataVector(v *vector.Vector) (*udf.DataVector, error) { - if v == nil { - return nil, nil - } - dv := &udf.DataVector{ - Const: v.IsConst(), - Length: int64(v.Length()), - Type: t2DataType[v.GetType().Oid], - Scale: v.GetType().Scale, - } - size := v.Length() - if dv.Const { - size = 1 - } - dv.Data = make([]*udf.Data, size) - switch v.GetType().Oid { - case types.T_bool: - p := vector.GenerateFunctionFixedTypeParameter[bool](v) - for i := 0; i < size; i++ { - val, isNull := p.GetValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_BoolVal{BoolVal: val}} - } - } - case types.T_int8: - p := vector.GenerateFunctionFixedTypeParameter[int8](v) - for i := 0; i < size; i++ { - val, isNull := p.GetValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_IntVal{IntVal: int32(val)}} - } - } - case types.T_int16: - p := vector.GenerateFunctionFixedTypeParameter[int16](v) - for i := 0; i < size; i++ { - val, isNull := p.GetValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_IntVal{IntVal: int32(val)}} - } - } - case types.T_int32: - p := vector.GenerateFunctionFixedTypeParameter[int32](v) - for i := 0; i < size; i++ { - val, isNull := p.GetValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_IntVal{IntVal: val}} - } - } - case types.T_int64: - p := vector.GenerateFunctionFixedTypeParameter[int64](v) - for i := 0; i < size; i++ { - val, isNull := p.GetValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_Int64Val{Int64Val: val}} - } - } - case types.T_uint8: - p := vector.GenerateFunctionFixedTypeParameter[uint8](v) - for i := 0; i < size; i++ { - val, isNull := p.GetValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_UintVal{UintVal: uint32(val)}} - } - } - case types.T_uint16: - p := vector.GenerateFunctionFixedTypeParameter[uint16](v) - for i := 0; i < size; i++ { - val, isNull := p.GetValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_UintVal{UintVal: uint32(val)}} - } - } - case types.T_uint32: - p := vector.GenerateFunctionFixedTypeParameter[uint32](v) - for i := 0; i < size; i++ { - val, isNull := p.GetValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_UintVal{UintVal: val}} - } - } - case types.T_uint64: - p := vector.GenerateFunctionFixedTypeParameter[uint64](v) - for i := 0; i < size; i++ { - val, isNull := p.GetValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_Uint64Val{Uint64Val: val}} - } - } - case types.T_float32: - p := vector.GenerateFunctionFixedTypeParameter[float32](v) - for i := 0; i < size; i++ { - val, isNull := p.GetValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_FloatVal{FloatVal: val}} - } - } - case types.T_float64: - p := vector.GenerateFunctionFixedTypeParameter[float64](v) - for i := 0; i < size; i++ { - val, isNull := p.GetValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_DoubleVal{DoubleVal: val}} - } - } - case types.T_char, types.T_varchar, types.T_text, types.T_datalink: - p := vector.GenerateFunctionStrParameter(v) - for i := 0; i < size; i++ { - val, isNull := p.GetStrValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_StringVal{StringVal: string(val)}} - } - } - case types.T_json: - p := vector.GenerateFunctionStrParameter(v) - for i := 0; i < size; i++ { - val, isNull := p.GetStrValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_StringVal{StringVal: types.DecodeJson(val).String()}} - } - } - case types.T_uuid: - p := vector.GenerateFunctionFixedTypeParameter[types.Uuid](v) - for i := 0; i < size; i++ { - val, isNull := p.GetValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_StringVal{StringVal: val.String()}} - } - } - case types.T_time: - p := vector.GenerateFunctionFixedTypeParameter[types.Time](v) - for i := 0; i < size; i++ { - val, isNull := p.GetValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_StringVal{StringVal: val.String2(v.GetType().Scale)}} - } - } - case types.T_date: - p := vector.GenerateFunctionFixedTypeParameter[types.Date](v) - for i := 0; i < size; i++ { - val, isNull := p.GetValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_StringVal{StringVal: val.String()}} - } - } - case types.T_datetime: - p := vector.GenerateFunctionFixedTypeParameter[types.Datetime](v) - for i := 0; i < size; i++ { - val, isNull := p.GetValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_StringVal{StringVal: val.String2(v.GetType().Scale)}} - } - } - case types.T_timestamp: - p := vector.GenerateFunctionFixedTypeParameter[types.Timestamp](v) - for i := 0; i < size; i++ { - val, isNull := p.GetValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_StringVal{StringVal: val.String2(time.Local, v.GetType().Scale)}} - } - } - case types.T_decimal64: - p := vector.GenerateFunctionFixedTypeParameter[types.Decimal64](v) - for i := 0; i < size; i++ { - val, isNull := p.GetValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_StringVal{StringVal: val.Format(v.GetType().Scale)}} - } - } - case types.T_decimal128: - p := vector.GenerateFunctionFixedTypeParameter[types.Decimal128](v) - for i := 0; i < size; i++ { - val, isNull := p.GetValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_StringVal{StringVal: val.Format(v.GetType().Scale)}} - } - } - case types.T_binary, types.T_varbinary, types.T_blob: - p := vector.GenerateFunctionStrParameter(v) - for i := 0; i < size; i++ { - val, isNull := p.GetStrValue(uint64(i)) - if !isNull { - dv.Data[i] = &udf.Data{Val: &udf.Data_BytesVal{BytesVal: val}} - } +func (u *Udf) GetArgsPlanType() []*plan.Type { + args := u.GetArgsType() + result := make([]*plan.Type, len(args)) + for i, typ := range args { + result[i] = type2PlanType(typ) + } + return result +} +func (u *Udf) GetRetPlanType() *plan.Type { return type2PlanType(u.GetRetType()) } +func (u *Udf) GetArgsType() []types.Type { + if u.Language == udf.LanguagePython { + // Resolver-created routines always set PythonReturnType when the + // canonical descriptor has been loaded. Keeping the fallback makes + // the generic Udf value usable by planner tests and by the SQL-side + // preflight checks without allowing a real Python call to skip body + // validation: GetRoutineCall decodes and validates Body again. + if u.PythonReturnType == nil && u.PythonArgTypes == nil { + return u.ArgsType + } + args := make([]types.Type, len(u.PythonArgTypes)) + for i, descriptor := range u.PythonArgTypes { + args[i] = descriptor.Type() + } + return args + } + return u.ArgsType +} +func (u *Udf) GetRetType() types.Type { + if u.Language == udf.LanguagePython { + if u.PythonReturnType == nil { + return types.Types[u.RetType].ToType() } - default: - return nil, moerr.NewInvalidArgNoCtx("python udf arg type", v.GetType().String()) + return u.PythonReturnType.Type() } - return dv, nil + return types.Types[u.RetType].ToType() } -func writeResponse(response *udf.Response, result vector.FunctionResultWrapper) error { - var err error - retType := dataType2T[response.Vector.Type] - length := int(response.Vector.Length) - scale := response.Vector.Scale - - result.GetResultVector().SetTypeScale(scale) +// LoadPythonTypeContract loads the exact type metadata persisted in the Python +// routine body. Python execution has one ABI, so an incomplete body is +// rejected instead of being reinterpreted through the legacy logical-type +// columns. +func (u *Udf) LoadPythonTypeContract() error { + if u == nil || u.Language == udf.LanguageSQL { + return nil + } + if u.Language != udf.LanguagePython { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: unsupported routine language %q", u.Language) + } + u.PythonArgTypes = nil + u.PythonReturnType = nil + body, err := DecodePythonRoutineBody(u.Body) + if err != nil { + return err + } + u.PythonArgTypes = append([]PythonTypeDescriptor(nil), body.ArgTypes...) + returnType := *body.ReturnType + u.PythonReturnType = &returnType + return nil +} - switch retType { - case types.T_bool: - res := vector.MustFunctionResult[bool](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.Append(false, true) - } else { - err = res.Append(data.GetBoolVal(), false) - } - if err != nil { - return err - } - } - case types.T_int8: - res := vector.MustFunctionResult[int8](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.Append(0, true) - } else { - err = res.Append(int8(data.GetIntVal()), false) - } - if err != nil { - return err - } - } - case types.T_int16: - res := vector.MustFunctionResult[int16](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.Append(0, true) - } else { - err = res.Append(int16(data.GetIntVal()), false) - } - if err != nil { - return err - } - } - case types.T_int32: - res := vector.MustFunctionResult[int32](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.Append(0, true) - } else { - err = res.Append(data.GetIntVal(), false) - } - if err != nil { - return err - } - } - case types.T_int64: - res := vector.MustFunctionResult[int64](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.Append(0, true) - } else { - err = res.Append(data.GetInt64Val(), false) - } - if err != nil { - return err - } - } - case types.T_uint8: - res := vector.MustFunctionResult[uint8](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.Append(0, true) - } else { - err = res.Append(uint8(data.GetUintVal()), false) - } - if err != nil { - return err - } - } - case types.T_uint16: - res := vector.MustFunctionResult[uint16](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.Append(0, true) - } else { - err = res.Append(uint16(data.GetUintVal()), false) - } - if err != nil { - return err - } - } - case types.T_uint32: - res := vector.MustFunctionResult[uint32](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.Append(0, true) - } else { - err = res.Append(data.GetUintVal(), false) - } - if err != nil { - return err - } - } - case types.T_uint64: - res := vector.MustFunctionResult[uint64](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.Append(0, true) - } else { - err = res.Append(data.GetUint64Val(), false) - } - if err != nil { - return err - } - } - case types.T_float32: - res := vector.MustFunctionResult[float32](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.Append(0, true) - } else { - err = res.Append(data.GetFloatVal(), false) - } - if err != nil { - return err - } - } - case types.T_float64: - res := vector.MustFunctionResult[float64](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.Append(0, true) - } else { - err = res.Append(data.GetDoubleVal(), false) - } - if err != nil { - return err - } - } - case types.T_char, types.T_varchar, types.T_text, types.T_datalink: - res := vector.MustFunctionResult[types.Varlena](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.AppendBytes(nil, true) - } else { - err = res.AppendBytes([]byte(data.GetStringVal()), false) - } - if err != nil { - return err - } - } - case types.T_json: - res := vector.MustFunctionResult[types.Varlena](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.AppendBytes(nil, true) - } else { - bytes, err2 := bytejson.ParseJsonByteFromString(data.GetStringVal()) - if err2 != nil { - return err2 - } - err = res.AppendBytes(bytes, false) - } - if err != nil { - return err - } - } - case types.T_uuid: - res := vector.MustFunctionResult[types.Uuid](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.AppendBytes(nil, true) - } else { - uuid, err2 := types.ParseUuid(data.GetStringVal()) - if err2 != nil { - return err2 - } - err = res.Append(uuid, false) - } - if err != nil { - return err - } - } - case types.T_time: - res := vector.MustFunctionResult[types.Time](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.AppendBytes(nil, true) - } else { - t, err2 := types.ParseTime(data.GetStringVal(), scale) - if err2 != nil { - return err2 - } - err = res.Append(t, false) - } - if err != nil { - return err - } - } - case types.T_date: - res := vector.MustFunctionResult[types.Date](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.AppendBytes(nil, true) - } else { - d, err2 := types.ParseDateCast(data.GetStringVal()) - if err2 != nil { - return err2 - } - err = res.Append(d, false) - } - if err != nil { - return err - } - } - case types.T_datetime: - res := vector.MustFunctionResult[types.Datetime](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.AppendBytes(nil, true) - } else { - dt, err2 := types.ParseDatetime(data.GetStringVal(), scale) - if err2 != nil { - return err2 - } - err = res.Append(dt, false) - } - if err != nil { - return err - } - } - case types.T_timestamp: - res := vector.MustFunctionResult[types.Timestamp](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.AppendBytes(nil, true) - } else { - ts, err2 := types.ParseTimestamp(time.Local, data.GetStringVal(), scale) - if err2 != nil { - return err2 - } - err = res.Append(ts, false) - } - if err != nil { - return err - } - } - case types.T_decimal64, types.T_decimal128: - res := vector.MustFunctionResult[types.Decimal128](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.AppendBytes(nil, true) - } else { - decimal, err2 := types.ParseDecimal128(data.GetStringVal(), 38, scale) - if err2 != nil { - return err2 - } - err = res.Append(decimal, false) - } - if err != nil { - return err - } +// ValidatePythonTypeContract checks the descriptor count after catalog +// argument names have been decoded. LoadPythonTypeContract deliberately runs +// before that decode during lookup, so this second check closes the only point +// where an argument list and its exact ABI could otherwise diverge. +func (u *Udf) ValidatePythonTypeContract() error { + if u == nil || u.Language == udf.LanguageSQL { + return nil + } + if u.Language != udf.LanguagePython { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: unsupported routine language %q", u.Language) + } + if u.PythonReturnType == nil { + return udferr.Newf("python routine is missing return descriptor") + } + if len(u.PythonArgTypes) != len(u.Args) { + return udferr.Newf("python routine has %d descriptors for %d arguments", len(u.PythonArgTypes), len(u.Args)) + } + for i, descriptor := range u.PythonArgTypes { + if err := validatePythonTypeDescriptor(descriptor); err != nil { + return errutil.Wrapf(err, "python routine argument descriptor %d", i) } - case types.T_binary, types.T_varbinary, types.T_blob: - res := vector.MustFunctionResult[types.Varlena](result) - for i := 0; i < length; i++ { - data := getDataFromDataVector(response.Vector, i) - if data == nil || data.Val == nil { - err = res.AppendBytes(nil, true) - } else { - err = res.AppendBytes(data.GetBytesVal(), false) - } - if err != nil { - return err + } + return validatePythonTypeDescriptor(*u.PythonReturnType) +} + +// ValidatePythonCatalogSignature verifies the logical type columns that are +// retained by mo_user_defined_function/mo_function_revisions against the +// exact Arrow descriptors in the Python implementation. The legacy columns +// intentionally omit width and scale, so they cannot replace the descriptor; +// they still must agree on the logical OID or a damaged catalog row could be +// selected by overload resolution and dispatched with a different ABI. +func (u *Udf) ValidatePythonCatalogSignature() error { + if u == nil || u.Language == udf.LanguageSQL { + return nil + } + if u.Language != udf.LanguagePython { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: unsupported routine language %q", u.Language) + } + if len(u.Args) != len(u.PythonArgTypes) || u.PythonReturnType == nil { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python catalog signature is incomplete") + } + for index, argument := range u.Args { + if argument == nil || !pythonCatalogTypeNameMatches(argument.Type, u.PythonArgTypes[index].Type().Oid) { + name := "" + if argument != nil { + name = argument.Type } + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python catalog argument %d type %q does not match its descriptor", index+1, name) } - default: - return moerr.NewNotSupportedNoCtxf("python udf return type: %v", retType.String()) } - + if !pythonCatalogTypeNameMatches(u.RetType, u.PythonReturnType.Type().Oid) { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python catalog return type %q does not match its descriptor", u.RetType) + } return nil } -var ( - t2DataType = map[types.T]udf.DataType{ - types.T_bool: udf.DataType_BOOL, - types.T_int8: udf.DataType_INT8, - types.T_int16: udf.DataType_INT16, - types.T_int32: udf.DataType_INT32, - types.T_int64: udf.DataType_INT64, - types.T_uint8: udf.DataType_UINT8, - types.T_uint16: udf.DataType_UINT16, - types.T_uint32: udf.DataType_UINT32, - types.T_uint64: udf.DataType_UINT64, - types.T_float32: udf.DataType_FLOAT32, - types.T_float64: udf.DataType_FLOAT64, - types.T_char: udf.DataType_CHAR, - types.T_varchar: udf.DataType_VARCHAR, - types.T_text: udf.DataType_TEXT, - types.T_json: udf.DataType_JSON, - types.T_uuid: udf.DataType_UUID, - types.T_time: udf.DataType_TIME, - types.T_date: udf.DataType_DATE, - types.T_datetime: udf.DataType_DATETIME, - types.T_timestamp: udf.DataType_TIMESTAMP, - types.T_decimal64: udf.DataType_DECIMAL64, - types.T_decimal128: udf.DataType_DECIMAL128, - types.T_binary: udf.DataType_BINARY, - types.T_varbinary: udf.DataType_VARBINARY, - types.T_blob: udf.DataType_BLOB, - } +func pythonCatalogTypeNameMatches(name string, oid types.T) bool { + name = strings.ToLower(strings.TrimSpace(name)) + return name == PythonCatalogTypeName(types.Type{Oid: oid}) +} - dataType2T = map[udf.DataType]types.T{ - udf.DataType_BOOL: types.T_bool, - udf.DataType_INT8: types.T_int8, - udf.DataType_INT16: types.T_int16, - udf.DataType_INT32: types.T_int32, - udf.DataType_INT64: types.T_int64, - udf.DataType_UINT8: types.T_uint8, - udf.DataType_UINT16: types.T_uint16, - udf.DataType_UINT32: types.T_uint32, - udf.DataType_UINT64: types.T_uint64, - udf.DataType_FLOAT32: types.T_float32, - udf.DataType_FLOAT64: types.T_float64, - udf.DataType_CHAR: types.T_char, - udf.DataType_VARCHAR: types.T_varchar, - udf.DataType_TEXT: types.T_text, - udf.DataType_JSON: types.T_json, - udf.DataType_UUID: types.T_uuid, - udf.DataType_TIME: types.T_time, - udf.DataType_DATE: types.T_date, - udf.DataType_DATETIME: types.T_datetime, - udf.DataType_TIMESTAMP: types.T_timestamp, - udf.DataType_DECIMAL64: types.T_decimal64, - udf.DataType_DECIMAL128: types.T_decimal128, - udf.DataType_BINARY: types.T_binary, - udf.DataType_VARBINARY: types.T_varbinary, - udf.DataType_BLOB: types.T_blob, +// PythonCatalogTypeName returns the logical type name stored in the shared +// catalog signature columns for a Python descriptor. The exact width and +// scale remain in the typed descriptor; the historical logical namespace +// intentionally represents both supported decimal physical widths as +// "decimal". +func PythonCatalogTypeName(typ types.Type) string { + if typ.Oid == types.T_decimal64 || typ.Oid == types.T_decimal128 { + return "decimal" } -) + return strings.ToLower(typ.Oid.String()) +} -type DefaultPkgReader struct { - Proc *process.Process +func validatePythonTypeDescriptor(descriptor PythonTypeDescriptor) error { + typ := descriptor.Type() + canonical, err := NewPythonTypeDescriptor(typ) + if err != nil { + return err + } + if !reflect.DeepEqual(canonical, descriptor) { + return udferr.Newf("descriptor is not canonical for %s", typ.String()) + } + if _, err := descriptor.Fingerprint(); err != nil { + return errutil.Wrapf(err, "descriptor has no valid Arrow physical type") + } + return nil +} +func type2PlanType(typ types.Type) *plan.Type { + return &plan.Type{Id: int32(typ.Oid), Width: typ.Width, Scale: typ.Scale, Charset: uint32(typ.Charset)} } -func (d *DefaultPkgReader) Get(ctx context.Context, path string) (io.ReadCloser, error) { - reader, writer := io.Pipe() - var errGroup *errgroup.Group - defer func() { - if errGroup == nil { - writer.Close() +func UdfArgTypeMatch(from []types.Type, to []types.T) (bool, int) { + status, cost := tryToMatch(from, to) + return status != matchFailed, cost +} +func UdfArgTypeCast(from []types.Type, to []types.T) []types.Type { + castType := make([]types.Type, len(from)) + for i := range castType { + if to[i] == from[i].Oid { + castType[i] = from[i] + } else { + castType[i] = to[i].ToType() + SetTargetScaleFromSource(&from[i], &castType[i]) } - }() - - ioVector := &fileservice.IOVector{ - FilePath: path, - Entries: []fileservice.IOEntry{ - { - Offset: 0, - Size: -1, - WriterForRead: writer, - }, - }, } - - errGroup = new(errgroup.Group) - errGroup.Go(func() error { - defer writer.Close() - return d.Proc.GetFileService().Read(ctx, ioVector) - }) - - return reader, nil + return castType } diff --git a/pkg/sql/plan/function/udf_test.go b/pkg/sql/plan/function/udf_test.go new file mode 100644 index 0000000000000..b15f995cc6207 --- /dev/null +++ b/pkg/sql/plan/function/udf_test.go @@ -0,0 +1,445 @@ +// Copyright 2026 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 function + +import ( + "context" + "encoding/json" + "testing" + + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/container/vector" + planpb "github.com/matrixorigin/matrixone/pkg/pb/plan" + "github.com/matrixorigin/matrixone/pkg/udf" + "github.com/stretchr/testify/require" +) + +func pythonTestBody(body PythonRoutineBody) PythonRoutineBody { + body.ArtifactDigest = udf.PythonInlineArtifactDigest(body.Handler, body.Source) + body.EnvironmentDigest, _ = udf.PythonEnvironmentDigest() + return body +} + +func TestPythonTypeContractPreservesDeclaredShape(t *testing.T) { + argument := types.New(types.T_decimal64, 18, 6) + returnType := types.New(types.T_varchar, 64, 0) + argumentDescriptor, err := NewPythonTypeDescriptor(argument) + require.NoError(t, err) + returnDescriptor, err := NewPythonTypeDescriptor(returnType) + require.NoError(t, err) + body, err := json.Marshal(pythonTestBody(PythonRoutineBody{ + DefinitionSchemaVersion: udf.PythonDefinitionSchemaVersion, + Handler: "identity", + Source: "def identity(ctx, x): return x", + Mode: "SCALAR", + NullPolicy: udf.NullCallHandler, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + SDKVersion: udf.PythonSDKVersion, + ArgTypes: []PythonTypeDescriptor{argumentDescriptor}, + ReturnType: &returnDescriptor, + })) + require.NoError(t, err) + + routine := &Udf{Language: "python", Body: string(body), RetType: "varchar", ArgsType: []types.Type{types.T_decimal64.ToType()}} + require.NoError(t, routine.LoadPythonTypeContract()) + routine.Args = []*Arg{{Type: "decimal"}} + require.NoError(t, routine.ValidatePythonTypeContract()) + require.NoError(t, routine.ValidatePythonCatalogSignature()) + require.Equal(t, argument, routine.GetArgsType()[0]) + require.Equal(t, returnType, routine.GetRetType()) + require.Equal(t, int32(6), routine.GetArgsPlanType()[0].Scale) + require.Equal(t, int32(64), routine.GetRetPlanType().Width) +} + +func TestPythonSignatureMetadataIsCanonicalAndSensitiveToShape(t *testing.T) { + argument, err := NewPythonTypeDescriptor(types.New(types.T_decimal64, 18, 2)) + require.NoError(t, err) + returnType, err := NewPythonTypeDescriptor(types.T_varchar.ToType()) + require.NoError(t, err) + input, output, fingerprint, err := PythonSignatureMetadata([]PythonTypeDescriptor{argument}, &returnType) + require.NoError(t, err) + require.Equal(t, `[{"type_id":32,"width":18,"scale":2,"offset_width":32}]`, input) + encodedReturn, err := json.Marshal(returnType) + require.NoError(t, err) + require.Equal(t, string(encodedReturn), output) + require.Len(t, fingerprint, 64) + + otherArgument, err := NewPythonTypeDescriptor(types.New(types.T_decimal64, 18, 6)) + require.NoError(t, err) + _, _, otherFingerprint, err := PythonSignatureMetadata([]PythonTypeDescriptor{otherArgument}, &returnType) + require.NoError(t, err) + require.NotEqual(t, fingerprint, otherFingerprint) +} + +func TestPythonUdfArgTypeMatchPrefersExactDescriptor(t *testing.T) { + source := types.New(types.T_decimal64, 18, 2) + exact := types.New(types.T_decimal64, 18, 2) + coerce := types.New(types.T_decimal64, 18, 6) + exactOK, exactCost := PythonUdfArgTypeMatch([]types.Type{source}, []types.Type{exact}) + coerceOK, coerceCost := PythonUdfArgTypeMatch([]types.Type{source}, []types.Type{coerce}) + require.True(t, exactOK) + require.True(t, coerceOK) + require.Less(t, exactCost, coerceCost) +} + +func TestPythonUdfArgTypeMatchRejectsVectorDimensionChange(t *testing.T) { + source := types.New(types.T_array_float32, 4, 0) + target := types.New(types.T_array_float32, 3, 0) + canMatch, cost := PythonUdfArgTypeMatch([]types.Type{source}, []types.Type{target}) + require.False(t, canMatch) + require.Equal(t, -1, cost) + + inputs := []types.Type{ + types.T_text.ToType(), + source, + target, + types.T_int64.ToType(), + } + result := checkPythonUdf(nil, inputs) + require.Equal(t, failedFunctionParametersWrong, result.status) + require.Nil(t, PythonUdfArgTypeCast([]types.Type{source}, []types.Type{target})) +} + +func TestPythonUdfArgTypeCastKeepsDeclaredDescriptorForSameOID(t *testing.T) { + source := types.New(types.T_decimal64, 18, 2) + target := types.New(types.T_decimal64, 18, 6) + + castTypes := PythonUdfArgTypeCast([]types.Type{source}, []types.Type{target}) + require.Equal(t, []types.Type{target}, castTypes) + require.Nil(t, PythonUdfArgTypeCast([]types.Type{source}, nil)) +} + +func TestPythonCatalogTypeNamePreservesLogicalDecimalAlias(t *testing.T) { + require.Equal(t, "decimal", PythonCatalogTypeName(types.New(types.T_decimal64, 18, 2))) + require.Equal(t, "decimal", PythonCatalogTypeName(types.New(types.T_decimal128, 38, 10))) + require.Equal(t, "bigint", PythonCatalogTypeName(types.T_int64.ToType())) +} + +func TestPythonCatalogSignatureRejectsLogicalDescriptorDrift(t *testing.T) { + argument, err := NewPythonTypeDescriptor(types.T_int64.ToType()) + require.NoError(t, err) + returnType, err := NewPythonTypeDescriptor(types.T_int64.ToType()) + require.NoError(t, err) + raw, err := json.Marshal(pythonTestBody(PythonRoutineBody{ + DefinitionSchemaVersion: udf.PythonDefinitionSchemaVersion, + Handler: "identity", + Source: "def identity(ctx, value): return value", + Mode: "SCALAR", + NullPolicy: udf.NullCallHandler, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + SDKVersion: udf.PythonSDKVersion, + ArgTypes: []PythonTypeDescriptor{argument}, + ReturnType: &returnType, + })) + require.NoError(t, err) + routine := &Udf{Language: "python", Body: string(raw), RetType: "bigint"} + require.NoError(t, routine.LoadPythonTypeContract()) + routine.Args = []*Arg{{Type: "varchar"}} + require.ErrorContains(t, routine.ValidatePythonCatalogSignature(), "argument 1") + + routine.Args[0].Type = "bigint" + routine.RetType = "varchar" + require.ErrorContains(t, routine.ValidatePythonCatalogSignature(), "return type") +} + +func TestPythonTypeContractRejectsMissingReturnDescriptor(t *testing.T) { + body := pythonTestBody(PythonRoutineBody{ + DefinitionSchemaVersion: udf.PythonDefinitionSchemaVersion, + Handler: "legacy", + Source: "def legacy(ctx, x): return x", + Mode: "SCALAR", + NullPolicy: udf.NullCallHandler, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + SDKVersion: udf.PythonSDKVersion, + }) + rawBody, err := json.Marshal(body) + require.NoError(t, err) + routine := &Udf{ + Language: "python", + Body: string(rawBody), + ArgsType: []types.Type{types.T_int32.ToType()}, + RetType: "int", + } + require.ErrorContains(t, routine.LoadPythonTypeContract(), "return descriptor") +} + +func TestPythonTypeContractRejectsArgumentCountMismatch(t *testing.T) { + argument, err := NewPythonTypeDescriptor(types.T_int32.ToType()) + require.NoError(t, err) + returnType, err := NewPythonTypeDescriptor(types.T_int32.ToType()) + require.NoError(t, err) + body, err := json.Marshal(pythonTestBody(PythonRoutineBody{ + DefinitionSchemaVersion: udf.PythonDefinitionSchemaVersion, + Handler: "identity", + Source: "def identity(ctx, x): return x", + Mode: "SCALAR", + NullPolicy: udf.NullCallHandler, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + SDKVersion: udf.PythonSDKVersion, + ArgTypes: []PythonTypeDescriptor{argument}, + ReturnType: &returnType, + })) + require.NoError(t, err) + routine := &Udf{Language: "python", Body: string(body)} + require.NoError(t, routine.LoadPythonTypeContract()) + require.ErrorContains(t, routine.ValidatePythonTypeContract(), "descriptors for 0 arguments") +} + +func TestPythonTypeContractReloadReplacesDescriptors(t *testing.T) { + argument, err := NewPythonTypeDescriptor(types.T_int32.ToType()) + require.NoError(t, err) + returnType, err := NewPythonTypeDescriptor(types.T_int32.ToType()) + require.NoError(t, err) + body, err := json.Marshal(pythonTestBody(PythonRoutineBody{ + DefinitionSchemaVersion: udf.PythonDefinitionSchemaVersion, + Handler: "identity", + Source: "def identity(ctx, x): return x", + Mode: "SCALAR", + NullPolicy: udf.NullCallHandler, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + SDKVersion: udf.PythonSDKVersion, + ArgTypes: []PythonTypeDescriptor{argument}, + ReturnType: &returnType, + })) + require.NoError(t, err) + routine := &Udf{Language: "python", Body: string(body)} + require.NoError(t, routine.LoadPythonTypeContract()) + require.NoError(t, routine.LoadPythonTypeContract()) + require.Len(t, routine.PythonArgTypes, 1) +} + +func TestPythonRoutineBodyRejectsUnknownAndTrailingData(t *testing.T) { + valid, err := json.Marshal(pythonTestBody(PythonRoutineBody{ + DefinitionSchemaVersion: udf.PythonDefinitionSchemaVersion, + Handler: "identity", + Source: "def identity(ctx): return 1", + Mode: "SCALAR", + NullPolicy: udf.NullCallHandler, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + SDKVersion: udf.PythonSDKVersion, + ReturnType: func() *PythonTypeDescriptor { d, _ := NewPythonTypeDescriptor(types.T_int32.ToType()); return &d }(), + })) + require.NoError(t, err) + + var withUnknown map[string]any + require.NoError(t, json.Unmarshal(valid, &withUnknown)) + withUnknown["future_field"] = true + unknown, err := json.Marshal(withUnknown) + require.NoError(t, err) + require.ErrorContains(t, func() error { _, err := DecodePythonRoutineBody(string(unknown)); return err }(), "unknown field") + require.ErrorContains(t, func() error { _, err := DecodePythonRoutineBody(string(valid) + string(valid)); return err }(), "multiple JSON values") +} + +func TestPythonTypeContractRejectsUnrepresentableArrowPrecision(t *testing.T) { + returnDescriptor := PythonTypeDescriptor{ + TypeID: int32(types.T_decimal128), + Width: 39, + OffsetWidth: 32, + } + body, err := json.Marshal(pythonTestBody(PythonRoutineBody{ + DefinitionSchemaVersion: udf.PythonDefinitionSchemaVersion, + Handler: "identity", + Source: "def identity(ctx): return 1", + Mode: "SCALAR", + NullPolicy: udf.NullCallHandler, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + SDKVersion: udf.PythonSDKVersion, + ReturnType: &returnDescriptor, + })) + require.NoError(t, err) + routine := &Udf{Language: "python", Body: string(body)} + require.ErrorContains(t, routine.LoadPythonTypeContract(), "precision") +} + +func TestPythonBindingNormalizesDecimalMetadata(t *testing.T) { + received := types.New(types.T_decimal64, 18, 2) + required := types.New(types.T_decimal64, 18, 6) + inputs := []types.Type{ + types.T_text.ToType(), + received, + required, + types.T_decimal64.ToType(), + } + result := checkPythonUdf(nil, inputs) + require.Equal(t, succeedWithCast, result.status) + require.Equal(t, required, result.finalType[1]) +} + +func TestPythonTypeEqualityUsesSQLIntegerSemantics(t *testing.T) { + declared := types.New(types.T_int32, 0, -1) + caseResult := types.New(types.T_int32, 32, -1) + require.True(t, pythonTypesEqual(declared, caseResult)) +} + +func TestPythonExecutionValidatesDescriptorAndInputTypes(t *testing.T) { + empty, err := vector.NewConstBytes(types.T_text.ToType(), nil, 0, nil) + require.NoError(t, err) + require.ErrorContains(t, validatePythonRoutineDescriptor(empty), "descriptor is empty") + + nonConst := vector.NewOffHeapVecWithTypeAndData( + types.T_text.ToType(), []byte("routine"), 1, 1, + ) + require.ErrorContains(t, validatePythonRoutineDescriptor(nonConst), "must be constant") + + input := vector.NewOffHeapVecWithTypeAndData(types.T_int32.ToType(), make([]byte, 4), 1, 1) + require.ErrorContains(t, + validatePythonInputVectors([]*vector.Vector{input}, []types.Type{types.T_int64.ToType()}, 1), + "does not match", + ) +} + +func TestPythonRoutineIsVolatile(t *testing.T) { + resolved, err := GetFunctionByName(context.Background(), "python_user_defined_function", []types.Type{ + types.T_text.ToType(), + types.T_text.ToType(), + }) + require.NoError(t, err) + _, overloadID := DecodeOverloadID(resolved.GetEncodedOverloadID()) + require.True(t, allSupportedFunctions[PYTHON_UDF].Overloads[overloadID].CannotFold()) +} + +func TestPythonRoutineCallCarriesExactCatalogContract(t *testing.T) { + descriptor, err := NewPythonTypeDescriptor(types.T_int64.ToType()) + require.NoError(t, err) + body, err := json.Marshal(pythonTestBody(PythonRoutineBody{ + DefinitionSchemaVersion: udf.PythonDefinitionSchemaVersion, + Handler: "identity", + Source: "def identity(ctx, value): return value", + Mode: "SCALAR", + NullPolicy: udf.NullCallHandler, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + SDKVersion: udf.PythonSDKVersion, + ArgTypes: []PythonTypeDescriptor{descriptor}, + ReturnType: &descriptor, + })) + require.NoError(t, err) + + routine := &Udf{ + FunctionID: 41, + AccountID: 7, + DatabaseID: 8, + Revision: 7, + NamespaceVersion: 12, + Language: "python", + Body: string(body), + Args: []*Arg{{Name: "value", Type: "bigint"}}, + } + require.NoError(t, routine.LoadPythonTypeContract()) + require.NoError(t, routine.ValidatePythonTypeContract()) + + call, err := routine.GetRoutineCall() + require.NoError(t, err) + require.Equal(t, int32(udf.PythonPlanContractVersion), call.ContractVersion) + require.Equal(t, &planpb.FunctionRef{FunctionId: 41, Revision: 7, NamespaceVersion: 12, AccountId: 7, DatabaseId: 8}, call.FunctionRef) + require.Equal(t, "python", call.Language) + require.Equal(t, "VOLATILE", call.Volatility) + require.Equal(t, udf.NullCallHandler, call.NullPolicy) + require.True(t, call.MayError) + require.Equal(t, "INVOKER", call.SecurityMode) + require.False(t, call.Leakproof) + require.Empty(t, call.Context) + require.Empty(t, call.GetPython().Source, "source is catalog payload, never executable plan state") + require.NotEmpty(t, call.GetPython().DefinitionFingerprint) +} + +func TestPythonRoutineCallRejectsNoncanonicalLanguage(t *testing.T) { + routine := &Udf{Language: "PYTHON"} + _, err := routine.GetRoutineCall() + require.ErrorContains(t, err, `routine call has unsupported language "PYTHON"`) +} + +func TestPythonContractPreflightRejectsNoncanonicalLanguage(t *testing.T) { + routine := &Udf{Language: "PYTHON"} + require.ErrorContains(t, routine.LoadPythonTypeContract(), "unsupported routine language") + require.ErrorContains(t, routine.ValidatePythonTypeContract(), "unsupported routine language") + require.ErrorContains(t, routine.ValidatePythonCatalogSignature(), "unsupported routine language") +} + +func TestSQLRoutineFingerprintAndCallUseSharedRevisionContract(t *testing.T) { + fingerprint, err := SQLRoutineFingerprint("select value + 1", "[\"bigint\"]", "bigint") + require.NoError(t, err) + require.Len(t, fingerprint, 64) + changed, err := SQLRoutineFingerprint("select value + 2", "[\"bigint\"]", "bigint") + require.NoError(t, err) + require.NotEqual(t, fingerprint, changed) + + routine := &Udf{ + FunctionID: 41, + AccountID: 7, + DatabaseID: 8, + Revision: 3, + NamespaceVersion: 4, + Language: udf.LanguageSQL, + RetType: "bigint", + ArgsType: []types.Type{types.T_int64.ToType()}, + DefinitionFingerprint: fingerprint, + SemanticDefinitionSchemaVersion: udf.SQLDefinitionSchemaVersion, + Volatility: "VOLATILE", + NullPolicy: udf.NullCallHandler, + } + call, err := routine.GetRoutineCall() + require.NoError(t, err) + require.Equal(t, udf.LanguageSQL, call.Language) + require.Equal(t, &planpb.FunctionRef{ + FunctionId: 41, Revision: 3, NamespaceVersion: 4, AccountId: 7, DatabaseId: 8, + }, call.FunctionRef) + require.Equal(t, fingerprint, string(call.GetSql().DefinitionFingerprint)) + require.Equal(t, int32(udf.SQLDefinitionSchemaVersion), call.GetSql().SemanticDefinitionSchemaVersion) + require.True(t, call.MayError) + require.Equal(t, "DEFINER", call.SecurityMode) + require.False(t, call.Leakproof) +} + +func TestPythonJSONPlanRequiresExactIdentity(t *testing.T) { + raw, err := json.Marshal(UdfWithContext{ + Udf: &Udf{ + Language: "python", + Body: `{"legacy":true}`, + }, + PlanContractVersion: udf.PythonPlanContractVersion, + }) + require.NoError(t, err) + _, err = DecodeUdfWithContext(raw) + require.ErrorContains(t, err, "JSON plan is not executable") +} + +func TestPythonInvocationTupleUsesOneShotGroupsByDefault(t *testing.T) { + first, err := NewInvocationTuple(nil, "query-1", 7) + require.NoError(t, err) + second, err := NewInvocationTuple(nil, "query-1", 7) + require.NoError(t, err) + require.NotEqual(t, first.InvocationID, second.InvocationID) + require.NotEqual(t, first.GroupID, second.GroupID) + require.Equal(t, first.GroupEpoch, uint64(1)) + require.Equal(t, second.GroupEpoch, uint64(1)) + + _, err = NewInvocationTuple(map[string]string{"group_id": "shared-group"}, "query-1", 7) + require.ErrorContains(t, err, "explicit group_id requires group_epoch") + shared, err := NewInvocationTuple(map[string]string{ + "group_id": "shared-group", + "group_epoch": "3", + }, "query-1", 7) + require.NoError(t, err) + require.Equal(t, "shared-group", shared.GroupID) + require.Equal(t, uint64(3), shared.GroupEpoch) +} diff --git a/pkg/sql/plan/returning.go b/pkg/sql/plan/returning.go index 9f9df4d17f32c..6408ab2f54bf4 100644 --- a/pkg/sql/plan/returning.go +++ b/pkg/sql/plan/returning.go @@ -329,6 +329,9 @@ func (builder *QueryBuilder) appendReturningProjection(exprs tree.SelectExprs, b if len(exprs) == 0 { return nil } + previousReturningBinding := builder.bindingReturningProjection + builder.bindingReturningProjection = true + defer func() { builder.bindingReturningProjection = previousReturningBinding }() if builder.returningSourceStep < 0 || builder.returningTableDef == nil { return moerr.NewInternalError(builder.GetContext(), "DML RETURNING row image was not materialized") } diff --git a/pkg/sql/plan/routine_dependency.go b/pkg/sql/plan/routine_dependency.go new file mode 100644 index 0000000000000..f589ad616ddc9 --- /dev/null +++ b/pkg/sql/plan/routine_dependency.go @@ -0,0 +1,125 @@ +// Copyright 2026 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 plan + +import ( + "fmt" + "strings" + + "github.com/matrixorigin/matrixone/pkg/udf/udferr" + + planpb "github.com/matrixorigin/matrixone/pkg/pb/plan" + "github.com/matrixorigin/matrixone/pkg/udf" +) + +// maxRoutinePlanDependencies bounds the amount of catalog state retained by +// one executable plan. A plan with more distinct routine revisions is rejected +// during binding instead of creating an unbounded cache invalidation payload. +const maxRoutinePlanDependencies = 1024 + +// assignRoutineCallsite gives a bound routine expression a stable identity +// within its plan. It is not a function identity and is never used for +// catalog lookup; it lets the physical stage, diagnostics and future +// scheduler account for two references to the same revision independently. +func (builder *QueryBuilder) assignRoutineCallsite(call *planpb.RoutineCall) error { + if builder == nil || call == nil { + return nil + } + if call.Language != udf.LanguageSQL && call.Language != udf.LanguagePython { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: routine call language %q is not canonical", call.Language) + } + if call.CallsiteId != "" { + if len(call.CallsiteId) > 256 || strings.ContainsAny(call.CallsiteId, "\r\n") { + return udferr.Newf("PROGRAM_LIMIT_EXCEEDED: routine callsite id is too large or invalid") + } + return nil + } + if builder.nextRoutineCallID == ^uint64(0) { + return udferr.Newf("PROGRAM_LIMIT_EXCEEDED: routine callsite id exhausted") + } + builder.nextRoutineCallID++ + call.CallsiteId = fmt.Sprintf("%s/%d", strings.ToLower(call.Language), builder.nextRoutineCallID) + return nil +} + +func (builder *QueryBuilder) recordRoutinePlanDependency(call *planpb.RoutineCall) error { + if builder == nil || builder.qry == nil || call == nil || call.FunctionRef == nil { + return nil + } + if call.Language != udf.LanguageSQL && call.Language != udf.LanguagePython { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: routine call language %q is not canonical", call.Language) + } + ref := call.FunctionRef + dependency := &planpb.RoutinePlanDependency{ + FunctionRef: &planpb.FunctionRef{ + FunctionId: ref.FunctionId, + Revision: ref.Revision, + NamespaceVersion: ref.NamespaceVersion, + AccountId: ref.AccountId, + DatabaseId: ref.DatabaseId, + }, + Language: call.Language, + NamespaceFingerprint: call.NamespaceFingerprint, + ContractVersion: call.ContractVersion, + DefinitionFingerprint: "", + Volatility: call.Volatility, + NullPolicy: call.NullPolicy, + MayError: call.MayError, + SecurityMode: call.SecurityMode, + Leakproof: call.Leakproof, + } + if python := call.GetPython(); python != nil { + dependency.DefinitionFingerprint = python.DefinitionFingerprint + dependency.ArtifactDigest = python.ArtifactDigest + dependency.EnvironmentDigest = python.EnvironmentDigest + } else if sql := call.GetSql(); sql != nil { + // SQL uses the same dependency envelope. The implementation digest is + // stored as the canonical hexadecimal SHA-256 string so cache + // validation has the same representation across languages. + dependency.DefinitionFingerprint = string(sql.DefinitionFingerprint) + } + for _, existing := range builder.qry.RoutineDependencies { + if routinePlanDependenciesEqual(existing, dependency) { + return nil + } + } + if len(builder.qry.RoutineDependencies) >= maxRoutinePlanDependencies { + return udferr.Newf("PROGRAM_LIMIT_EXCEEDED: routine dependency count exceeds %d", maxRoutinePlanDependencies) + } + builder.qry.RoutineDependencies = append(builder.qry.RoutineDependencies, dependency) + return nil +} + +func routinePlanDependenciesEqual(left, right *planpb.RoutinePlanDependency) bool { + if left == nil || right == nil || left.FunctionRef == nil || right.FunctionRef == nil { + return left == right + } + return left.NamespaceFingerprint == right.NamespaceFingerprint && + left.Language == right.Language && + left.ContractVersion == right.ContractVersion && + left.DefinitionFingerprint == right.DefinitionFingerprint && + left.ArtifactDigest == right.ArtifactDigest && + left.EnvironmentDigest == right.EnvironmentDigest && + left.Volatility == right.Volatility && + left.NullPolicy == right.NullPolicy && + left.MayError == right.MayError && + left.SecurityMode == right.SecurityMode && + left.Leakproof == right.Leakproof && + left.FunctionRef.FunctionId == right.FunctionRef.FunctionId && + left.FunctionRef.Revision == right.FunctionRef.Revision && + left.FunctionRef.NamespaceVersion == right.FunctionRef.NamespaceVersion && + left.FunctionRef.AccountId == right.FunctionRef.AccountId && + left.FunctionRef.DatabaseId == right.FunctionRef.DatabaseId +} diff --git a/pkg/sql/plan/routine_dependency_test.go b/pkg/sql/plan/routine_dependency_test.go new file mode 100644 index 0000000000000..0a49b099d6e12 --- /dev/null +++ b/pkg/sql/plan/routine_dependency_test.go @@ -0,0 +1,128 @@ +// Copyright 2026 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 plan + +import ( + "testing" + + planpb "github.com/matrixorigin/matrixone/pkg/pb/plan" + "github.com/matrixorigin/matrixone/pkg/udf" + "github.com/stretchr/testify/require" +) + +func testRoutineCallForDependency() *planpb.RoutineCall { + return &planpb.RoutineCall{ + ContractVersion: udf.PythonPlanContractVersion, + FunctionRef: &planpb.FunctionRef{ + FunctionId: 11, + Revision: 3, + NamespaceVersion: 4, + AccountId: 5, + DatabaseId: 6, + }, + Language: udf.LanguagePython, + Volatility: "VOLATILE", + NullPolicy: udf.NullCallHandler, + MayError: true, + SecurityMode: "INVOKER", + Leakproof: false, + Implementation: &planpb.RoutineCall_Python{Python: &planpb.PythonRoutineImplementation{ + DefinitionFingerprint: "fingerprint", + ArtifactDigest: "artifact", + EnvironmentDigest: "environment", + }}, + } +} + +func TestRecordRoutinePlanDependencyDeduplicatesAndCopiesIdentity(t *testing.T) { + builder := &QueryBuilder{qry: &planpb.Query{}} + call := testRoutineCallForDependency() + + require.NoError(t, builder.recordRoutinePlanDependency(call)) + require.NoError(t, builder.recordRoutinePlanDependency(call)) + require.Len(t, builder.qry.RoutineDependencies, 1) + + dependency := builder.qry.RoutineDependencies[0] + require.Equal(t, uint64(11), dependency.FunctionRef.FunctionId) + require.Equal(t, uint64(3), dependency.FunctionRef.Revision) + require.Equal(t, "fingerprint", dependency.DefinitionFingerprint) + require.Equal(t, "artifact", dependency.ArtifactDigest) + require.Equal(t, "environment", dependency.EnvironmentDigest) + require.Equal(t, "VOLATILE", dependency.Volatility) + require.Equal(t, udf.NullCallHandler, dependency.NullPolicy) + require.True(t, dependency.MayError) + require.Equal(t, "INVOKER", dependency.SecurityMode) + require.False(t, dependency.Leakproof) + + // The envelope is a plan-owned snapshot of the call identity. Mutating the + // source FunctionRef after binding must not mutate cache validation state. + call.FunctionRef.Revision = 99 + require.Equal(t, uint64(3), dependency.FunctionRef.Revision) +} + +func TestAssignRoutineCallsiteIsPlanLocalAndIdempotent(t *testing.T) { + builder := &QueryBuilder{qry: &planpb.Query{}} + call := testRoutineCallForDependency() + require.NoError(t, builder.assignRoutineCallsite(call)) + require.Equal(t, "python/1", call.CallsiteId) + require.NoError(t, builder.assignRoutineCallsite(call)) + require.Equal(t, "python/1", call.CallsiteId) + + second := testRoutineCallForDependency() + require.NoError(t, builder.assignRoutineCallsite(second)) + require.Equal(t, "python/2", second.CallsiteId) +} + +func TestRoutineDependencyRejectsNoncanonicalLanguage(t *testing.T) { + builder := &QueryBuilder{qry: &planpb.Query{}} + call := testRoutineCallForDependency() + call.Language = "PYTHON" + require.ErrorContains(t, builder.assignRoutineCallsite(call), "language") + require.ErrorContains(t, builder.recordRoutinePlanDependency(call), "language") +} + +func TestRecordRoutinePlanDependencyBoundsPlanClosure(t *testing.T) { + builder := &QueryBuilder{qry: &planpb.Query{ + RoutineDependencies: make([]*planpb.RoutinePlanDependency, maxRoutinePlanDependencies), + }} + + err := builder.recordRoutinePlanDependency(testRoutineCallForDependency()) + require.ErrorContains(t, err, "PROGRAM_LIMIT_EXCEEDED") +} + +func TestRecordSQLRoutinePlanDependencyUsesSharedEnvelope(t *testing.T) { + builder := &QueryBuilder{qry: &planpb.Query{}} + call := &planpb.RoutineCall{ + ContractVersion: udf.RoutinePlanContractVersion, + FunctionRef: &planpb.FunctionRef{ + FunctionId: 11, Revision: 3, NamespaceVersion: 4, AccountId: 5, DatabaseId: 6, + }, + Language: udf.LanguageSQL, + Volatility: "VOLATILE", + NullPolicy: udf.NullCallHandler, + MayError: true, + SecurityMode: "DEFINER", + Leakproof: false, + Implementation: &planpb.RoutineCall_Sql{Sql: &planpb.SqlRoutineImplementation{ + DefinitionFingerprint: []byte("0123456789abcdef"), + }}, + } + require.NoError(t, builder.recordRoutinePlanDependency(call)) + require.Len(t, builder.qry.RoutineDependencies, 1) + require.Equal(t, udf.LanguageSQL, builder.qry.RoutineDependencies[0].Language) + require.Equal(t, "0123456789abcdef", builder.qry.RoutineDependencies[0].DefinitionFingerprint) + require.Empty(t, builder.qry.RoutineDependencies[0].ArtifactDigest) + require.Empty(t, builder.qry.RoutineDependencies[0].EnvironmentDigest) +} diff --git a/pkg/sql/plan/rule/constant_fold.go b/pkg/sql/plan/rule/constant_fold.go index a7ca93f35abce..949ce8f193865 100644 --- a/pkg/sql/plan/rule/constant_fold.go +++ b/pkg/sql/plan/rule/constant_fold.go @@ -215,6 +215,12 @@ func (r *ConstantFold) constantFold(expr *plan.Expr, proc *process.Process) *pla return expr } + // A typed RoutineCall is an execute-time boundary. Even a zero-argument + // call with only literal metadata must reach ExternalRoutineEval so that + // volatility, row cardinality, and the captured revision remain intact. + if fn.RoutineCall != nil { + return expr + } overloadID := fn.Func.GetObj() if r.isPrepared && IsNullIntegerArgumentCast(expr) { return expr @@ -948,6 +954,9 @@ func IsConstant(e *plan.Expr, varAndParamIsConst bool) bool { case *plan.Expr_Lit, *plan.Expr_T, *plan.Expr_Vec: return true case *plan.Expr_F: + if ef.F == nil || ef.F.RoutineCall != nil { + return false + } // CASE expressions should always be evaluated at runtime to preserve // branch semantics; treat them as non-constant. if fid, _ := function.DecodeOverloadID(ef.F.Func.GetObj()); fid == function.CASE { diff --git a/pkg/sql/plan/rule/constant_fold_test.go b/pkg/sql/plan/rule/constant_fold_test.go index 7b8e72accc2d0..4f5455fe96328 100644 --- a/pkg/sql/plan/rule/constant_fold_test.go +++ b/pkg/sql/plan/rule/constant_fold_test.go @@ -71,6 +71,29 @@ func TestConstantFoldRuleRetainsStandaloneInterval(t *testing.T) { require.Same(t, expr, NewConstantFold(false).constantFold(expr, testutil.NewProcess(t))) } +func TestConstantFoldRuleNeverExecutesTypedRoutineCall(t *testing.T) { + expr := &plan.Expr{ + Typ: plan.Type{Id: int32(types.T_int64)}, + Expr: &plan.Expr_F{F: &plan.Function{ + Func: &plan.ObjectRef{ + Obj: function.EncodeOverloadID(function.PYTHON_UDF, 0), + ObjName: "python_user_defined_function", + }, + Args: []*plan.Expr{{ + Typ: plan.Type{Id: int32(types.T_int64)}, + Expr: &plan.Expr_Lit{Lit: &plan.Literal{Value: &plan.Literal_I64Val{I64Val: 1}}}, + }}, + RoutineCall: &plan.RoutineCall{ + FunctionRef: &plan.FunctionRef{FunctionId: 1, DatabaseId: 1, Revision: 1, NamespaceVersion: 1}, + Language: "PYTHON", + }, + }}, + } + + require.False(t, IsConstant(expr, false)) + require.Same(t, expr, NewConstantFold(false).constantFold(expr, testutil.NewProcess(t))) +} + func TestGetConstantValue2PreservesAndValidatesLiteralStringSource(t *testing.T) { proc := testutil.NewProcess(t) vec := vector.NewVec(types.T_varchar.ToType()) diff --git a/pkg/sql/plan/types.go b/pkg/sql/plan/types.go index 051c9245d907b..ae15d03b39472 100644 --- a/pkg/sql/plan/types.go +++ b/pkg/sql/plan/types.go @@ -475,6 +475,11 @@ type QueryBuilder struct { nextBindTag int32 nextMsgTag int32 nextSQLUdfCallID uint64 + // nextRoutineCallID gives every typed routine expression a plan-local + // callsite identity. It is deliberately separate from the SQL body + // substitution counter: lowering must not make a callsite depend on the + // number of generated parameter markers. + nextRoutineCallID uint64 isPrepareStatement bool mysqlCompatible bool @@ -587,13 +592,14 @@ type QueryBuilder struct { // returningFilterPos identifies an optional semantic eligibility selector in // the materialized row image. It filters only the RETURNING reader; mutation // readers continue to consume implicit FK action rows. - returningFilterPos int32 - returningRequested bool - returningTableDef *plan.TableDef - returningObjRef *plan.ObjectRef - returningTableName string - returningAlias string - returningColPos map[string]int32 + returningFilterPos int32 + returningRequested bool + bindingReturningProjection bool + returningTableDef *plan.TableDef + returningObjRef *plan.ObjectRef + returningTableName string + returningAlias string + returningColPos map[string]int32 // updateParentActionStack bounds recursive ON UPDATE actions by the active // physical-table path. Acyclic multi-layer cascades recurse normally; a // cycle is rejected before any mutation step is appended. diff --git a/pkg/sql/plan/utils.go b/pkg/sql/plan/utils.go index 73bef9ec035ec..7490ec00b2af5 100644 --- a/pkg/sql/plan/utils.go +++ b/pkg/sql/plan/utils.go @@ -2083,6 +2083,11 @@ func constantFoldWithPreparedExactSource( if fn == nil || proc == nil { return expr, nil } + // Typed external routines are execute-time calls. Do not let statistics or + // binder-side folding execute or replace a captured FunctionRef/revision. + if fn.RoutineCall != nil { + return expr, nil + } overloadID := fn.Func.GetObj() functionID, _ := function.DecodeOverloadID(overloadID) diff --git a/pkg/udf/Makefile b/pkg/udf/Makefile deleted file mode 100644 index 21ee463ed71e4..0000000000000 --- a/pkg/udf/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2023 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. - -.PHONY: clean -clean: - rm -f udf.pb.go - rm -f udf_grpc.pb.go - rm -f pythonservice/pyserver/python_udf_pb2.py - rm -f pythonservice/pyserver/python_udf_pb2.pyi - rm -f pythonservice/pyserver/python_udf_pb2_grpc.py - -.PHONY: generate -generate: - protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./udf.proto - @cd pythonservice/pyserver && python -m grpc_tools.protoc -I ../../ --python_out=. --pyi_out=. --grpc_python_out=. ../../udf.proto diff --git a/pkg/udf/protocol/protocol.go b/pkg/udf/protocol/protocol.go new file mode 100644 index 0000000000000..4b4418a441b4f --- /dev/null +++ b/pkg/udf/protocol/protocol.go @@ -0,0 +1,1038 @@ +// Copyright 2026 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 protocol contains the transport-independent contracts shared by the +// Python UDF gateway and its callers. It deliberately does not know about +// gRPC, Arrow, or a particular scheduler implementation. +package protocol + +import ( + "bytes" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "errors" + "io" + "sync" + "time" + "unicode/utf8" + + "github.com/matrixorigin/matrixone/pkg/udf/udferr" + "github.com/matrixorigin/matrixone/pkg/util/errutil" +) + +const ( + // Version identifies the control envelope understood by this runtime. It is + // a wire compatibility field, not a language or package name. + Version = 1 + + // MaxControlBytes is a trust-boundary ceiling. A runtime may negotiate a + // smaller limit, but a caller must never silently raise it. + MaxControlBytes = 1 << 20 + + // MaxFenceComponentBytes bounds the identity retained by active and + // terminal ledgers. The wire envelope is larger than a single component, + // but allowing an unbounded statement/group/invocation string would make + // every bounded entry claim an unbounded memory claim. + MaxFenceComponentBytes = 256 + // Control JSON is intentionally shallow. The byte bound alone is not a + // stack bound because duplicate-key validation walks nested arrays/objects + // before encoding/json can decode the envelope. + MaxJSONNesting = 64 +) + +var ( + ErrProtocol = udferr.New("python udf protocol violation") + ErrSequence = udferr.New("python udf sequence violation") + ErrGroupClosed = udferr.New("python udf execution group is closed") + ErrDuplicate = udferr.New("python udf identity is already present") + ErrLedgerFull = udferr.New("python udf terminal ledger is full") + ErrUnknownIdentity = udferr.New("python udf identity is unknown") +) + +// FencingTuple is carried by every invocation control and data-plane +// application message. IDs are never reused while their fence/tombstone is +// retained. The tuple is a deduplication fence, not an authentication token. +type FencingTuple struct { + AccountID uint64 `json:"account_id"` + StatementID string `json:"statement_id"` + GroupID string `json:"group_id"` + GroupEpoch uint64 `json:"group_epoch"` + InvocationID string `json:"invocation_id"` + LeaseEpoch uint64 `json:"lease_epoch"` +} + +func (t FencingTuple) Validate() error { + // Account zero is the reserved system account in MatrixOne and is a valid + // execution identity. The remaining fields are generation fences and must + // never be zero or empty. + if t.StatementID == "" || t.GroupID == "" || + t.GroupEpoch == 0 || t.InvocationID == "" || t.LeaseEpoch == 0 { + return errutil.WrapfCauseFirst(ErrProtocol, "incomplete fencing tuple") + } + if !utf8.ValidString(t.StatementID) || !utf8.ValidString(t.GroupID) || !utf8.ValidString(t.InvocationID) { + return errutil.WrapfCauseFirst(ErrProtocol, "fencing tuple contains invalid UTF-8") + } + if len(t.StatementID) > MaxFenceComponentBytes || len(t.GroupID) > MaxFenceComponentBytes || len(t.InvocationID) > MaxFenceComponentBytes { + return errutil.WrapfCauseFirst(ErrProtocol, "fencing tuple component is too large") + } + return nil +} + +// Control is the small, canonical application envelope carried in Flight +// app_metadata. Payload is a versioned descriptor or error body owned by the +// message kind; it is bounded before JSON decoding. +type Control struct { + Version int `json:"version"` + Kind string `json:"kind"` + Tuple FencingTuple `json:"tuple"` + Sequence uint64 `json:"sequence,omitempty"` + LastSequence uint64 `json:"last_sequence,omitempty"` + AckSequence uint64 `json:"ack_sequence,omitempty"` + ReleasedBytes int64 `json:"released_bytes,omitempty"` + ReleasedBatches uint64 `json:"released_batches,omitempty"` + LastResultSequence uint64 `json:"last_result_sequence,omitempty"` + FinishID string `json:"finish_id,omitempty"` + Status string `json:"status,omitempty"` + Reason string `json:"reason,omitempty"` + Payload json.RawMessage `json:"payload,omitempty"` +} + +type controlFieldRule struct { + allowed map[string]struct{} + required map[string]struct{} +} + +var controlFieldRules = map[string]controlFieldRule{ + "OpenInvocation": {allowed: map[string]struct{}{"payload": {}}, required: map[string]struct{}{"payload": {}}}, + "InputBatch": {allowed: map[string]struct{}{"sequence": {}}, required: map[string]struct{}{"sequence": {}}}, + "EndInput": {allowed: map[string]struct{}{"last_sequence": {}}, required: map[string]struct{}{"last_sequence": {}}}, + "ResultSchema": {allowed: map[string]struct{}{}}, + "InputConsumed": {allowed: map[string]struct{}{"sequence": {}, "released_bytes": {}, "released_batches": {}}, required: map[string]struct{}{"sequence": {}, "released_bytes": {}, "released_batches": {}}}, + "ResultBatch": {allowed: map[string]struct{}{"sequence": {}}, required: map[string]struct{}{"sequence": {}}}, + "Finish": {allowed: map[string]struct{}{"last_sequence": {}, "last_result_sequence": {}, "finish_id": {}, "status": {}}, required: map[string]struct{}{"last_sequence": {}, "last_result_sequence": {}, "finish_id": {}, "status": {}}}, + "AcknowledgeResults": {allowed: map[string]struct{}{"ack_sequence": {}}, required: map[string]struct{}{"ack_sequence": {}}}, + "AcknowledgeFinish": {allowed: map[string]struct{}{"finish_id": {}}, required: map[string]struct{}{"finish_id": {}}}, + "Ack": {allowed: map[string]struct{}{"ack_sequence": {}, "finish_id": {}, "status": {}}, required: map[string]struct{}{"status": {}}}, + "Error": {allowed: map[string]struct{}{"status": {}, "reason": {}}, required: map[string]struct{}{"status": {}, "reason": {}}}, +} + +var controlBaseFields = map[string]struct{}{ + "version": {}, "kind": {}, "tuple": {}, +} + +func validateControlFields(control Control, wire map[string]json.RawMessage) error { + rule, ok := controlFieldRules[control.Kind] + if !ok { + return errutil.WrapfCauseFirst(ErrProtocol, "unsupported control kind %q", control.Kind) + } + if wire != nil { + for field := range wire { + if _, base := controlBaseFields[field]; base { + continue + } + if _, allowed := rule.allowed[field]; !allowed { + return errutil.WrapfCauseFirst(ErrProtocol, "field %q is not valid for control kind %q", field, control.Kind) + } + } + for field := range rule.required { + if _, present := wire[field]; !present { + return errutil.WrapfCauseFirst(ErrProtocol, "control kind %q is missing field %q", control.Kind, field) + } + } + } + if control.Sequence != 0 { + if _, allowed := rule.allowed["sequence"]; !allowed { + return errutil.WrapfCauseFirst(ErrProtocol, "field %q is not valid for control kind %q", "sequence", control.Kind) + } + } + if control.LastSequence != 0 { + if _, allowed := rule.allowed["last_sequence"]; !allowed { + return errutil.WrapfCauseFirst(ErrProtocol, "field %q is not valid for control kind %q", "last_sequence", control.Kind) + } + } + if control.AckSequence != 0 { + if _, allowed := rule.allowed["ack_sequence"]; !allowed { + return errutil.WrapfCauseFirst(ErrProtocol, "field %q is not valid for control kind %q", "ack_sequence", control.Kind) + } + } + if control.ReleasedBytes != 0 { + if _, allowed := rule.allowed["released_bytes"]; !allowed { + return errutil.WrapfCauseFirst(ErrProtocol, "field %q is not valid for control kind %q", "released_bytes", control.Kind) + } + } + if control.ReleasedBatches != 0 { + if _, allowed := rule.allowed["released_batches"]; !allowed { + return errutil.WrapfCauseFirst(ErrProtocol, "field %q is not valid for control kind %q", "released_batches", control.Kind) + } + } + if control.LastResultSequence != 0 { + if _, allowed := rule.allowed["last_result_sequence"]; !allowed { + return errutil.WrapfCauseFirst(ErrProtocol, "field %q is not valid for control kind %q", "last_result_sequence", control.Kind) + } + } + if control.FinishID != "" { + if _, allowed := rule.allowed["finish_id"]; !allowed { + return errutil.WrapfCauseFirst(ErrProtocol, "field %q is not valid for control kind %q", "finish_id", control.Kind) + } + } + if control.Status != "" { + if _, allowed := rule.allowed["status"]; !allowed { + return errutil.WrapfCauseFirst(ErrProtocol, "field %q is not valid for control kind %q", "status", control.Kind) + } + } + if control.Reason != "" { + if _, allowed := rule.allowed["reason"]; !allowed { + return errutil.WrapfCauseFirst(ErrProtocol, "field %q is not valid for control kind %q", "reason", control.Kind) + } + } + if len(control.Payload) != 0 { + if _, allowed := rule.allowed["payload"]; !allowed { + return errutil.WrapfCauseFirst(ErrProtocol, "field %q is not valid for control kind %q", "payload", control.Kind) + } + } + switch control.Kind { + case "OpenInvocation": + if len(control.Payload) == 0 && wire == nil { + return errutil.WrapfCauseFirst(ErrProtocol, "control kind %q is missing field %q", control.Kind, "payload") + } + if len(control.Payload) != 0 { + var payload map[string]json.RawMessage + if err := json.Unmarshal(control.Payload, &payload); err != nil || payload == nil { + return errutil.WrapfCauseFirst(ErrProtocol, "control kind %q payload must be a JSON object", control.Kind) + } + if err := rejectDuplicateJSONKeys(control.Payload); err != nil { + return errutil.WrapfCauseFirst(ErrProtocol, "invalid control payload: %v", err) + } + } + case "InputBatch", "ResultBatch": + if control.Sequence == 0 { + return errutil.WrapfCauseFirst(ErrProtocol, "control kind %q requires a positive sequence", control.Kind) + } + case "InputConsumed": + if control.Sequence == 0 || control.ReleasedBytes <= 0 || control.ReleasedBatches == 0 { + return errutil.WrapfCauseFirst(ErrProtocol, "control kind %q requires sequence and positive released bytes/batches", control.Kind) + } + case "AcknowledgeResults": + if control.AckSequence == 0 { + return errutil.WrapfCauseFirst(ErrProtocol, "control kind %q requires a positive ack_sequence", control.Kind) + } + case "Finish": + if control.FinishID == "" || control.Status == "" { + return errutil.WrapfCauseFirst(ErrProtocol, "control kind %q requires finish_id and status", control.Kind) + } + case "AcknowledgeFinish": + if control.FinishID == "" { + return errutil.WrapfCauseFirst(ErrProtocol, "control kind %q requires finish_id", control.Kind) + } + case "Ack": + if control.Status == "" || ((control.AckSequence == 0) == (control.FinishID == "")) { + return errutil.WrapfCauseFirst(ErrProtocol, "Ack requires status and exactly one acknowledgement identity") + } + case "Error": + if control.Status == "" || control.Reason == "" { + return errutil.WrapfCauseFirst(ErrProtocol, "control kind %q requires status and reason", control.Kind) + } + } + return nil +} + +// MarshalJSON keeps closing controls self-describing when their final +// sequence is zero. The zero value is meaningful for an empty input stream; +// omitting it would make EndInput(0) indistinguishable from a malformed +// control at the Python boundary. Other controls retain the compact +// omission used for fields they do not own. +func (c Control) MarshalJSON() ([]byte, error) { + type wireControl struct { + Version int `json:"version"` + Kind string `json:"kind"` + Tuple FencingTuple `json:"tuple"` + Sequence uint64 `json:"sequence,omitempty"` + LastSequence *uint64 `json:"last_sequence,omitempty"` + AckSequence uint64 `json:"ack_sequence,omitempty"` + ReleasedBytes *int64 `json:"released_bytes,omitempty"` + ReleasedBatches *uint64 `json:"released_batches,omitempty"` + LastResultSequence *uint64 `json:"last_result_sequence,omitempty"` + FinishID string `json:"finish_id,omitempty"` + Status string `json:"status,omitempty"` + Reason string `json:"reason,omitempty"` + Payload json.RawMessage `json:"payload,omitempty"` + } + wire := wireControl{ + Version: c.Version, Kind: c.Kind, Tuple: c.Tuple, + Sequence: c.Sequence, AckSequence: c.AckSequence, + FinishID: c.FinishID, Status: c.Status, Reason: c.Reason, + Payload: c.Payload, + } + if c.Kind == "EndInput" || c.Kind == "Finish" || c.LastSequence != 0 { + lastSequence := c.LastSequence + wire.LastSequence = &lastSequence + } + if c.Kind == "Finish" { + lastResultSequence := c.LastResultSequence + wire.LastResultSequence = &lastResultSequence + } + if c.Kind == "InputConsumed" { + releasedBytes := c.ReleasedBytes + releasedBatches := c.ReleasedBatches + wire.ReleasedBytes = &releasedBytes + wire.ReleasedBatches = &releasedBatches + } + return json.Marshal(wire) +} + +// MarshalControl produces the byte representation used in the Flight +// application metadata field. Struct-field order is intentional: the same +// bytes are used when a descriptor fingerprint is calculated. +func MarshalControl(control Control) ([]byte, error) { + if control.Version == 0 { + control.Version = Version + } + if control.Version != Version || control.Kind == "" { + return nil, errutil.WrapfCauseFirst(ErrProtocol, "unsupported control version or empty kind") + } + if err := control.Tuple.Validate(); err != nil { + return nil, err + } + if err := validateControlFields(control, nil); err != nil { + return nil, err + } + encoded, err := json.Marshal(control) + if err != nil { + return nil, errutil.WrapfCauseFirst(ErrProtocol, "encode control: %v", err) + } + if len(encoded) > MaxControlBytes { + return nil, errutil.WrapfCauseFirst(ErrProtocol, "control is %d bytes, limit is %d", len(encoded), MaxControlBytes) + } + return encoded, nil +} + +func UnmarshalControl(data []byte) (Control, error) { + if len(data) == 0 || len(data) > MaxControlBytes { + return Control{}, errutil.WrapfCauseFirst(ErrProtocol, "control size %d is outside the allowed range", len(data)) + } + // encoding/json replaces invalid UTF-8 in JSON strings with U+FFFD. A + // fencing tuple is an identity, so accepting that replacement would make a + // malformed wire tuple refer to a different invocation than the sender + // intended. Reject the bytes before any JSON decoder can normalize them. + if !utf8.Valid(data) { + return Control{}, errutil.WrapfCauseFirst(ErrProtocol, "control contains invalid UTF-8") + } + if err := rejectDuplicateJSONKeys(data); err != nil { + return Control{}, errutil.WrapfCauseFirst(ErrProtocol, "%v", err) + } + var control Control + decoder := json.NewDecoder(bytes.NewReader(data)) + decoder.DisallowUnknownFields() + if err := decoder.Decode(&control); err != nil { + return Control{}, errutil.WrapfCauseFirst(ErrProtocol, "decode control: %v", err) + } + var trailing any + if err := decoder.Decode(&trailing); err != io.EOF { + if err == nil { + return Control{}, errutil.WrapfCauseFirst(ErrProtocol, "control contains trailing JSON") + } + return Control{}, errutil.WrapfCauseFirst(ErrProtocol, "decode trailing control data: %v", err) + } + if control.Version != Version || control.Kind == "" { + return Control{}, errutil.WrapfCauseFirst(ErrProtocol, "unsupported control version %d", control.Version) + } + if err := control.Tuple.Validate(); err != nil { + return Control{}, err + } + var fields map[string]json.RawMessage + if err := json.Unmarshal(data, &fields); err != nil { + return Control{}, errutil.WrapfCauseFirst(ErrProtocol, "control must be an object: %v", err) + } + if err := validateControlFields(control, fields); err != nil { + return Control{}, err + } + return control, nil +} + +func rejectDuplicateJSONKeys(data []byte) error { + decoder := json.NewDecoder(bytes.NewReader(data)) + if err := walkJSONValue(decoder); err != nil { + return err + } + var trailing any + if err := decoder.Decode(&trailing); err != io.EOF { + if err == nil { + return udferr.New("control contains trailing JSON") + } + return udferr.Newf("decode trailing control data: %v", err) + } + return nil +} + +func walkJSONValue(decoder *json.Decoder) error { + return walkJSONValueAtDepth(decoder, 0) +} + +func walkJSONValueAtDepth(decoder *json.Decoder, depth int) error { + token, err := decoder.Token() + if err != nil { + return udferr.Newf("decode control JSON: %v", err) + } + delim, ok := token.(json.Delim) + if !ok { + return nil + } + if depth >= MaxJSONNesting { + return udferr.Newf("control JSON nesting exceeds %d levels", MaxJSONNesting) + } + switch delim { + case '{': + seen := make(map[string]struct{}) + for decoder.More() { + keyToken, err := decoder.Token() + if err != nil { + return udferr.Newf("decode control object key: %v", err) + } + key, ok := keyToken.(string) + if !ok { + return udferr.New("control object key is not a string") + } + if _, exists := seen[key]; exists { + return udferr.Newf("duplicate control JSON field %q", key) + } + seen[key] = struct{}{} + if err := walkJSONValueAtDepth(decoder, depth+1); err != nil { + return err + } + } + _, err = decoder.Token() + return err + case '[': + for decoder.More() { + if err := walkJSONValueAtDepth(decoder, depth+1); err != nil { + return err + } + } + _, err = decoder.Token() + return err + default: + return udferr.Newf("unexpected control JSON delimiter %q", delim) + } +} + +// Sequence validates the independent input and result directions of one +// invocation. EndInput is a normal half-close; it does not make results +// terminal until all results have been acknowledged. +type Sequence struct { + mu sync.Mutex + nextInput uint64 + lastInput uint64 + inputEnded bool + nextResult uint64 + lastResult uint64 + ackedResult uint64 +} + +func (s *Sequence) AcceptInput(sequence uint64) error { + s.mu.Lock() + defer s.mu.Unlock() + if s.inputEnded { + return errutil.WrapfCauseFirst(ErrSequence, "input arrived after EndInput") + } + if sequence != s.nextInput+1 { + return errutil.WrapfCauseFirst(ErrSequence, "input sequence %d, expected %d", sequence, s.nextInput+1) + } + s.nextInput = sequence + s.lastInput = sequence + return nil +} + +func (s *Sequence) EndInput(lastSequence uint64) error { + s.mu.Lock() + defer s.mu.Unlock() + if s.inputEnded { + if s.lastInput == lastSequence { + return nil + } + return errutil.WrapfCauseFirst(ErrSequence, "EndInput changed from %d to %d", s.lastInput, lastSequence) + } + if lastSequence != s.lastInput { + return errutil.WrapfCauseFirst(ErrSequence, "EndInput last sequence %d, observed %d", lastSequence, s.lastInput) + } + s.inputEnded = true + return nil +} + +func (s *Sequence) AcceptResult(sequence uint64) error { + s.mu.Lock() + defer s.mu.Unlock() + if sequence != s.nextResult+1 || sequence > s.lastInput { + return errutil.WrapfCauseFirst(ErrSequence, "result sequence %d, expected %d and at most input %d", sequence, s.nextResult+1, s.lastInput) + } + s.nextResult = sequence + s.lastResult = sequence + return nil +} + +func (s *Sequence) AcknowledgeResults(sequence uint64) error { + s.mu.Lock() + defer s.mu.Unlock() + if sequence == 0 || sequence < s.ackedResult || sequence > s.lastResult { + return errutil.WrapfCauseFirst(ErrSequence, "result ACK %d outside [%d,%d]", sequence, s.ackedResult, s.lastResult) + } + s.ackedResult = sequence + return nil +} + +func (s *Sequence) ReadyToFinish() bool { + s.mu.Lock() + defer s.mu.Unlock() + return s.inputEnded && s.lastResult == s.lastInput && s.ackedResult == s.lastResult +} + +func (s *Sequence) State() (lastInput, lastResult, acked uint64, inputEnded bool) { + s.mu.Lock() + defer s.mu.Unlock() + return s.lastInput, s.lastResult, s.ackedResult, s.inputEnded +} + +// OutputSnapshot is the only representation that may cross the trusted +// validation/publication boundary. Freeze copies the worker-owned bytes +// before validation. The snapshot's backing is private, so later worker +// writes cannot change the bytes validated or published by the caller. +type OutputSnapshot struct { + backing []byte + digest [sha256.Size]byte +} + +func FreezeOutput(source []byte, maxBytes int64) (*OutputSnapshot, error) { + if maxBytes <= 0 || int64(len(source)) > maxBytes { + return nil, errutil.WrapfCauseFirst(ErrProtocol, "output snapshot size %d exceeds limit %d", len(source), maxBytes) + } + backing := make([]byte, len(source)) + copy(backing, source) + return &OutputSnapshot{backing: backing, digest: sha256.Sum256(backing)}, nil +} + +func (s *OutputSnapshot) Len() int { + if s == nil { + return 0 + } + return len(s.backing) +} + +func (s *OutputSnapshot) Digest() string { + if s == nil { + return "" + } + return hex.EncodeToString(s.digest[:]) +} + +func (s *OutputSnapshot) Validate(expectedLength int, expectedDigest string) error { + if s == nil || s.backing == nil { + return errutil.WrapfCauseFirst(ErrProtocol, "missing output snapshot") + } + if expectedLength >= 0 && len(s.backing) != expectedLength { + return errutil.WrapfCauseFirst(ErrProtocol, "output snapshot length %d, expected %d", len(s.backing), expectedLength) + } + currentDigest := sha256.Sum256(s.backing) + if currentDigest != s.digest { + return errutil.WrapfCauseFirst(ErrProtocol, "output snapshot backing changed") + } + if expectedDigest != "" && !equalFoldHex(expectedDigest, hex.EncodeToString(currentDigest[:])) { + return errutil.WrapfCauseFirst(ErrProtocol, "output snapshot digest changed") + } + return nil +} + +// Bytes returns a private copy for an API that cannot consume an immutable +// view. Validation and publication in a trusted consumer should operate on +// the same snapshot object, rather than refetching the worker buffer. +func (s *OutputSnapshot) Bytes() []byte { + if s == nil { + return nil + } + return append([]byte(nil), s.backing...) +} + +// TrustedBytes exposes the private frozen backing to a validator/consumer +// that is part of the same trusted boundary. The caller must treat the +// returned slice as read-only. It exists so validation and decoding can use +// exactly the bytes that were frozen, rather than refetching worker memory or +// making a second mutable copy between the two steps. +func (s *OutputSnapshot) TrustedBytes() []byte { + if s == nil { + return nil + } + return s.backing +} + +func equalFoldHex(left, right string) bool { + if len(left) != len(right) { + return false + } + for i := range left { + l, r := left[i], right[i] + if l >= 'A' && l <= 'F' { + l += 'a' - 'A' + } + if r >= 'A' && r <= 'F' { + r += 'a' - 'A' + } + if l != r { + return false + } + } + return true +} + +type GroupState string + +const ( + GroupReserved GroupState = "RESERVED" + GroupOpen GroupState = "OPEN" + GroupDraining GroupState = "DRAINING" + GroupReleased GroupState = "RELEASED" +) + +// CloseReason is deliberately a string so the scheduler can add a reason in +// a newer minor protocol without changing the lifetime rules. +type CloseReason string + +const ( + ReasonInputEOF CloseReason = "INPUT_EOF" + ReasonEmptyInput CloseReason = "EMPTY_INPUT" + ReasonAllNull CloseReason = "ALL_NULL" + ReasonNoSelectedRows CloseReason = "NO_SELECTED_ROWS" + ReasonPartialOpenError CloseReason = "PARTIAL_OPEN_FAILURE" + ReasonFailure CloseReason = "FAILURE" + ReasonCancel CloseReason = "CANCEL" + ReasonIdle CloseReason = "IDLE" +) + +// ExecutionGroup is a one-shot admission cohort. Member terminal cleanup +// only removes that member. The release callback belongs to the group owner +// and runs after close, all members terminal, and all in-flight opens finish. +type ExecutionGroup struct { + mu sync.Mutex + id string + epoch uint64 + maxMembers int + registered int + inFlight int + members map[string]bool + pending map[string]struct{} + terminal map[string]bool + closing bool + releaseBusy bool + releaseDone chan struct{} + releaseErr error + released bool + release func() error + reason CloseReason +} + +func NewExecutionGroup(id string, epoch uint64, maxMembers int, release func() error) (*ExecutionGroup, error) { + if id == "" || epoch == 0 || maxMembers <= 0 || release == nil { + return nil, errutil.WrapfCauseFirst(ErrProtocol, "invalid execution group") + } + return &ExecutionGroup{ + id: id, epoch: epoch, maxMembers: maxMembers, + members: make(map[string]bool), pending: make(map[string]struct{}), + terminal: make(map[string]bool), release: release, + }, nil +} + +// BeginOpen reserves one cumulative member-registration slot. The returned +// token must be committed or aborted exactly once by the Open owner. +func (g *ExecutionGroup) BeginOpen(memberID string) (*OpenToken, error) { + if memberID == "" { + return nil, errutil.WrapfCauseFirst(ErrProtocol, "empty member id") + } + g.mu.Lock() + defer g.mu.Unlock() + if g.closing || g.released { + return nil, ErrGroupClosed + } + if g.members[memberID] || g.terminal[memberID] { + return nil, ErrDuplicate + } + if _, exists := g.pending[memberID]; exists { + return nil, ErrDuplicate + } + if g.registered+g.inFlight >= g.maxMembers { + return nil, errutil.WrapfCauseFirst(ErrLedgerFull, "member limit %d reached", g.maxMembers) + } + g.pending[memberID] = struct{}{} + g.inFlight++ + return &OpenToken{group: g, memberID: memberID}, nil +} + +type OpenToken struct { + group *ExecutionGroup + memberID string + mu sync.Mutex + state openTokenState +} + +type openTokenState uint8 + +const ( + openTokenPending openTokenState = iota + openTokenCommitted + openTokenAborted +) + +func (t *OpenToken) Commit() error { + if t == nil || t.group == nil { + return ErrUnknownIdentity + } + if err := t.begin(openTokenCommitted); err != nil { + return err + } + g := t.group + g.mu.Lock() + delete(g.pending, t.memberID) + g.inFlight-- + if g.closing || g.released { + release := g.shouldReleaseLocked() + g.mu.Unlock() + if release { + return errors.Join(ErrGroupClosed, g.releaseIfReady()) + } + return ErrGroupClosed + } + g.members[t.memberID] = true + g.registered++ + g.mu.Unlock() + return nil +} + +func (t *OpenToken) Abort() error { + if t == nil || t.group == nil { + return ErrUnknownIdentity + } + if err := t.begin(openTokenAborted); err != nil { + return err + } + g := t.group + g.mu.Lock() + delete(g.pending, t.memberID) + g.inFlight-- + release := g.shouldReleaseLocked() + g.mu.Unlock() + if release { + return g.releaseIfReady() + } + return nil +} + +func (t *OpenToken) begin(state openTokenState) error { + t.mu.Lock() + defer t.mu.Unlock() + if t.state != openTokenPending { + return errutil.WrapfCauseFirst(ErrProtocol, "open token was already finalized") + } + t.state = state + return nil +} + +func (g *ExecutionGroup) Close(reason CloseReason) error { + if reason == "" { + return errutil.WrapfCauseFirst(ErrProtocol, "close reason is empty") + } + g.mu.Lock() + if g.closing && g.reason != reason { + g.mu.Unlock() + return errutil.WrapfCauseFirst(ErrProtocol, "close reason changed from %q to %q", g.reason, reason) + } + if g.released { + g.mu.Unlock() + return nil + } + if !g.closing { + g.closing = true + g.reason = reason + } + release := g.shouldReleaseLocked() + g.mu.Unlock() + if release { + return g.releaseIfReady() + } + return nil +} + +func (g *ExecutionGroup) MemberTerminal(memberID string) error { + g.mu.Lock() + if g.terminal[memberID] { + g.mu.Unlock() + return nil + } + if !g.members[memberID] { + g.mu.Unlock() + return ErrUnknownIdentity + } + delete(g.members, memberID) + g.terminal[memberID] = true + release := g.shouldReleaseLocked() + g.mu.Unlock() + if release { + return g.releaseIfReady() + } + return nil +} + +func (g *ExecutionGroup) shouldReleaseLocked() bool { + return g.closing && len(g.members) == 0 && g.inFlight == 0 && !g.released +} + +func (g *ExecutionGroup) releaseIfReady() error { + g.mu.Lock() + if !g.shouldReleaseLocked() { + g.mu.Unlock() + return nil + } + if g.releaseBusy { + done := g.releaseDone + g.mu.Unlock() + <-done + g.mu.Lock() + err := g.releaseErr + released := g.released + g.mu.Unlock() + if released { + return nil + } + return err + } + g.releaseBusy = true + g.releaseDone = make(chan struct{}) + done := g.releaseDone + g.mu.Unlock() + err := func() (err error) { + defer func() { + if recovered := recover(); recovered != nil { + err = errutil.WrapfCauseFirst(ErrProtocol, "group release panicked: %v", recovered) + } + }() + return g.release() + }() + g.mu.Lock() + g.releaseBusy = false + g.releaseErr = err + if err == nil { + g.released = true + } + close(done) + g.mu.Unlock() + return err +} + +func (g *ExecutionGroup) State() GroupState { + g.mu.Lock() + defer g.mu.Unlock() + if g.released { + return GroupReleased + } + if g.closing { + return GroupDraining + } + if g.registered > 0 { + return GroupOpen + } + return GroupReserved +} + +func (g *ExecutionGroup) Reason() CloseReason { + g.mu.Lock() + defer g.mu.Unlock() + return g.reason +} + +func (g *ExecutionGroup) Counts() (registered, active, inFlight int) { + g.mu.Lock() + defer g.mu.Unlock() + return g.registered, len(g.members), g.inFlight +} + +// ID and Epoch identify the ownership fence used by the group owner. They are +// immutable for the lifetime of an ExecutionGroup. +func (g *ExecutionGroup) ID() string { + if g == nil { + return "" + } + g.mu.Lock() + defer g.mu.Unlock() + return g.id +} + +func (g *ExecutionGroup) Epoch() uint64 { + if g == nil { + return 0 + } + g.mu.Lock() + defer g.mu.Unlock() + return g.epoch +} + +type ledgerEntry struct { + key string + groupID string + groupEpoch uint64 + bytes int64 + expiresAt time.Time + tombstone bool +} + +// TerminalLedger is an admission-reserved bounded deduplication ledger. A +// terminal entry is retained until expiry; it is never deleted merely to make +// room for a new invocation. +type TerminalLedger struct { + mu sync.Mutex + maxEntries int + maxBytes int64 + entries map[string]ledgerEntry + reservedN int + reservedB int64 +} + +type LedgerCredit struct { + ledger *TerminalLedger + groupID string + groupEpoch uint64 + remainingN int + remainingB int64 + closed bool +} + +func NewTerminalLedger(maxEntries int, maxBytes int64) (*TerminalLedger, error) { + if maxEntries <= 0 || maxBytes <= 0 { + return nil, errutil.WrapfCauseFirst(ErrProtocol, "invalid terminal ledger limit") + } + return &TerminalLedger{maxEntries: maxEntries, maxBytes: maxBytes, entries: make(map[string]ledgerEntry)}, nil +} + +func (l *TerminalLedger) Reserve(groupID string, groupEpoch uint64, entries int, bytes int64) (*LedgerCredit, error) { + if groupID == "" || groupEpoch == 0 || entries <= 0 || bytes <= 0 { + return nil, errutil.WrapfCauseFirst(ErrProtocol, "invalid terminal ledger reservation") + } + l.mu.Lock() + defer l.mu.Unlock() + if l.reservedN > l.maxEntries-entries || l.reservedB > l.maxBytes-bytes { + return nil, ErrLedgerFull + } + l.reservedN += entries + l.reservedB += bytes + return &LedgerCredit{ledger: l, groupID: groupID, groupEpoch: groupEpoch, remainingN: entries, remainingB: bytes}, nil +} + +func (c *LedgerCredit) Add(key string, bytes int64, expiry time.Time) error { + if c == nil || c.ledger == nil || key == "" || bytes <= 0 || expiry.IsZero() { + return errutil.WrapfCauseFirst(ErrProtocol, "invalid terminal ledger entry") + } + c.ledger.mu.Lock() + defer c.ledger.mu.Unlock() + if c.closed || c.remainingN == 0 || c.remainingB < bytes { + return ErrLedgerFull + } + if _, exists := c.ledger.entries[key]; exists { + return ErrDuplicate + } + c.ledger.entries[key] = ledgerEntry{key: key, groupID: c.groupID, groupEpoch: c.groupEpoch, bytes: bytes, expiresAt: expiry} + c.remainingN-- + c.remainingB -= bytes + return nil +} + +func (c *LedgerCredit) ReleaseUnused() { + if c == nil || c.ledger == nil { + return + } + c.ledger.mu.Lock() + defer c.ledger.mu.Unlock() + if c.closed { + return + } + c.ledger.reservedN -= c.remainingN + c.ledger.reservedB -= c.remainingB + c.remainingN = 0 + c.remainingB = 0 + c.closed = true +} + +func (l *TerminalLedger) Complete(key string) error { + l.mu.Lock() + defer l.mu.Unlock() + entry, ok := l.entries[key] + if !ok { + return ErrUnknownIdentity + } + if entry.tombstone { + return nil + } + entry.tombstone = true + l.entries[key] = entry + return nil +} + +// EpochFence is supplied by the Scheduler/group owner. It must return true +// only after the owner has durably or monotonically closed the corresponding +// group epoch so that an old grant cannot be issued again. A wall clock TTL is +// deliberately insufficient proof and a nil fence therefore reclaims nothing. +// The callback must not call back into the ledger. +type EpochFence func(groupID string, groupEpoch uint64) bool + +func (l *TerminalLedger) Expire(now time.Time, fence EpochFence) int { + l.mu.Lock() + defer l.mu.Unlock() + removed := 0 + for key, entry := range l.entries { + // Active entries represent work that may still produce a result. Their + // admission credit belongs to the running execution and can only be + // released by an explicit termination/recovery path. Expiry is solely + // for completed deduplication tombstones. + if !entry.tombstone { + continue + } + if !now.Before(entry.expiresAt) && fence != nil && fence(entry.groupID, entry.groupEpoch) { + delete(l.entries, key) + l.reservedN-- + l.reservedB -= entry.bytes + removed++ + } + } + return removed +} + +// Abandon removes an active execution after its owner has confirmed +// cancellation, crash recovery, or another terminal failure. It is separate +// from Expire so a clock cannot reclaim a live invocation's deduplication +// entry. +func (l *TerminalLedger) Abandon(key string) error { + l.mu.Lock() + defer l.mu.Unlock() + entry, ok := l.entries[key] + if !ok { + return ErrUnknownIdentity + } + if entry.tombstone { + return ErrProtocol + } + delete(l.entries, key) + l.reservedN-- + l.reservedB -= entry.bytes + return nil +} + +func (l *TerminalLedger) Counts() (entries int, bytes int64) { + l.mu.Lock() + defer l.mu.Unlock() + return len(l.entries), l.reservedB +} diff --git a/pkg/udf/protocol/protocol_test.go b/pkg/udf/protocol/protocol_test.go new file mode 100644 index 0000000000000..13334a95b6016 --- /dev/null +++ b/pkg/udf/protocol/protocol_test.go @@ -0,0 +1,471 @@ +// Copyright 2026 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 protocol + +import ( + "bytes" + "encoding/json" + "errors" + "strings" + "sync" + "sync/atomic" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func testTuple() FencingTuple { + return FencingTuple{ + AccountID: 1, StatementID: "statement", GroupID: "group", + GroupEpoch: 2, InvocationID: "invocation", LeaseEpoch: 3, + } +} + +func TestControlRoundTripIsBoundedAndVersioned(t *testing.T) { + wire, err := MarshalControl(Control{Kind: "OpenInvocation", Tuple: testTuple(), Payload: []byte(`{"mode":"VECTOR"}`)}) + require.NoError(t, err) + got, err := UnmarshalControl(wire) + require.NoError(t, err) + require.Equal(t, Version, got.Version) + require.Equal(t, "OpenInvocation", got.Kind) + require.JSONEq(t, `{"mode":"VECTOR"}`, string(got.Payload)) + + _, err = UnmarshalControl(bytes.Repeat([]byte{'x'}, MaxControlBytes+1)) + require.ErrorIs(t, err, ErrProtocol) + _, err = UnmarshalControl(append(wire, []byte(" trailing")...)) + require.ErrorIs(t, err, ErrProtocol) + _, err = MarshalControl(Control{Kind: "", Tuple: testTuple()}) + require.ErrorIs(t, err, ErrProtocol) +} + +func TestControlRejectsUnknownEnvelopeFields(t *testing.T) { + wire, err := MarshalControl(Control{Kind: "InputBatch", Tuple: testTuple(), Sequence: 1}) + require.NoError(t, err) + var object map[string]any + require.NoError(t, json.Unmarshal(wire, &object)) + object["future_field"] = "must not be ignored" + wire, err = json.Marshal(object) + require.NoError(t, err) + _, err = UnmarshalControl(wire) + require.ErrorIs(t, err, ErrProtocol) + require.ErrorContains(t, err, "unknown field") +} + +func TestControlRejectsDuplicateJSONFields(t *testing.T) { + wire := []byte(`{"version":1,"kind":"InputBatch","tuple":{"account_id":1,"statement_id":"statement","group_id":"group","group_epoch":2,"invocation_id":"invocation","lease_epoch":3},"sequence":1,"sequence":2}`) + _, err := UnmarshalControl(wire) + require.ErrorIs(t, err, ErrProtocol) + require.ErrorContains(t, err, "duplicate control JSON field") +} + +func TestControlRejectsExcessiveJSONNesting(t *testing.T) { + deepPayload := `{"value":` + strings.Repeat("[", MaxJSONNesting) + "0" + strings.Repeat("]", MaxJSONNesting) + "}" + wire, err := MarshalControl(Control{ + Kind: "OpenInvocation", + Tuple: testTuple(), + Payload: json.RawMessage(deepPayload), + }) + require.ErrorContains(t, err, "nesting exceeds") + require.Nil(t, wire) + + // The same bound must protect an incoming frame even when it was produced + // by an older or non-Go peer that did not enforce the outbound check. + outer := `{"version":1,"kind":"OpenInvocation","tuple":{"account_id":1,"statement_id":"statement","group_id":"group","group_epoch":2,"invocation_id":"invocation","lease_epoch":3},"payload":` + deepPayload + `}` + _, err = UnmarshalControl([]byte(outer)) + require.ErrorContains(t, err, "nesting exceeds") +} + +func TestOpenInvocationPayloadMustBeObject(t *testing.T) { + for _, payload := range []string{"null", "[]", `"text"`} { + wire := []byte(`{"version":1,"kind":"OpenInvocation","tuple":{"account_id":1,"statement_id":"statement","group_id":"group","group_epoch":2,"invocation_id":"invocation","lease_epoch":3},"payload":` + payload + `}`) + _, err := UnmarshalControl(wire) + require.ErrorIs(t, err, ErrProtocol) + require.ErrorContains(t, err, "payload must be a JSON object") + + _, err = MarshalControl(Control{Kind: "OpenInvocation", Tuple: testTuple(), Payload: json.RawMessage(payload)}) + require.ErrorIs(t, err, ErrProtocol) + require.ErrorContains(t, err, "payload must be a JSON object") + } +} + +func TestControlFieldsBelongToTheirKind(t *testing.T) { + wire, err := MarshalControl(Control{Kind: "InputBatch", Tuple: testTuple(), Sequence: 1}) + require.NoError(t, err) + var object map[string]any + require.NoError(t, json.Unmarshal(wire, &object)) + object["last_sequence"] = 1 + wire, err = json.Marshal(object) + require.NoError(t, err) + _, err = UnmarshalControl(wire) + require.ErrorIs(t, err, ErrProtocol) + require.ErrorContains(t, err, "not valid for control kind") + + _, err = MarshalControl(Control{Kind: "InputBatch", Tuple: testTuple(), Sequence: 1, Status: "ERROR"}) + require.ErrorIs(t, err, ErrProtocol) + require.ErrorContains(t, err, "not valid for control kind") + + _, err = UnmarshalControl([]byte(`{"version":1,"kind":"Unknown","tuple":{"account_id":1,"statement_id":"statement","group_id":"group","group_epoch":2,"invocation_id":"invocation","lease_epoch":3}}`)) + require.ErrorIs(t, err, ErrProtocol) + require.ErrorContains(t, err, "unsupported control kind") +} + +func TestClosingControlCarriesZeroLastSequence(t *testing.T) { + for _, kind := range []string{"EndInput", "Finish"} { + control := Control{Kind: kind, Tuple: testTuple()} + if kind == "Finish" { + control.Status = "OK" + control.FinishID = "finish" + control.LastResultSequence = 0 + } + wire, err := MarshalControl(control) + require.NoError(t, err) + var object map[string]any + require.NoError(t, json.Unmarshal(wire, &object)) + lastSequence, ok := object["last_sequence"] + require.True(t, ok, "%s must carry an explicit last_sequence", kind) + require.Equal(t, float64(0), lastSequence) + + decoded, err := UnmarshalControl(wire) + require.NoError(t, err) + require.Zero(t, decoded.LastSequence) + } + + wire, err := MarshalControl(Control{Kind: "InputBatch", Tuple: testTuple(), Sequence: 1}) + require.NoError(t, err) + var object map[string]any + require.NoError(t, json.Unmarshal(wire, &object)) + _, ok := object["last_sequence"] + require.False(t, ok, "non-closing controls should not grow a closing-only field") +} + +func TestInputConsumedCarriesReleaseCredit(t *testing.T) { + control := Control{ + Kind: "InputConsumed", + Tuple: testTuple(), + Sequence: 2, + ReleasedBytes: 128, + ReleasedBatches: 1, + } + wire, err := MarshalControl(control) + require.NoError(t, err) + decoded, err := UnmarshalControl(wire) + require.NoError(t, err) + require.Equal(t, int64(128), decoded.ReleasedBytes) + require.Equal(t, uint64(1), decoded.ReleasedBatches) + + var object map[string]any + require.NoError(t, json.Unmarshal(wire, &object)) + require.Equal(t, float64(128), object["released_bytes"]) + require.Equal(t, float64(1), object["released_batches"]) + delete(object, "released_batches") + invalid, err := json.Marshal(object) + require.NoError(t, err) + _, err = UnmarshalControl(invalid) + require.ErrorIs(t, err, ErrProtocol) +} + +func TestSystemAccountIsValidFencingIdentity(t *testing.T) { + tuple := testTuple() + tuple.AccountID = 0 + require.NoError(t, tuple.Validate()) + _, err := MarshalControl(Control{Kind: "OpenInvocation", Tuple: tuple, Payload: []byte(`{}`)}) + require.NoError(t, err) +} + +func TestFencingTupleRejectsInvalidUTF8(t *testing.T) { + tuple := testTuple() + tuple.StatementID = string([]byte{0xff}) + require.ErrorContains(t, tuple.Validate(), "invalid UTF-8") + _, err := MarshalControl(Control{Kind: "OpenInvocation", Tuple: tuple, Payload: []byte(`{}`)}) + require.ErrorContains(t, err, "invalid UTF-8") +} + +func TestFencingTupleRejectsUnboundedIdentityComponents(t *testing.T) { + tuple := testTuple() + tuple.GroupID = string(bytes.Repeat([]byte{'g'}, MaxFenceComponentBytes+1)) + require.ErrorContains(t, tuple.Validate(), "component is too large") + _, err := MarshalControl(Control{Kind: "OpenInvocation", Tuple: tuple, Payload: []byte(`{}`)}) + require.ErrorContains(t, err, "component is too large") +} + +func TestUnmarshalControlRejectsInvalidWireUTF8(t *testing.T) { + wire := []byte(`{"version":1,"kind":"InputBatch","tuple":{"account_id":1,"statement_id":"`) + wire = append(wire, 0xff) + wire = append(wire, []byte(`","group_id":"group","group_epoch":2,"invocation_id":"invocation","lease_epoch":3},"sequence":1}`)...) + _, err := UnmarshalControl(wire) + require.ErrorIs(t, err, ErrProtocol) + require.ErrorContains(t, err, "invalid UTF-8") +} + +func TestSequenceKeepsHalfCloseIndependentFromResults(t *testing.T) { + var sequence Sequence + require.NoError(t, sequence.AcceptInput(1)) + require.NoError(t, sequence.AcceptInput(2)) + require.NoError(t, sequence.EndInput(2)) + require.NoError(t, sequence.AcceptResult(1)) + require.False(t, sequence.ReadyToFinish()) + require.NoError(t, sequence.AcknowledgeResults(1)) + require.NoError(t, sequence.AcceptResult(2)) + require.NoError(t, sequence.AcknowledgeResults(2)) + require.True(t, sequence.ReadyToFinish()) + + require.ErrorIs(t, sequence.AcceptInput(3), ErrSequence) + require.ErrorIs(t, sequence.AcknowledgeResults(3), ErrSequence) + require.ErrorIs(t, sequence.AcknowledgeResults(0), ErrSequence) + require.NoError(t, sequence.EndInput(2)) +} + +func TestOutputSnapshotFreezesBeforeWorkerCanRewrite(t *testing.T) { + worker := []byte("trusted-before-barrier") + snapshot, err := FreezeOutput(worker, 1024) + require.NoError(t, err) + worker[0] = 'X' + + require.NoError(t, snapshot.Validate(len("trusted-before-barrier"), snapshot.Digest())) + worker[1] = 'Y' + require.Equal(t, "trusted-before-barrier", string(snapshot.Bytes())) + require.Equal(t, "trusted-before-barrier", string(snapshot.TrustedBytes())) + + empty, err := FreezeOutput(nil, 1024) + require.NoError(t, err) + require.NoError(t, empty.Validate(0, empty.Digest())) +} + +func TestOutputSnapshotDetectsTrustedBackingMutation(t *testing.T) { + snapshot, err := FreezeOutput([]byte("trusted"), 1024) + require.NoError(t, err) + snapshot.TrustedBytes()[0] = 'X' + require.ErrorContains(t, snapshot.Validate(snapshot.Len(), snapshot.Digest()), "backing changed") +} + +func TestExecutionGroupReleasesOnlyAfterCloseAndAllMembersTerminal(t *testing.T) { + var releases atomic.Int32 + group, err := NewExecutionGroup("g", 1, 2, func() error { + releases.Add(1) + return nil + }) + require.NoError(t, err) + a, err := group.BeginOpen("a") + require.NoError(t, err) + require.NoError(t, a.Commit()) + b, err := group.BeginOpen("b") + require.NoError(t, err) + require.NoError(t, b.Commit()) + + require.NoError(t, group.MemberTerminal("a")) + require.NoError(t, group.MemberTerminal("a")) + _, err = group.BeginOpen("a") + require.ErrorIs(t, err, ErrDuplicate) + require.NoError(t, group.Close(ReasonInputEOF)) + require.Equal(t, int32(0), releases.Load()) + require.NoError(t, group.MemberTerminal("b")) + require.Equal(t, int32(1), releases.Load()) + require.Equal(t, GroupReleased, group.State()) + + _, err = group.BeginOpen("late") + require.ErrorIs(t, err, ErrGroupClosed) + require.ErrorIs(t, group.Close(ReasonCancel), ErrProtocol) + require.NoError(t, group.Close(ReasonInputEOF)) + require.Equal(t, int32(1), releases.Load()) +} + +func TestExecutionGroupZeroMemberAndAbortedOpenRelease(t *testing.T) { + var releases atomic.Int32 + group, err := NewExecutionGroup("g", 1, 1, func() error { + releases.Add(1) + return nil + }) + require.NoError(t, err) + open, err := group.BeginOpen("will-abort") + require.NoError(t, err) + require.NoError(t, group.Close(ReasonPartialOpenError)) + require.Equal(t, int32(0), releases.Load()) + require.NoError(t, open.Abort()) + require.Equal(t, int32(1), releases.Load()) + + group, err = NewExecutionGroup("empty", 1, 1, func() error { + releases.Add(1) + return nil + }) + require.NoError(t, err) + require.NoError(t, group.Close(ReasonEmptyInput)) + require.Equal(t, int32(2), releases.Load()) + + group, err = NewExecutionGroup("late", 1, 1, func() error { + releases.Add(1) + return nil + }) + require.NoError(t, err) + open, err = group.BeginOpen("late-member") + require.NoError(t, err) + require.NoError(t, group.Close(ReasonCancel)) + require.ErrorIs(t, open.Commit(), ErrGroupClosed) + require.ErrorIs(t, open.Commit(), ErrProtocol) +} + +func TestExecutionGroupReservesPendingMemberIdentity(t *testing.T) { + group, err := NewExecutionGroup("g", 1, 2, func() error { return nil }) + require.NoError(t, err) + first, err := group.BeginOpen("member") + require.NoError(t, err) + _, err = group.BeginOpen("member") + require.ErrorIs(t, err, ErrDuplicate) + registered, active, inFlight := group.Counts() + require.Equal(t, 0, registered) + require.Equal(t, 0, active) + require.Equal(t, 1, inFlight) + require.NoError(t, first.Abort()) + _, _, inFlight = group.Counts() + require.Zero(t, inFlight) + + second, err := group.BeginOpen("member") + require.NoError(t, err) + require.NoError(t, second.Commit()) + registered, active, inFlight = group.Counts() + require.Equal(t, 1, registered) + require.Equal(t, 1, active) + require.Zero(t, inFlight) +} + +func TestExecutionGroupCloseReasonIsImmutable(t *testing.T) { + group, err := NewExecutionGroup("g", 1, 1, func() error { return nil }) + require.NoError(t, err) + require.NoError(t, group.Close(ReasonIdle)) + require.NoError(t, group.Close(ReasonIdle)) + require.ErrorIs(t, group.Close(ReasonCancel), ErrProtocol) + require.Equal(t, ReasonIdle, group.Reason()) +} + +func TestTerminalLedgerRetainsTombstonesUntilExpiry(t *testing.T) { + ledger, err := NewTerminalLedger(2, 200) + require.NoError(t, err) + now := time.Unix(100, 0) + credit, err := ledger.Reserve("g1", 1, 1, 100) + require.NoError(t, err) + require.NoError(t, credit.Add("i1", 100, now.Add(time.Hour))) + require.NoError(t, ledger.Complete("i1")) + credit.ReleaseUnused() + + second, err := ledger.Reserve("g2", 1, 1, 100) + require.NoError(t, err) + require.NoError(t, second.Add("i2", 100, now.Add(time.Hour))) + require.NoError(t, ledger.Complete("i2")) + second.ReleaseUnused() + _, err = ledger.Reserve("g3", 1, 1, 1) + require.ErrorIs(t, err, ErrLedgerFull) + + require.Equal(t, 2, func() int { n, _ := ledger.Counts(); return n }()) + require.Equal(t, 0, ledger.Expire(now.Add(time.Minute), func(string, uint64) bool { return true })) + require.Equal(t, 2, func() int { n, _ := ledger.Counts(); return n }()) + require.Equal(t, 0, ledger.Expire(now.Add(2*time.Hour), nil), "TTL must not advance the ownership epoch") + require.Equal(t, 2, ledger.Expire(now.Add(2*time.Hour), func(groupID string, groupEpoch uint64) bool { + return groupID == "g1" && groupEpoch == 1 || groupID == "g2" && groupEpoch == 1 + })) + third, err := ledger.Reserve("g3", 1, 1, 1) + require.NoError(t, err) + require.NoError(t, third.Add("i3", 1, now.Add(3*time.Hour))) + + require.ErrorIs(t, ledger.Complete("missing"), ErrUnknownIdentity) + require.NoError(t, ledger.Complete("i3")) + require.NoError(t, ledger.Complete("i3")) +} + +func TestTerminalLedgerDoesNotExpireActiveEntries(t *testing.T) { + ledger, err := NewTerminalLedger(1, 100) + require.NoError(t, err) + now := time.Unix(100, 0) + credit, err := ledger.Reserve("g", 1, 1, 100) + require.NoError(t, err) + require.NoError(t, credit.Add("active", 100, now.Add(time.Second))) + credit.ReleaseUnused() + require.Equal(t, 0, ledger.Expire(now.Add(time.Hour), func(string, uint64) bool { return true })) + entries, bytes := ledger.Counts() + require.Equal(t, 1, entries) + require.Equal(t, int64(100), bytes) + _, err = ledger.Reserve("other", 1, 1, 1) + require.ErrorIs(t, err, ErrLedgerFull) + require.NoError(t, ledger.Abandon("active")) + entries, bytes = ledger.Counts() + require.Zero(t, entries) + require.Zero(t, bytes) +} + +func TestExecutionGroupReleaseErrorCanBeRetried(t *testing.T) { + var attempts atomic.Int32 + group, err := NewExecutionGroup("g", 1, 1, func() error { + if attempts.Add(1) == 1 { + return errors.New("temporary release failure") + } + return nil + }) + require.NoError(t, err) + require.Error(t, group.Close(ReasonCancel)) + require.Equal(t, GroupDraining, group.State()) + // A second close is the scheduler's retry-safe release trigger. + require.NoError(t, group.Close(ReasonCancel)) + require.Equal(t, GroupReleased, group.State()) + require.Equal(t, int32(2), attempts.Load()) +} + +func TestExecutionGroupConcurrentReleaseWaitersObserveTheSameFailure(t *testing.T) { + releaseStarted := make(chan struct{}) + releaseContinue := make(chan struct{}) + var releaseStartOnce sync.Once + group, err := NewExecutionGroup("concurrent", 1, 1, func() error { + releaseStartOnce.Do(func() { close(releaseStarted) }) + <-releaseContinue + return errors.New("temporary concurrent release failure") + }) + require.NoError(t, err) + member, err := group.BeginOpen("member") + require.NoError(t, err) + require.NoError(t, member.Commit()) + require.NoError(t, group.Close(ReasonCancel)) + + firstDone := make(chan error, 1) + go func() { firstDone <- group.MemberTerminal("member") }() + <-releaseStarted + secondDone := make(chan error, 1) + go func() { secondDone <- group.Close(ReasonCancel) }() + close(releaseContinue) + require.ErrorContains(t, <-firstDone, "temporary concurrent release failure") + require.ErrorContains(t, <-secondDone, "temporary concurrent release failure") + require.Equal(t, GroupDraining, group.State()) +} + +func TestExecutionGroupCommitReportsReleaseFailure(t *testing.T) { + var attempts atomic.Int32 + group, err := NewExecutionGroup("g", 1, 1, func() error { + if attempts.Add(1) == 1 { + return errors.New("temporary release failure") + } + return nil + }) + require.NoError(t, err) + open, err := group.BeginOpen("member") + require.NoError(t, err) + require.NoError(t, group.Close(ReasonCancel)) + + err = open.Commit() + require.ErrorIs(t, err, ErrGroupClosed) + require.ErrorContains(t, err, "temporary release failure") + require.ErrorIs(t, open.Commit(), ErrProtocol) + require.ErrorIs(t, open.Abort(), ErrProtocol) + require.Equal(t, GroupDraining, group.State()) + require.NoError(t, group.Close(ReasonCancel)) + require.Equal(t, GroupReleased, group.State()) + require.Equal(t, int32(2), attempts.Load()) +} diff --git a/pkg/udf/python/arrow.go b/pkg/udf/python/arrow.go new file mode 100644 index 0000000000000..a129311757350 --- /dev/null +++ b/pkg/udf/python/arrow.go @@ -0,0 +1,1670 @@ +// Copyright 2026 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 python + +import ( + "bytes" + "context" + "crypto/sha256" + "encoding/binary" + "encoding/hex" + "encoding/json" + "fmt" + "io" + "math" + "reflect" + "unicode/utf8" + + "github.com/matrixorigin/matrixone/pkg/udf/udferr" + "github.com/matrixorigin/matrixone/pkg/util/errutil" + + "github.com/apache/arrow-go/v18/arrow" + "github.com/apache/arrow-go/v18/arrow/array" + "github.com/apache/arrow-go/v18/arrow/decimal128" + "github.com/apache/arrow-go/v18/arrow/flight" + "github.com/apache/arrow-go/v18/arrow/ipc" + "github.com/apache/arrow-go/v18/arrow/memory" + "github.com/matrixorigin/matrixone/pkg/common/mpool" + commonutil "github.com/matrixorigin/matrixone/pkg/common/util" + "github.com/matrixorigin/matrixone/pkg/container/arrowipc" + "github.com/matrixorigin/matrixone/pkg/container/bytejson" + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/container/vector" +) + +const ( + TypeMetadataKey = "mo.udf.type" + TypeFingerprintKey = "mo.udf.type_fingerprint" + DefaultMaxBatchBytes = 16 << 20 + DefaultMaxBatchRows = 65536 + DefaultMaxControlBytes = 1 << 20 + // Bulk append is only used for a large fixed-width primitive column. The + // small-batch path avoids allocating a temporary validity slice and keeps + // the ordinary per-value path for constants and special SQL encodings. + bulkInputMinRows = 64 +) + +type TypeDescriptor struct { + TypeID int32 `json:"type_id"` + Width int32 `json:"width,omitempty"` + Scale int32 `json:"scale,omitempty"` + Charset uint8 `json:"charset,omitempty"` + OffsetWidth int32 `json:"offset_width,omitempty"` + JSONEncoding string `json:"json_encoding,omitempty"` + TemporalEncoding string `json:"temporal_encoding,omitempty"` +} + +func NewTypeDescriptor(typ types.Type) (TypeDescriptor, error) { + // Planner types use scale=-1 as the sentinel for types whose SQL + // definition has no scale (for example INT and BINARY). That sentinel is + // an internal planner representation and cannot cross the Python ABI: + // descriptors are canonical and use zero for every non-applicable field. + // Likewise, display widths on numeric types are not part of their value + // contract. Normalize those fields here so SQL planner metadata and the + // persisted/Arrow descriptor have one stable representation. + width := typ.Width + scale := typ.Scale + switch typ.Oid { + case types.T_decimal64, types.T_decimal128: + if scale < 0 { + scale = 0 + } + case types.T_time, types.T_datetime, types.T_timestamp: + width = 0 + if scale < 0 { + scale = 0 + } + case types.T_char, types.T_varchar, types.T_binary, types.T_varbinary, + types.T_array_float32, types.T_array_float64: + scale = 0 + default: + width = 0 + scale = 0 + } + d := TypeDescriptor{TypeID: int32(typ.Oid), Width: width, Scale: scale, Charset: typ.Charset, OffsetWidth: 32} + switch typ.Oid { + case types.T_json: + d.JSONEncoding = "canonical_text" + case types.T_date, types.T_datetime, types.T_timestamp: + d.TemporalEncoding = "sql_zero_struct" + case types.T_bool, types.T_int8, types.T_int16, types.T_int32, types.T_int64, + types.T_uint8, types.T_uint16, types.T_uint32, types.T_uint64, + types.T_float32, types.T_float64, types.T_decimal64, types.T_decimal128, + types.T_char, types.T_varchar, types.T_text, types.T_uuid, types.T_time, + types.T_binary, types.T_varbinary, types.T_blob, + types.T_array_float32, types.T_array_float64: + default: + return TypeDescriptor{}, udferr.Newf("python udf does not support MatrixOne type %s", typ.String()) + } + if typ.Oid == types.T_array_float32 || typ.Oid == types.T_array_float64 { + if typ.Width <= 0 { + return TypeDescriptor{}, udferr.Newf("python udf requires a positive vector dimension for %s", typ.String()) + } + d.OffsetWidth = 0 + } + if typ.Oid == types.T_uuid { + d.OffsetWidth = 0 + } + return d, nil +} + +func (d TypeDescriptor) Type() types.Type { + return types.NewWithCharset(types.T(d.TypeID), d.Width, d.Scale, d.Charset) +} +func (d TypeDescriptor) canonical() ([]byte, error) { return json.Marshal(d) } +func (d TypeDescriptor) Fingerprint() (string, error) { + if err := d.Validate(); err != nil { + return "", err + } + canonical, err := d.canonical() + if err != nil { + return "", err + } + physical, err := d.arrowType() + if err != nil { + return "", err + } + physicalFingerprint := physical.Fingerprint() + if types.T(d.TypeID) == types.T_uuid { + // Arrow-Go's FixedSizeBinary fingerprint omits ByteWidth. Keep the + // UUID width in the cross-language fingerprint as part of the frozen + // physical contract instead of relying only on the local type check. + physicalFingerprint = "@P[16]" + } + h := sha256.New() + h.Write([]byte("matrixone-python-udf-type\x00")) + h.Write(canonical) + h.Write([]byte{0}) + h.Write([]byte(physicalFingerprint)) + return hex.EncodeToString(h.Sum(nil)), nil +} + +// Validate checks the semantic fields that Arrow's physical type does not +// carry. Keeping this at the descriptor boundary makes manually constructed +// catalog or wire descriptors obey the same contract as descriptors produced +// from a SQL type. +func (d TypeDescriptor) Validate() error { + oid := types.T(d.TypeID) + if d.Width < 0 { + return udferr.Newf("TYPE_CONTRACT: descriptor width must be non-negative") + } + if d.Scale < 0 { + return udferr.Newf("TYPE_CONTRACT: descriptor scale must be non-negative") + } + expectedOffsetWidth := int32(32) + if oid == types.T_uuid || oid == types.T_array_float32 || oid == types.T_array_float64 { + expectedOffsetWidth = 0 + } + if d.OffsetWidth != expectedOffsetWidth { + return udferr.Newf("TYPE_CONTRACT: descriptor offset_width must be %d for %s", expectedOffsetWidth, oid.String()) + } + if d.JSONEncoding != "" && (oid != types.T_json || d.JSONEncoding != "canonical_text") { + return udferr.Newf("TYPE_CONTRACT: unsupported JSON encoding") + } + if oid == types.T_json && d.JSONEncoding != "canonical_text" { + return udferr.Newf("TYPE_CONTRACT: JSON descriptor must use canonical_text encoding") + } + if d.TemporalEncoding != "" && (oid != types.T_date && oid != types.T_datetime && oid != types.T_timestamp || d.TemporalEncoding != "sql_zero_struct") { + return udferr.Newf("TYPE_CONTRACT: unsupported temporal encoding") + } + if (oid == types.T_date || oid == types.T_datetime || oid == types.T_timestamp) && d.TemporalEncoding != "sql_zero_struct" { + return udferr.Newf("TYPE_CONTRACT: temporal descriptor must use sql_zero_struct encoding") + } + + switch oid { + case types.T_bool, types.T_int8, types.T_int16, types.T_int32, types.T_int64, + types.T_uint8, types.T_uint16, types.T_uint32, types.T_uint64, + types.T_float32, types.T_float64, types.T_json: + if d.Width != 0 || d.Scale != 0 || d.Charset != types.CharsetLegacy { + return udferr.Newf("TYPE_CONTRACT: descriptor carries unused fields for %s", oid.String()) + } + case types.T_decimal64, types.T_decimal128: + maxPrecision := int32(38) + if oid == types.T_decimal64 { + maxPrecision = 18 + } + if d.Width < 1 || d.Width > maxPrecision { + return udferr.Newf("TYPE_CONTRACT: decimal precision %d is outside %s range", d.Width, oid.String()) + } + if d.Scale > d.Width { + return udferr.Newf("TYPE_CONTRACT: decimal scale %d exceeds precision %d", d.Scale, d.Width) + } + if d.Charset != types.CharsetLegacy { + return udferr.Newf("TYPE_CONTRACT: decimal descriptor carries a charset") + } + case types.T_date: + if d.Width != 0 || d.Scale != 0 || d.Charset != types.CharsetLegacy { + return udferr.Newf("TYPE_CONTRACT: DATE descriptor has unused or invalid fields") + } + case types.T_time, types.T_datetime, types.T_timestamp: + if d.Width != 0 || d.Scale > 6 || d.Charset != types.CharsetLegacy { + return udferr.Newf("TYPE_CONTRACT: temporal scale or charset is outside the supported range") + } + case types.T_char, types.T_varchar, types.T_text: + if d.Scale != 0 { + return udferr.Newf("TYPE_CONTRACT: text descriptor carries an unused scale") + } + switch d.Charset { + case types.CharsetLegacy, types.CharsetUTF8MB4Bin, types.CharsetUTF8: + default: + return udferr.Newf("TYPE_CONTRACT: unsupported text charset %d", d.Charset) + } + case types.T_binary, types.T_varbinary, types.T_blob: + if d.Scale != 0 || d.Charset != types.CharsetBinary { + return udferr.Newf("TYPE_CONTRACT: binary descriptor must use the binary charset") + } + case types.T_uuid: + if d.Width != 0 || d.Scale != 0 || d.Charset != types.CharsetLegacy { + return udferr.Newf("TYPE_CONTRACT: UUID descriptor carries unused fields") + } + case types.T_array_float32, types.T_array_float64: + if d.Width < 1 || d.Width > types.MaxArrayDimension || d.Scale != 0 || d.Charset != types.CharsetLegacy { + return udferr.Newf("TYPE_CONTRACT: vector dimension or metadata is outside the supported range") + } + default: + return udferr.Newf("TYPE_CONTRACT: unsupported MatrixOne type id %d", d.TypeID) + } + return nil +} + +func (d TypeDescriptor) arrowType() (arrow.DataType, error) { + switch types.T(d.TypeID) { + case types.T_bool: + return arrow.FixedWidthTypes.Boolean, nil + case types.T_int8: + return arrow.PrimitiveTypes.Int8, nil + case types.T_int16: + return arrow.PrimitiveTypes.Int16, nil + case types.T_int32: + return arrow.PrimitiveTypes.Int32, nil + case types.T_int64: + return arrow.PrimitiveTypes.Int64, nil + case types.T_uint8: + return arrow.PrimitiveTypes.Uint8, nil + case types.T_uint16: + return arrow.PrimitiveTypes.Uint16, nil + case types.T_uint32: + return arrow.PrimitiveTypes.Uint32, nil + case types.T_uint64: + return arrow.PrimitiveTypes.Uint64, nil + case types.T_float32: + return arrow.PrimitiveTypes.Float32, nil + case types.T_float64: + return arrow.PrimitiveTypes.Float64, nil + case types.T_decimal64, types.T_decimal128: + precision := d.Width + if precision == 0 { + precision = 18 + if types.T(d.TypeID) == types.T_decimal128 { + precision = 38 + } + } + if precision < 1 || precision > decimal128.MaxPrecision { + return nil, udferr.Newf("decimal precision %d is outside Arrow's supported range", precision) + } + return &arrow.Decimal128Type{Precision: precision, Scale: d.Scale}, nil + case types.T_char, types.T_varchar, types.T_text, types.T_json: + if d.OffsetWidth == 64 { + return arrow.BinaryTypes.LargeString, nil + } + return arrow.BinaryTypes.String, nil + case types.T_binary, types.T_varbinary, types.T_blob: + if d.OffsetWidth == 64 { + return arrow.BinaryTypes.LargeBinary, nil + } + return arrow.BinaryTypes.Binary, nil + case types.T_uuid: + return &arrow.FixedSizeBinaryType{ByteWidth: 16}, nil + case types.T_time: + return &arrow.DurationType{Unit: arrow.Microsecond}, nil + case types.T_array_float32: + if d.Width <= 0 { + return nil, udferr.Newf("invalid vecf32 dimension %d", d.Width) + } + return arrow.FixedSizeListOf(d.Width, arrow.PrimitiveTypes.Float32), nil + case types.T_array_float64: + if d.Width <= 0 { + return nil, udferr.Newf("invalid vecf64 dimension %d", d.Width) + } + return arrow.FixedSizeListOf(d.Width, arrow.PrimitiveTypes.Float64), nil + case types.T_date: + return sqlTemporalType(arrow.PrimitiveTypes.Date32), nil + case types.T_datetime: + return sqlTemporalType(&arrow.TimestampType{Unit: arrow.Microsecond}), nil + case types.T_timestamp: + return sqlTemporalType(&arrow.TimestampType{Unit: arrow.Microsecond, TimeZone: "UTC"}), nil + default: + return nil, udferr.Newf("unsupported MatrixOne type id %d", d.TypeID) + } +} +func sqlTemporalType(value arrow.DataType) *arrow.StructType { + return arrow.StructOf(arrow.Field{Name: "is_zero", Type: arrow.FixedWidthTypes.Boolean, Nullable: false}, arrow.Field{Name: "value", Type: value, Nullable: false}) +} +func (d TypeDescriptor) Field(name string) (arrow.Field, error) { + typ, err := d.arrowType() + if err != nil { + return arrow.Field{}, err + } + fingerprint, err := d.Fingerprint() + if err != nil { + return arrow.Field{}, err + } + descriptor, err := d.canonical() + if err != nil { + return arrow.Field{}, err + } + return arrow.Field{Name: name, Type: typ, Nullable: true, Metadata: arrow.NewMetadata([]string{TypeMetadataKey, TypeFingerprintKey}, []string{string(descriptor), fingerprint})}, nil +} +func (d TypeDescriptor) ValidateField(field arrow.Field) error { + want, err := d.Field(field.Name) + if err != nil { + return err + } + if field.Type == nil || !sameArrowType(field.Type, want.Type) || field.Nullable != want.Nullable { + return udferr.Newf("TYPE_CONTRACT: Arrow type %s does not match %s", field.Type, want.Type) + } + if !field.Metadata.Equal(want.Metadata) { + return udferr.Newf("TYPE_CONTRACT: Arrow logical metadata does not match the frozen descriptor") + } + return nil +} + +// sameArrowType intentionally compares the complete concrete Arrow type. +// Arrow-Go's Fingerprint is a physical layout fingerprint and, for some +// FixedSizeBinary versions, omits ByteWidth. A UUID contract must reject +// fixed_size_binary(1) even when that fingerprint collides with the expected +// fixed_size_binary(16). +func sameArrowType(left, right arrow.DataType) bool { + if left == nil || right == nil { + return left == right + } + return reflect.DeepEqual(left, right) +} + +type ArrowFrame struct { + Header []byte + Body []byte +} + +type encodedRecordBatch struct { + Frames []ArrowFrame + Rows int64 +} + +var errArrowBatchTooLarge = udferr.New("Arrow record batch exceeds the configured limit") + +func EncodeRecordBatch(record arrow.RecordBatch, maxBytes int64) ([]ArrowFrame, error) { + if record == nil || record.Schema() == nil || maxBytes <= 0 { + return nil, udferr.Newf("invalid Arrow record batch") + } + collector := &flightFrameCollector{maxBytes: maxBytes} + writer := flight.NewRecordWriter(collector, ipc.WithSchema(record.Schema()), ipc.WithAllocator(memory.NewGoAllocator())) + if err := writer.Write(record); err != nil { + return nil, errutil.Wrapf(err, "encode Arrow record batch") + } + if err := writer.Close(); err != nil { + return nil, errutil.Wrapf(err, "close Arrow record batch") + } + if len(collector.frames) < 2 { + return nil, udferr.Newf("Arrow stream did not contain schema and record batch") + } + return collector.frames, nil +} + +// flightFrameCollector preserves the exact Flight representation: DataHeader +// is the unframed IPC FlatBuffer and DataBody contains the body plus its IPC +// alignment padding. A stream-file frame cannot be copied directly into +// FlightData because its eight-byte continuation prefix is not part of +// FlightData.DataHeader. +type flightFrameCollector struct { + frames []ArrowFrame + maxBytes int64 + total int64 +} + +func (c *flightFrameCollector) reset(maxBytes, retainedBytes int64) { + // Do not reuse the frame slice backing array. A successful candidate can be + // retained by the size search while the next candidate is encoded. + c.frames = nil + c.maxBytes = maxBytes + c.total = retainedBytes +} + +func (c *flightFrameCollector) Send(data *flight.FlightData) error { + if data == nil || len(data.DataHeader) == 0 { + return udferr.Newf("invalid Arrow Flight frame") + } + if data.FlightDescriptor != nil || len(data.AppMetadata) != 0 { + return udferr.Newf("unexpected metadata on Arrow payload frame") + } + header := append([]byte(nil), data.DataHeader...) + body := append([]byte(nil), data.DataBody...) + c.total += int64(len(header) + len(body)) + if c.total > c.maxBytes { + return errutil.WrapfCauseFirst(errArrowBatchTooLarge, "stream is %d bytes, limit is %d", c.total, c.maxBytes) + } + c.frames = append(c.frames, ArrowFrame{Header: header, Body: body}) + return nil +} + +// inputBatchWireEncoder keeps one Arrow IPC writer alive for an invocation. +// The writer emits the schema once; later candidates and batches only encode a +// record message. The cached schema is still counted in every candidate's +// limit, because MaxBatchBytes describes the complete Flight payload that the +// receiver would have to admit for that batch. +type inputBatchWireEncoder struct { + schema *arrow.Schema + collector *flightFrameCollector + writer *flight.Writer + schemaFrame ArrowFrame + schemaBytes int64 + schemaReady bool + closed bool +} + +func (e *inputBatchWireEncoder) encode(record arrow.RecordBatch, maxBytes int64) ([]ArrowFrame, error) { + if e == nil || e.closed || record == nil || maxBytes <= 0 { + return nil, udferr.Newf("invalid Arrow record batch encoder") + } + if e.schema == nil || !record.Schema().Equal(e.schema) { + return nil, udferr.Newf("Arrow record batch schema does not match the invocation schema") + } + if e.writer == nil { + e.collector = &flightFrameCollector{} + e.writer = flight.NewRecordWriter( + e.collector, + ipc.WithSchema(e.schema), + ipc.WithAllocator(memory.NewGoAllocator()), + ) + } + writerHadSchema := e.schemaReady + e.collector.reset(maxBytes, e.schemaBytes) + if err := e.writer.Write(record); err != nil { + e.captureSchema() + return nil, errutil.Wrapf(err, "encode Arrow record batch") + } + e.captureSchema() + if writerHadSchema { + if len(e.collector.frames) != 1 { + return nil, udferr.Newf("Arrow writer did not emit one record frame") + } + return []ArrowFrame{e.schemaFrame, e.collector.frames[0]}, nil + } + if len(e.collector.frames) != 2 || !e.schemaReady { + return nil, udferr.Newf("Arrow stream did not contain schema and record batch") + } + return append([]ArrowFrame(nil), e.collector.frames...), nil +} + +func (e *inputBatchWireEncoder) captureSchema() { + if e == nil || e.schemaReady || e.collector == nil || len(e.collector.frames) == 0 { + return + } + frame := e.collector.frames[0] + e.schemaFrame = ArrowFrame{ + Header: append([]byte(nil), frame.Header...), + Body: append([]byte(nil), frame.Body...), + } + e.schemaBytes = int64(len(e.schemaFrame.Header) + len(e.schemaFrame.Body)) + e.schemaReady = true +} + +func (e *inputBatchWireEncoder) close() error { + if e == nil || e.closed { + return nil + } + if e.writer == nil { + e.closed = true + return nil + } + if err := e.writer.Close(); err != nil { + return errutil.Wrapf(err, "close Arrow record batch encoder") + } + // Commit the closed state only after the writer has released its resources. + // A failed close remains retryable for the owning invocation cleanup path. + e.closed = true + return nil +} + +func BuildInputRecord(inputs []*vector.Vector, args []types.Type, length int) (arrow.RecordBatch, *arrow.Schema, error) { + return BuildInputRecordRange(inputs, args, 0, length) +} + +func BuildInputRecordRange(inputs []*vector.Vector, args []types.Type, start, length int) (arrow.RecordBatch, *arrow.Schema, error) { + encoder, err := newInputBatchEncoder(inputs, args) + if err != nil { + return nil, nil, err + } + return encoder.build(start, length) +} + +// inputBatchEncoder owns the immutable descriptor/schema portion of the +// Gateway input boundary for one invocation. Building it once avoids +// re-creating TypeDescriptor, Field metadata, and the Arrow Schema for every +// physical batch and every size probe. The record builder and encoded bytes +// remain per batch, so the encoder does not retain input or output buffers. +type inputBatchEncoder struct { + inputs []*vector.Vector + args []types.Type + descriptors []TypeDescriptor + varlenaParameters []vector.FunctionParameterWrapper[types.Varlena] + schema *arrow.Schema + fixedWidth bool + wire *inputBatchWireEncoder +} + +func newInputBatchEncoder(inputs []*vector.Vector, args []types.Type) (*inputBatchEncoder, error) { + if len(inputs) != len(args) { + return nil, udferr.Newf("invalid Python UDF input shape") + } + fields := make([]arrow.Field, len(args)) + descriptors := make([]TypeDescriptor, len(args)) + varlenaParameters := make([]vector.FunctionParameterWrapper[types.Varlena], len(args)) + fixedWidth := true + for i, typ := range args { + descriptor, err := NewTypeDescriptor(typ) + if err != nil { + return nil, err + } + descriptors[i] = descriptor + fields[i], err = descriptor.Field(fmt.Sprintf("arg_%d", i)) + if err != nil { + return nil, err + } + if typ.IsVarlen() { + fixedWidth = false + } + if inputs[i] == nil { + return nil, udferr.Newf("input column %d is missing", i) + } + actualType := inputs[i].GetType() + if actualType == nil { + return nil, udferr.Newf("input column %d has no type", i) + } + if !actualType.Eq(typ) { + return nil, udferr.Newf("input column %d type %s does not match the frozen argument type %s", i, actualType.DescString(), typ.DescString()) + } + if inputs[i].Length() > 0 && isVarlenaInputType(typ.Oid) { + varlenaParameters[i] = vector.GenerateFunctionStrParameter(inputs[i]) + } + } + schema := arrow.NewSchema(fields, nil) + return &inputBatchEncoder{ + inputs: inputs, + args: args, + descriptors: descriptors, + varlenaParameters: varlenaParameters, + schema: schema, + fixedWidth: fixedWidth, + }, nil +} + +func (e *inputBatchEncoder) encode(record arrow.RecordBatch, maxBytes int64) ([]ArrowFrame, error) { + if e == nil { + return nil, udferr.Newf("invalid Python UDF input encoder") + } + if e.wire == nil { + e.wire = &inputBatchWireEncoder{schema: e.schema} + } + return e.wire.encode(record, maxBytes) +} + +func (e *inputBatchEncoder) close() error { + if e == nil || e.wire == nil { + return nil + } + return e.wire.close() +} + +func (e *inputBatchEncoder) build(start, length int) (arrow.RecordBatch, *arrow.Schema, error) { + if e == nil || start < 0 || length <= 0 { + return nil, nil, udferr.Newf("invalid Python UDF input shape") + } + for i, input := range e.inputs { + if input.Length() == 0 || (!input.IsConst() && input.Length() < start+length) { + return nil, nil, udferr.Newf("input column %d is shorter than batch range", i) + } + } + if len(e.args) == 0 { + return array.NewRecordBatch(e.schema, nil, int64(length)), e.schema, nil + } + builder := array.NewRecordBuilder(memory.NewGoAllocator(), e.schema) + defer builder.Release() + for column, typ := range e.args { + bulk, err := appendBulkFixedInputValue( + builder.Field(column), e.inputs[column], typ, start, length, + ) + if err != nil { + return nil, nil, errutil.Wrapf(err, "input column %d", column) + } + if bulk { + continue + } + for row := 0; row < length; row++ { + if err := appendInputValue( + builder.Field(column), e.inputs[column], typ, start, row, + e.varlenaParameters[column], + ); err != nil { + return nil, nil, errutil.Wrapf(err, "input column %d row %d", column, row) + } + } + } + return builder.NewRecordBatch(), e.schema, nil +} + +// appendBulkFixedInputValue uses Arrow's typed AppendValues APIs for the +// primitive SQL types whose MatrixOne storage already has the same physical +// representation. It copies only the values that Arrow must own; the source +// vector remains the ownership boundary, and NULL positions are supplied as a +// separate validity slice. The return value says whether the type was +// handled by this path. +func appendBulkFixedInputValue( + builder array.Builder, v *vector.Vector, typ types.Type, start, length int, +) (bool, error) { + if length < bulkInputMinRows { + return false, nil + } + validity := func() []bool { + if v.IsConstNull() { + return make([]bool, length) + } + if v.GetNulls() == nil || v.GetNulls().IsEmpty() { + return nil + } + valid := make([]bool, length) + for row := range valid { + valid[row] = !v.IsNull(uint64(sourceRow(v, start, row))) + } + return valid + } + if builder == nil || v == nil { + return false, udferr.Newf("input column is missing") + } + + switch typ.Oid { + case types.T_bool: + values, err := bulkFixedInputWindow[bool](v, start, length) + if err != nil { + return false, err + } + builder.(*array.BooleanBuilder).AppendValues(values, validity()) + case types.T_int8: + values, err := bulkFixedInputWindow[int8](v, start, length) + if err != nil { + return false, err + } + builder.(*array.Int8Builder).AppendValues(values, validity()) + case types.T_int16: + values, err := bulkFixedInputWindow[int16](v, start, length) + if err != nil { + return false, err + } + builder.(*array.Int16Builder).AppendValues(values, validity()) + case types.T_int32: + values, err := bulkFixedInputWindow[int32](v, start, length) + if err != nil { + return false, err + } + builder.(*array.Int32Builder).AppendValues(values, validity()) + case types.T_int64: + values, err := bulkFixedInputWindow[int64](v, start, length) + if err != nil { + return false, err + } + builder.(*array.Int64Builder).AppendValues(values, validity()) + case types.T_uint8: + values, err := bulkFixedInputWindow[uint8](v, start, length) + if err != nil { + return false, err + } + builder.(*array.Uint8Builder).AppendValues(values, validity()) + case types.T_uint16: + values, err := bulkFixedInputWindow[uint16](v, start, length) + if err != nil { + return false, err + } + builder.(*array.Uint16Builder).AppendValues(values, validity()) + case types.T_uint32: + values, err := bulkFixedInputWindow[uint32](v, start, length) + if err != nil { + return false, err + } + builder.(*array.Uint32Builder).AppendValues(values, validity()) + case types.T_uint64: + values, err := bulkFixedInputWindow[uint64](v, start, length) + if err != nil { + return false, err + } + builder.(*array.Uint64Builder).AppendValues(values, validity()) + case types.T_float32: + values, err := bulkFixedInputWindow[float32](v, start, length) + if err != nil { + return false, err + } + builder.(*array.Float32Builder).AppendValues(values, validity()) + case types.T_float64: + values, err := bulkFixedInputWindow[float64](v, start, length) + if err != nil { + return false, err + } + builder.(*array.Float64Builder).AppendValues(values, validity()) + default: + return false, nil + } + return true, nil +} + +func bulkFixedInputWindow[T any](v *vector.Vector, start, length int) ([]T, error) { + if v.IsConstNull() { + // A constant NULL intentionally has no physical value slot. Arrow + // still needs one placeholder per logical row so its validity bitmap + // preserves the batch shape. + return make([]T, length), nil + } + values := vector.MustFixedColNoTypeCheck[T](v) + if v.IsConst() { + if len(values) == 0 { + return nil, udferr.Newf("constant input column has no value") + } + expanded := make([]T, length) + for row := range expanded { + expanded[row] = values[0] + } + return expanded, nil + } + if start < 0 || length <= 0 || start > len(values) || length > len(values)-start { + return nil, udferr.Newf("input column is shorter than batch range") + } + return values[start : start+length], nil +} + +// canBuildFullBatch cheaply decides whether a variable-width full candidate +// is worth materializing. It uses the source values already owned by the +// SQL vector and a deliberately inflated bound. If the bound is not clearly +// below the wire limit, the bounded probe path is retained so a very wide +// input cannot create an oversized temporary Arrow record just to discover +// that it does not fit. +func (e *inputBatchEncoder) canBuildFullBatch(start, length, maxBytes int64) bool { + if e == nil || e.fixedWidth || length <= 0 || maxBytes <= 0 { + return false + } + const safetyNumerator = int64(2) + const safetyDenominator = int64(1) + const perColumnOverhead = int64(4096) + const perRowOverhead = int64(16) + const maxEstimate = int64(^uint64(0) >> 1) + add := func(total, value int64) int64 { + if value < 0 || total > maxEstimate-value { + return maxEstimate + } + return total + value + } + multiply := func(left, right int64) int64 { + if left < 0 || right < 0 || (left != 0 && right > maxEstimate/left) { + return maxEstimate + } + return left * right + } + estimate := int64(128) + for column, typ := range e.args { + if !typ.IsVarlen() { + return false + } + if elementWidth, ok := arrayElementByteWidth(typ.Oid); ok { + // Vector arguments use a fixed-size-list physical type. They are + // varlen in MatrixOne's storage, but do not have a Varlena wrapper + // or Arrow string/binary offsets to inspect. Account for every + // child value and the parent validity bitmap instead of treating + // the vector as a byte string. + valueBytes := multiply(int64(typ.Width), elementWidth) + estimate = add(estimate, multiply(valueBytes, length)) + estimate = add(estimate, add(length, 7)/8) + estimate = add(estimate, multiply(length, perRowOverhead)) + continue + } + if !isVarlenaInputType(typ.Oid) { + // An unsupported variable-width physical type must use the + // ordinary bounded probe path. In particular, never call a nil + // Varlena wrapper while estimating a batch. + return false + } + descriptor := e.descriptors[column] + offsetWidth := int64(descriptor.OffsetWidth) + if offsetWidth == 0 { + offsetWidth = 32 + } + offsetWidth /= 8 + if offsetWidth != 4 && offsetWidth != 8 { + return false + } + estimate = add(estimate, perColumnOverhead) + estimate = add(estimate, multiply(add(length, 1), offsetWidth)) + estimate = add(estimate, add(length, 7)/8) + parameter := e.varlenaParameters[column] + for row := int64(0); row < length; row++ { + index := sourceRow(e.inputs[column], int(start), int(row)) + if e.inputs[column].IsNull(uint64(index)) { + continue + } + value, _ := parameter.GetStrValue(uint64(index)) + valueBytes := int64(len(value)) + // JSON canonicalization can add escaping and separators. The + // factor is intentionally conservative; a bound that is not + // clearly safe falls back to the ordinary bounded probes. + if typ.Oid == types.T_json { + valueBytes = add(valueBytes, valueBytes) + } + estimate = add(estimate, valueBytes) + estimate = add(estimate, perRowOverhead) + } + } + if estimate > maxEstimate/safetyNumerator { + return false + } + return estimate*safetyNumerator <= maxBytes*safetyDenominator +} + +func arrayElementByteWidth(oid types.T) (int64, bool) { + switch oid { + case types.T_array_float32: + return 4, true + case types.T_array_float64: + return 8, true + default: + return 0, false + } +} + +func sourceRow(v *vector.Vector, start, row int) int { + if v.IsConst() { + return 0 + } + return start + row +} + +func isVarlenaInputType(oid types.T) bool { + switch oid { + case types.T_char, types.T_varchar, types.T_text, types.T_json, + types.T_binary, types.T_varbinary, types.T_blob: + return true + default: + return false + } +} + +func appendInputValue( + builder array.Builder, + v *vector.Vector, + typ types.Type, + start, row int, + varlenaParameter vector.FunctionParameterWrapper[types.Varlena], +) error { + index := sourceRow(v, start, row) + null := v.IsNull(uint64(index)) + if !null && isVarlenaInputType(typ.Oid) && varlenaParameter == nil { + return udferr.Newf("missing cached varlena input parameter") + } + if typ.Oid == types.T_date || typ.Oid == types.T_datetime || typ.Oid == types.T_timestamp { + return appendTemporalInput(builder.(*array.StructBuilder), v, typ, index, null) + } + if typ.Oid == types.T_time { + b := builder.(*array.DurationBuilder) + if null { + b.AppendNull() + } else { + b.Append(arrow.Duration(vector.GetFixedAtNoTypeCheck[types.Time](v, index))) + } + return nil + } + switch typ.Oid { + case types.T_bool: + b := builder.(*array.BooleanBuilder) + if null { + b.AppendNull() + } else { + b.Append(vector.GetFixedAtNoTypeCheck[bool](v, index)) + } + case types.T_int8: + b := builder.(*array.Int8Builder) + if null { + b.AppendNull() + } else { + b.Append(vector.GetFixedAtNoTypeCheck[int8](v, index)) + } + case types.T_int16: + b := builder.(*array.Int16Builder) + if null { + b.AppendNull() + } else { + b.Append(vector.GetFixedAtNoTypeCheck[int16](v, index)) + } + case types.T_int32: + b := builder.(*array.Int32Builder) + if null { + b.AppendNull() + } else { + b.Append(vector.GetFixedAtNoTypeCheck[int32](v, index)) + } + case types.T_int64: + b := builder.(*array.Int64Builder) + if null { + b.AppendNull() + } else { + b.Append(vector.GetFixedAtNoTypeCheck[int64](v, index)) + } + case types.T_uint8: + b := builder.(*array.Uint8Builder) + if null { + b.AppendNull() + } else { + b.Append(vector.GetFixedAtNoTypeCheck[uint8](v, index)) + } + case types.T_uint16: + b := builder.(*array.Uint16Builder) + if null { + b.AppendNull() + } else { + b.Append(vector.GetFixedAtNoTypeCheck[uint16](v, index)) + } + case types.T_uint32: + b := builder.(*array.Uint32Builder) + if null { + b.AppendNull() + } else { + b.Append(vector.GetFixedAtNoTypeCheck[uint32](v, index)) + } + case types.T_uint64: + b := builder.(*array.Uint64Builder) + if null { + b.AppendNull() + } else { + b.Append(vector.GetFixedAtNoTypeCheck[uint64](v, index)) + } + case types.T_float32: + b := builder.(*array.Float32Builder) + if null { + b.AppendNull() + } else { + b.Append(vector.GetFixedAtNoTypeCheck[float32](v, index)) + } + case types.T_float64: + b := builder.(*array.Float64Builder) + if null { + b.AppendNull() + } else { + b.Append(vector.GetFixedAtNoTypeCheck[float64](v, index)) + } + case types.T_decimal64: + b := builder.(*array.Decimal128Builder) + if null { + b.AppendNull() + } else { + b.Append(decimal64ToArrow(vector.GetFixedAtNoTypeCheck[types.Decimal64](v, index))) + } + case types.T_decimal128: + b := builder.(*array.Decimal128Builder) + if null { + b.AppendNull() + } else { + value := vector.GetFixedAtNoTypeCheck[types.Decimal128](v, index) + b.Append(decimal128.New(int64(value.B64_127), value.B0_63)) + } + case types.T_char, types.T_varchar, types.T_text, types.T_json: + b := builder.(*array.StringBuilder) + if null { + b.AppendNull() + } else { + value, _ := varlenaParameter.GetStrValue(uint64(index)) + if typ.Oid == types.T_json { + canonical, err := canonicalJSONInput(value) + if err != nil { + return err + } + value = canonical + } + b.Append(string(value)) + } + case types.T_binary, types.T_varbinary, types.T_blob: + b := builder.(*array.BinaryBuilder) + if null { + b.AppendNull() + } else { + value, _ := varlenaParameter.GetStrValue(uint64(index)) + b.Append(value) + } + case types.T_uuid: + b := builder.(*array.FixedSizeBinaryBuilder) + if null { + b.AppendNull() + } else { + value := vector.GetFixedAtNoTypeCheck[types.Uuid](v, index) + b.Append(value[:]) + } + case types.T_array_float32: + b := builder.(*array.FixedSizeListBuilder) + if null { + b.AppendNull() + } else { + b.Append(true) + b.ValueBuilder().(*array.Float32Builder).AppendValues(vector.GetArrayAt[float32](v, index), nil) + } + case types.T_array_float64: + b := builder.(*array.FixedSizeListBuilder) + if null { + b.AppendNull() + } else { + b.Append(true) + b.ValueBuilder().(*array.Float64Builder).AppendValues(vector.GetArrayAt[float64](v, index), nil) + } + default: + return udferr.Newf("unsupported input type %s", typ.String()) + } + return nil +} + +// canonicalJSONInput converts MatrixOne's binary JSON rendering into the +// compact UTF-8 text required by the Python ABI. ByteJson.String is intended +// for SQL display and includes object/array whitespace; passing it directly +// would make a valid object fail the worker's canonical-text check even +// though scalar JSON values happen to work. +func canonicalJSONInput(value []byte) ([]byte, error) { + text := []byte(types.DecodeJson(value).String()) + canonical, err := canonicalJSONTextBytes(text) + if err != nil { + return nil, errutil.Wrapf(err, "TYPE_CONTRACT: invalid JSON input") + } + return canonical, nil +} + +func canonicalJSONText(value string) (string, error) { + canonical, err := canonicalJSONTextBytes([]byte(value)) + if err != nil { + return "", err + } + return string(canonical), nil +} + +func canonicalJSONTextBytes(value []byte) ([]byte, error) { + var compact bytes.Buffer + if err := json.Compact(&compact, value); err != nil { + return nil, err + } + return compact.Bytes(), nil +} + +func appendTemporalInput(builder *array.StructBuilder, v *vector.Vector, typ types.Type, index int, null bool) error { + zero := false + var raw int64 + switch typ.Oid { + case types.T_date: + if !null { + value := vector.GetFixedAtNoTypeCheck[types.Date](v, index) + zero = value == types.ZeroDate + if !zero { + raw = int64(value.DaysSinceUnixEpoch()) + } + } + builder.Append(!null) + builder.FieldBuilder(0).(*array.BooleanBuilder).Append(zero) + builder.FieldBuilder(1).(*array.Date32Builder).Append(arrow.Date32(raw)) + case types.T_datetime: + if !null { + value := vector.GetFixedAtNoTypeCheck[types.Datetime](v, index) + zero = value == types.ZeroDatetime + if !zero { + raw = int64(value) - types.GetUnixEpochSecs() + } + } + builder.Append(!null) + builder.FieldBuilder(0).(*array.BooleanBuilder).Append(zero) + builder.FieldBuilder(1).(*array.TimestampBuilder).Append(arrow.Timestamp(raw)) + case types.T_timestamp: + if !null { + value := vector.GetFixedAtNoTypeCheck[types.Timestamp](v, index) + zero = value == types.ZeroTimestamp + if !zero { + raw = int64(value) - types.GetUnixEpochSecs() + } + } + builder.Append(!null) + builder.FieldBuilder(0).(*array.BooleanBuilder).Append(zero) + builder.FieldBuilder(1).(*array.TimestampBuilder).Append(arrow.Timestamp(raw)) + default: + return udferr.Newf("unsupported temporal type %s", typ.String()) + } + return nil +} +func decimal64ToArrow(value types.Decimal64) decimal128.Num { + if value.Sign() { + return decimal128.New(-1, uint64(value)) + } + return decimal128.New(0, uint64(value)) +} + +func DecodeRecordBatch(schemaFrame, batchFrame ArrowFrame, maxBytes int64) (arrow.RecordBatch, error) { + if len(schemaFrame.Header) == 0 || len(batchFrame.Header) == 0 || maxBytes <= 0 { + return nil, udferr.Newf("invalid Arrow output frames") + } + if len(schemaFrame.Body) != 0 { + return nil, udferr.Newf("invalid Arrow schema frame body") + } + schemaInfo, err := arrowipc.InspectMessage(context.Background(), schemaFrame.Header, arrowipc.ValidationOptions{MaxMetadataBytes: arrowipc.DefaultMaxMetadataBytes, MaxBodyBytes: 0, BodyEnvelopeBytes: 0, MaxDecodedRecordBytes: 1}) + if err != nil { + return nil, err + } + if schemaInfo.HeaderType != arrowipc.MessageHeaderSchema { + return nil, udferr.Newf("invalid Arrow schema frame header %d", schemaInfo.HeaderType) + } + batchInfo, err := arrowipc.InspectMessage(context.Background(), batchFrame.Header, arrowipc.ValidationOptions{MaxMetadataBytes: arrowipc.DefaultMaxMetadataBytes, MaxBodyBytes: maxBytes, BodyEnvelopeBytes: int64(len(batchFrame.Body)), Body: batchFrame.Body, ValidateBody: true, MaxDecodedRecordBytes: maxBytes}) + if err != nil { + return nil, err + } + if batchInfo.HeaderType != arrowipc.MessageHeaderRecordBatch { + return nil, udferr.Newf("invalid Arrow record frame header %d", batchInfo.HeaderType) + } + // The snapshot is already the immutable validation/publication backing. + // Feed that backing directly to Arrow's stream reader instead of assembling + // another stream-sized byte slice around it. The small IPC continuation + // prefixes and alignment padding are separate readers; the body remains + // owned by the validated snapshot until Arrow releases the record. + stream := newIPCStreamReader(schemaFrame, batchFrame) + reader, err := ipc.NewReader(stream, ipc.WithAllocator(memory.NewGoAllocator())) + if err != nil { + return nil, errutil.Wrapf(err, "decode Arrow output") + } + defer reader.Release() + if !reader.Next() { + return nil, udferr.Newf("decode Arrow output: %v", reader.Err()) + } + record := reader.RecordBatch() + if record == nil { + return nil, udferr.Newf("decode Arrow output: missing record batch") + } + record.Retain() + return record, nil +} + +const ( + inlineIPCFrameCount = 2 + inlineIPCPartCount = inlineIPCFrameCount*5 + 1 +) + +var ipcZeroPadding [8]byte + +func newIPCStreamReader(frames ...ArrowFrame) io.Reader { + reader := &ipcStreamReader{} + if len(frames) <= inlineIPCFrameCount { + reader.parts = reader.inlineParts[:0] + for index, frame := range frames { + metadataLength := (len(frame.Header) + 7) &^ 7 + bodyLength := (len(frame.Body) + 7) &^ 7 + binary.LittleEndian.PutUint32(reader.prefixes[index][:4], math.MaxUint32) + binary.LittleEndian.PutUint32(reader.prefixes[index][4:], uint32(metadataLength)) + reader.parts = append(reader.parts, + reader.prefixes[index][:], + frame.Header, + ipcZeroPadding[:metadataLength-len(frame.Header)], + frame.Body, + ipcZeroPadding[:bodyLength-len(frame.Body)], + ) + } + // Arrow's stream reader uses an eight-byte zero continuation marker to + // observe the end of the stream after the one record batch. + reader.parts = append(reader.parts, ipcZeroPadding[:]) + return reader + } + + // Keep the helper correct for future callers that need more than the + // schema-plus-record pair. The production result path stays on the inline + // storage above, so this fallback does not add a per-batch allocation to + // the current protocol. + parts := make([][]byte, 0, len(frames)*5+1) + for _, frame := range frames { + metadataLength := (len(frame.Header) + 7) &^ 7 + bodyLength := (len(frame.Body) + 7) &^ 7 + var prefix [8]byte + binary.LittleEndian.PutUint32(prefix[:4], math.MaxUint32) + binary.LittleEndian.PutUint32(prefix[4:], uint32(metadataLength)) + parts = append(parts, + prefix[:], + frame.Header, + ipcZeroPadding[:metadataLength-len(frame.Header)], + frame.Body, + ipcZeroPadding[:bodyLength-len(frame.Body)], + ) + } + parts = append(parts, ipcZeroPadding[:]) + return &ipcStreamReader{parts: parts} +} + +type ipcStreamReader struct { + parts [][]byte + inlineParts [inlineIPCPartCount][]byte + prefixes [inlineIPCFrameCount][8]byte + part int + offset int +} + +func (r *ipcStreamReader) Read(dst []byte) (int, error) { + if len(dst) == 0 { + return 0, nil + } + read := 0 + for read < len(dst) && r.part < len(r.parts) { + source := r.parts[r.part] + if r.offset >= len(source) { + r.part++ + r.offset = 0 + continue + } + copied := copy(dst[read:], source[r.offset:]) + r.offset += copied + read += copied + } + if read != 0 { + return read, nil + } + return 0, io.EOF +} + +func AppendArrowResult(descriptor TypeDescriptor, input arrow.Array, result vector.FunctionResultWrapper, mp *mpool.MPool) error { + if input == nil { + return udferr.Newf("TYPE_CONTRACT: missing Arrow result") + } + if result == nil { + return udferr.Newf("python udf: missing result wrapper") + } + // AppendArrowResult is also the public adapter boundary used by runtimes + // other than the Flight Gateway. Do not let an invalid manually-built + // descriptor become executable merely because its Arrow physical type can + // be constructed (for example DECIMAL64 precision 19). + if err := descriptor.Validate(); err != nil { + return err + } + if err := validateArrayType(descriptor, input); err != nil { + return err + } + if err := validateArrowValueDomain(descriptor, input); err != nil { + return err + } + if input.Len() == 0 { + return nil + } + if mp == nil { + return udferr.Newf("python udf: missing memory pool for Arrow result") + } + result.GetResultVector().SetTypeScale(descriptor.Scale) + typ := types.T(descriptor.TypeID) + switch typ { + case types.T_bool: + return appendBoolArrowResult(input.(*array.Boolean), result) + case types.T_int8: + return appendFixedArrowValues(input.(*array.Int8).Int8Values(), input, result) + case types.T_int16: + return appendFixedArrowValues(input.(*array.Int16).Int16Values(), input, result) + case types.T_int32: + return appendFixedArrowValues(input.(*array.Int32).Int32Values(), input, result) + case types.T_int64: + return appendFixedArrowValues(input.(*array.Int64).Int64Values(), input, result) + case types.T_uint8: + return appendFixedArrowValues(input.(*array.Uint8).Uint8Values(), input, result) + case types.T_uint16: + return appendFixedArrowValues(input.(*array.Uint16).Uint16Values(), input, result) + case types.T_uint32: + return appendFixedArrowValues(input.(*array.Uint32).Uint32Values(), input, result) + case types.T_uint64: + return appendFixedArrowValues(input.(*array.Uint64).Uint64Values(), input, result) + case types.T_float32: + return appendFixedArrowValues(input.(*array.Float32).Float32Values(), input, result) + case types.T_float64: + return appendFixedArrowValues(input.(*array.Float64).Float64Values(), input, result) + case types.T_char, types.T_varchar, types.T_text: + return appendStringArrowResult(input.(*array.String), result) + case types.T_json: + return appendJSONArrowResult(input.(*array.String), result) + case types.T_binary, types.T_varbinary, types.T_blob: + return appendBinaryArrowResult(input.(*array.Binary), result) + } + for i := 0; i < input.Len(); i++ { + null := input.IsNull(i) + switch typ { + case types.T_decimal64: + var value types.Decimal64 + if !null { + converted, err := decimalFromArray(input.(*array.Decimal128).Value(i), true) + if err != nil { + return err + } + value = converted.(types.Decimal64) + } + if err := vector.MustFunctionResult[types.Decimal64](result).Append(value, null); err != nil { + return err + } + case types.T_decimal128: + var value types.Decimal128 + if !null { + converted, err := decimalFromArray(input.(*array.Decimal128).Value(i), false) + if err != nil { + return err + } + value = converted.(types.Decimal128) + } + if err := vector.MustFunctionResult[types.Decimal128](result).Append(value, null); err != nil { + return err + } + case types.T_uuid: + var value types.Uuid + if !null { + copy(value[:], input.(*array.FixedSizeBinary).Value(i)) + } + if err := vector.MustFunctionResult[types.Uuid](result).Append(value, null); err != nil { + return err + } + case types.T_time: + if err := vector.MustFunctionResult[types.Time](result).Append(types.Time(input.(*array.Duration).Value(i)), null); err != nil { + return err + } + case types.T_array_float32: + if err := appendFloat32ArrayResult(input.(*array.FixedSizeList), i, null, result, mp); err != nil { + return err + } + case types.T_array_float64: + if err := appendFloat64ArrayResult(input.(*array.FixedSizeList), i, null, result, mp); err != nil { + return err + } + case types.T_date, types.T_datetime, types.T_timestamp: + if err := appendTemporalResult(input.(*array.Struct), typ, i, result); err != nil { + return err + } + default: + return udferr.Newf("unsupported output type %s", typ.String()) + } + } + return nil +} + +func appendStringArrowResult(input *array.String, result vector.FunctionResultWrapper) error { + output := vector.MustFunctionResult[types.Varlena](result) + for i := 0; i < input.Len(); i++ { + // AppendBytes copies synchronously into the MO-owned area. The unsafe + // view therefore never escapes the call and does not retain Arrow's + // backing buffer after the decoded record is released. + if err := output.AppendBytes( + commonutil.UnsafeStringToBytes(input.Value(i)), input.IsNull(i), + ); err != nil { + return err + } + } + return nil +} + +func appendJSONArrowResult(input *array.String, result vector.FunctionResultWrapper) error { + output := vector.MustFunctionResult[types.Varlena](result) + for i := 0; i < input.Len(); i++ { + if input.IsNull(i) { + if err := output.AppendBytes(nil, true); err != nil { + return err + } + continue + } + encoded, err := bytejson.ParseJsonByteFromString(input.Value(i)) + if err != nil { + return errutil.Wrapf(err, "TYPE_CONTRACT: invalid JSON result") + } + if err = output.AppendBytes(encoded, false); err != nil { + return err + } + } + return nil +} + +func appendBinaryArrowResult(input *array.Binary, result vector.FunctionResultWrapper) error { + output := vector.MustFunctionResult[types.Varlena](result) + for i := 0; i < input.Len(); i++ { + if err := output.AppendBytes(input.Value(i), input.IsNull(i)); err != nil { + return err + } + } + return nil +} + +type nullableArrowArray interface { + NullN() int + IsNull(int) bool +} + +func appendBoolArrowResult(input *array.Boolean, result vector.FunctionResultWrapper) error { + output := vector.MustFunctionResult[bool](result) + if input.NullN() == 0 { + for i := 0; i < input.Len(); i++ { + output.AppendMustValue(input.Value(i)) + } + return nil + } + for i := 0; i < input.Len(); i++ { + if input.IsNull(i) { + output.AppendMustNull() + } else { + output.AppendMustValue(input.Value(i)) + } + } + return nil +} + +func appendFixedArrowValues[T types.FixedSizeT](values []T, input nullableArrowArray, result vector.FunctionResultWrapper) error { + output := vector.MustFunctionResult[T](result) + if input.NullN() == 0 { + for _, value := range values { + output.AppendMustValue(value) + } + return nil + } + for i, value := range values { + if input.IsNull(i) { + output.AppendMustNull() + } else { + output.AppendMustValue(value) + } + } + return nil +} + +func appendFloat32ArrayResult(input *array.FixedSizeList, row int, null bool, result vector.FunctionResultWrapper, mp *mpool.MPool) error { + if null { + return vector.AppendArray[float32](result.GetResultVector(), nil, true, mp) + } + start, end := input.ValueOffsets(row) + values := input.ListValues().(*array.Float32) + items := make([]float32, end-start) + for i := start; i < end; i++ { + if values.IsNull(int(i)) { + return udferr.Newf("TYPE_CONTRACT: vector child at row %d is null", row) + } + items[i-start] = values.Value(int(i)) + } + return vector.AppendArray(result.GetResultVector(), items, false, mp) +} + +func appendFloat64ArrayResult(input *array.FixedSizeList, row int, null bool, result vector.FunctionResultWrapper, mp *mpool.MPool) error { + if null { + return vector.AppendArray[float64](result.GetResultVector(), nil, true, mp) + } + start, end := input.ValueOffsets(row) + values := input.ListValues().(*array.Float64) + items := make([]float64, end-start) + for i := start; i < end; i++ { + if values.IsNull(int(i)) { + return udferr.Newf("TYPE_CONTRACT: vector child at row %d is null", row) + } + items[i-start] = values.Value(int(i)) + } + return vector.AppendArray(result.GetResultVector(), items, false, mp) +} +func validateArrayType(descriptor TypeDescriptor, input arrow.Array) error { + want, err := descriptor.arrowType() + if err != nil { + return err + } + if !sameArrowType(input.DataType(), want) { + return udferr.Newf("TYPE_CONTRACT: output Arrow type %s does not match %s", input.DataType(), want) + } + return nil +} + +func validateArrowValueDomain(descriptor TypeDescriptor, input arrow.Array) error { + if input == nil { + return udferr.Newf("TYPE_CONTRACT: missing Arrow result") + } + for row := 0; row < input.Len(); row++ { + if input.IsNull(row) { + continue + } + switch types.T(descriptor.TypeID) { + case types.T_char, types.T_varchar, types.T_text: + if descriptor.Width > 0 && int32(utf8.RuneCountInString(input.(*array.String).Value(row))) > descriptor.Width { + return udferr.Newf("TYPE_CONTRACT: string row %d exceeds width %d", row, descriptor.Width) + } + case types.T_json: + value := input.(*array.String).Value(row) + canonical, err := canonicalJSONText(value) + if err != nil { + return errutil.Wrapf(err, "TYPE_CONTRACT: JSON row %d is not valid canonical text", row) + } + if canonical != value { + return udferr.Newf("TYPE_CONTRACT: JSON row %d is not canonical text", row) + } + case types.T_binary, types.T_varbinary, types.T_blob: + if descriptor.Width > 0 && int32(len(input.(*array.Binary).Value(row))) > descriptor.Width { + return udferr.Newf("TYPE_CONTRACT: binary row %d exceeds width %d", row, descriptor.Width) + } + case types.T_time: + value := types.Time(input.(*array.Duration).Value(row)) + if !types.IsMySQLTime(value) || !hasExactMicrosecondScale(int64(value), descriptor.Scale) { + return udferr.Newf("TYPE_CONTRACT: TIME row %d is outside the declared SQL domain", row) + } + case types.T_decimal64, types.T_decimal128: + precision := descriptor.Width + if precision == 0 { + precision = 18 + if types.T(descriptor.TypeID) == types.T_decimal128 { + precision = 38 + } + } + if !input.(*array.Decimal128).Value(row).FitsInPrecision(precision) { + return udferr.Newf("TYPE_CONTRACT: decimal row %d exceeds precision %d", row, precision) + } + case types.T_array_float32: + list := input.(*array.FixedSizeList) + values := list.ListValues().(*array.Float32) + start, end := list.ValueOffsets(row) + for child := start; child < end; child++ { + if values.IsNull(int(child)) { + return udferr.Newf("TYPE_CONTRACT: vector child at row %d is null", row) + } + } + case types.T_array_float64: + list := input.(*array.FixedSizeList) + values := list.ListValues().(*array.Float64) + start, end := list.ValueOffsets(row) + for child := start; child < end; child++ { + if values.IsNull(int(child)) { + return udferr.Newf("TYPE_CONTRACT: vector child at row %d is null", row) + } + } + case types.T_date, types.T_datetime, types.T_timestamp: + structValue := input.(*array.Struct) + zeroField, valueField := structValue.Field(0), structValue.Field(1) + if zeroField.IsNull(row) || valueField.IsNull(row) { + return udferr.Newf("TYPE_CONTRACT: temporal row %d has a null child", row) + } + zero := zeroField.(*array.Boolean).Value(row) + switch types.T(descriptor.TypeID) { + case types.T_date: + value := valueField.(*array.Date32).Value(row) + if zero && value != 0 { + return udferr.Newf("TYPE_CONTRACT: DATE zero row %d has a non-zero placeholder", row) + } + if !zero { + date := types.DaysFromUnixEpochToDate(int32(value)) + year, month, day, _ := date.Calendar(true) + if !types.ValidDate(year, month, day) { + return udferr.Newf("TYPE_CONTRACT: DATE row %d is outside the SQL domain", row) + } + } + case types.T_datetime: + value := valueField.(*array.Timestamp).Value(row) + if zero && value != 0 { + return udferr.Newf("TYPE_CONTRACT: DATETIME zero row %d has a non-zero placeholder", row) + } + if !zero { + absolute, ok := addUnixEpoch(int64(value)) + if !ok || !hasExactMicrosecondScale(absolute, descriptor.Scale) { + return udferr.Newf("TYPE_CONTRACT: DATETIME row %d is outside the declared SQL domain", row) + } + datetime := types.Datetime(absolute) + year, month, day, _ := datetime.ToDate().Calendar(true) + if !types.ValidDatetime(year, month, day) { + return udferr.Newf("TYPE_CONTRACT: DATETIME row %d is outside the SQL domain", row) + } + } + case types.T_timestamp: + value := valueField.(*array.Timestamp).Value(row) + if zero && value != 0 { + return udferr.Newf("TYPE_CONTRACT: TIMESTAMP zero row %d has a non-zero placeholder", row) + } + if !zero { + absolute, ok := addUnixEpoch(int64(value)) + if !ok || absolute < int64(types.TimestampMinValue) || absolute > int64(types.TimestampMaxValue) || !hasExactMicrosecondScale(absolute, descriptor.Scale) { + return udferr.Newf("TYPE_CONTRACT: TIMESTAMP row %d is outside the declared SQL domain", row) + } + } + } + } + } + return nil +} + +func addUnixEpoch(value int64) (int64, bool) { + epoch := types.GetUnixEpochSecs() + if value > math.MaxInt64-epoch || value < math.MinInt64+epoch { + return 0, false + } + return value + epoch, true +} + +func hasExactMicrosecondScale(value int64, scale int32) bool { + if scale < 0 || scale > 6 { + return false + } + quantum := int64(1) + for i := scale; i < 6; i++ { + quantum *= 10 + } + return value%quantum == 0 +} +func decimalFromArray(value decimal128.Num, narrow bool) (any, error) { + high, low := uint64(value.HighBits()), value.LowBits() + if narrow && !decimal128FitsDecimal64(high, low) { + return nil, udferr.Newf("TYPE_CONTRACT: Decimal128 result does not fit Decimal64") + } + if narrow { + return types.Decimal64(low), nil + } + return types.Decimal128{B0_63: low, B64_127: high}, nil +} + +func decimal128FitsDecimal64(high, low uint64) bool { + // A signed 128-bit value fits in signed 64 bits only when the high word is + // a proper sign extension of the low word. Checking the high word alone + // would turn +2^63 into the negative Decimal64 minimum. + return (high == 0 && low <= math.MaxInt64) || + (high == math.MaxUint64 && low >= uint64(1)<<63) +} + +func appendTemporalResult(input *array.Struct, typ types.T, index int, result vector.FunctionResultWrapper) error { + if input.IsNull(index) { + return appendTemporalNull(typ, result) + } + zero := input.Field(0).(*array.Boolean).Value(index) + if typ == types.T_date { + value := types.ZeroDate + if !zero { + value = types.DaysFromUnixEpochToDate(int32(input.Field(1).(*array.Date32).Value(index))) + } + return vector.MustFunctionResult[types.Date](result).Append(value, false) + } + if typ == types.T_datetime { + value := types.ZeroDatetime + if !zero { + value = types.Datetime(input.Field(1).(*array.Timestamp).Value(index)) + types.Datetime(types.GetUnixEpochSecs()) + } + return vector.MustFunctionResult[types.Datetime](result).Append(value, false) + } + value := types.ZeroTimestamp + if !zero { + value = types.Timestamp(input.Field(1).(*array.Timestamp).Value(index)) + types.Timestamp(types.GetUnixEpochSecs()) + } + return vector.MustFunctionResult[types.Timestamp](result).Append(value, false) +} +func appendTemporalNull(typ types.T, result vector.FunctionResultWrapper) error { + switch typ { + case types.T_date: + return vector.MustFunctionResult[types.Date](result).Append(0, true) + case types.T_datetime: + return vector.MustFunctionResult[types.Datetime](result).Append(0, true) + default: + return vector.MustFunctionResult[types.Timestamp](result).Append(0, true) + } +} diff --git a/pkg/udf/python/arrow_test.go b/pkg/udf/python/arrow_test.go new file mode 100644 index 0000000000000..515206c9564fe --- /dev/null +++ b/pkg/udf/python/arrow_test.go @@ -0,0 +1,1079 @@ +// Copyright 2026 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 python + +import ( + "bytes" + "encoding/binary" + "encoding/json" + "fmt" + "math" + "os" + "testing" + + "github.com/apache/arrow-go/v18/arrow" + "github.com/apache/arrow-go/v18/arrow/array" + "github.com/apache/arrow-go/v18/arrow/decimal128" + "github.com/apache/arrow-go/v18/arrow/ipc" + "github.com/apache/arrow-go/v18/arrow/memory" + "github.com/matrixorigin/matrixone/pkg/common/mpool" + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/container/vector" + "github.com/stretchr/testify/require" +) + +func TestArrowFieldMetadataIsExact(t *testing.T) { + descriptor, err := NewTypeDescriptor(types.T_varchar.ToType()) + require.NoError(t, err) + field, err := descriptor.Field("result") + require.NoError(t, err) + require.Equal(t, []string{TypeMetadataKey, TypeFingerprintKey}, field.Metadata.Keys()) + require.NoError(t, descriptor.ValidateField(field)) + + withExtra := field + withExtra.Metadata = arrow.MetadataFrom(map[string]string{ + TypeMetadataKey: field.Metadata.ToMap()[TypeMetadataKey], + TypeFingerprintKey: field.Metadata.ToMap()[TypeFingerprintKey], + "untrusted": "must be rejected", + }) + require.Error(t, descriptor.ValidateField(withExtra)) +} + +func TestEncodeRecordBatchUsesFlightPayloadFrames(t *testing.T) { + descriptor, err := NewTypeDescriptor(types.T_int64.ToType()) + require.NoError(t, err) + field, err := descriptor.Field("arg_0") + require.NoError(t, err) + builder := array.NewInt64Builder(memory.NewGoAllocator()) + builder.AppendValues([]int64{1, 2, 3}, nil) + values := builder.NewInt64Array() + defer values.Release() + record := array.NewRecordBatch(arrow.NewSchema([]arrow.Field{field}, nil), []arrow.Array{values}, 3) + defer record.Release() + + frames, err := EncodeRecordBatch(record, DefaultMaxBatchBytes) + require.NoError(t, err) + require.Len(t, frames, 2) + // FlightData.DataHeader is the raw IPC FlatBuffer, without the stream + // continuation prefix. DecodeRecordBatch adds that prefix back only for + // the local bounded decoder. + require.NotEqual(t, []byte{0xff, 0xff, 0xff, 0xff}, frames[0].Header[:4]) + decoded, err := DecodeRecordBatch(frames[0], frames[1], DefaultMaxBatchBytes) + require.NoError(t, err) + defer decoded.Release() + require.Equal(t, int64(3), decoded.NumRows()) + decodedValues := decoded.Column(0).(*array.Int64) + require.Equal(t, int64(1), decodedValues.Value(0)) + require.Equal(t, int64(2), decodedValues.Value(1)) + require.Equal(t, int64(3), decodedValues.Value(2)) +} + +func BenchmarkDecodeRecordBatch(b *testing.B) { + descriptor, err := NewTypeDescriptor(types.T_int64.ToType()) + require.NoError(b, err) + field, err := descriptor.Field("arg_0") + require.NoError(b, err) + builder := array.NewInt64Builder(memory.NewGoAllocator()) + values := make([]int64, 8192) + for i := range values { + values[i] = int64(i) + } + builder.AppendValues(values, nil) + arrayValues := builder.NewInt64Array() + defer arrayValues.Release() + record := array.NewRecordBatch( + arrow.NewSchema([]arrow.Field{field}, nil), + []arrow.Array{arrayValues}, + int64(len(values)), + ) + defer record.Release() + frames, err := EncodeRecordBatch(record, DefaultMaxBatchBytes) + require.NoError(b, err) + b.SetBytes(int64(len(frames[1].Body))) + + b.Run("copy_baseline", func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + decoded, err := decodeRecordBatchCopyBaseline(frames[0], frames[1], DefaultMaxBatchBytes) + if err != nil { + b.Fatal(err) + } + decoded.Release() + } + }) + b.Run("snapshot_reader", func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + decoded, err := DecodeRecordBatch(frames[0], frames[1], DefaultMaxBatchBytes) + if err != nil { + b.Fatal(err) + } + decoded.Release() + } + }) +} + +func BenchmarkAppendArrowResultFixedWidth(b *testing.B) { + builder := array.NewInt64Builder(memory.NewGoAllocator()) + values := make([]int64, 8192) + for i := range values { + values[i] = int64(i) + } + builder.AppendValues(values, nil) + input := builder.NewInt64Array() + defer input.Release() + mp := mpool.MustNewZeroNoFixed() + defer mpool.DeleteMPool(mp) + b.SetBytes(int64(len(values) * 8)) + + bench := func(b *testing.B, appendResult func(vector.FunctionResultWrapper) error) { + result := vector.NewFunctionResultWrapper(types.T_int64.ToType(), mp) + defer result.Free() + require.NoError(b, result.PreExtendAndReset(len(values))) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + if err := result.PreExtendAndReset(len(values)); err != nil { + b.Fatal(err) + } + if err := appendResult(result); err != nil { + b.Fatal(err) + } + } + } + + b.Run("wrapper_each_row", func(b *testing.B) { + bench(b, func(result vector.FunctionResultWrapper) error { + for i := 0; i < input.Len(); i++ { + if err := vector.MustFunctionResult[int64](result).Append(input.Value(i), input.IsNull(i)); err != nil { + return err + } + } + return nil + }) + }) + b.Run("wrapper_once", func(b *testing.B) { + bench(b, func(result vector.FunctionResultWrapper) error { + return appendFixedArrowValues(input.Int64Values(), input, result) + }) + }) +} + +func BenchmarkAppendArrowResultVariableWidth(b *testing.B) { + builder := array.NewStringBuilder(memory.NewGoAllocator()) + values := make([]string, 8192) + for i := range values { + values[i] = fmt.Sprintf("value-%d", i) + } + builder.AppendValues(values, nil) + input := builder.NewStringArray() + defer input.Release() + mp := mpool.MustNewZeroNoFixed() + defer mpool.DeleteMPool(mp) + b.SetBytes(int64(len(values) * 8)) + + bench := func(b *testing.B, appendResult func(vector.FunctionResultWrapper) error) { + result := vector.NewFunctionResultWrapper(types.T_varchar.ToType(), mp) + defer result.Free() + require.NoError(b, result.PreExtendAndReset(len(values))) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + if err := result.PreExtendAndReset(len(values)); err != nil { + b.Fatal(err) + } + if err := appendResult(result); err != nil { + b.Fatal(err) + } + } + } + + b.Run("string_to_bytes_copy", func(b *testing.B) { + bench(b, func(result vector.FunctionResultWrapper) error { + output := vector.MustFunctionResult[types.Varlena](result) + for i := 0; i < input.Len(); i++ { + if err := output.AppendBytes([]byte(input.Value(i)), input.IsNull(i)); err != nil { + return err + } + } + return nil + }) + }) + b.Run("borrowed_string_view", func(b *testing.B) { + bench(b, func(result vector.FunctionResultWrapper) error { + return appendStringArrowResult(input, result) + }) + }) +} + +func decodeRecordBatchCopyBaseline(schemaFrame, batchFrame ArrowFrame, maxBytes int64) (arrow.RecordBatch, error) { + stream := make([]byte, 0, len(schemaFrame.Header)+len(batchFrame.Header)+len(batchFrame.Body)+32) + stream = appendIPCFrameCopyBaseline(stream, schemaFrame.Header, schemaFrame.Body) + stream = appendIPCFrameCopyBaseline(stream, batchFrame.Header, batchFrame.Body) + stream = append(stream, 0, 0, 0, 0, 0, 0, 0, 0) + reader, err := ipc.NewReader(bytes.NewReader(stream), ipc.WithAllocator(memory.NewGoAllocator())) + if err != nil { + return nil, err + } + defer reader.Release() + if !reader.Next() { + return nil, reader.Err() + } + record := reader.RecordBatch() + if record == nil { + return nil, fmt.Errorf("missing record batch") + } + record.Retain() + return record, nil +} + +func appendIPCFrameCopyBaseline(dst, header, body []byte) []byte { + metadataLength := (len(header) + 7) &^ 7 + var prefix [8]byte + binary.LittleEndian.PutUint32(prefix[:4], math.MaxUint32) + binary.LittleEndian.PutUint32(prefix[4:], uint32(metadataLength)) + dst = append(dst, prefix[:]...) + dst = append(dst, header...) + for len(dst)%8 != 0 { + dst = append(dst, 0) + } + dst = append(dst, body...) + for len(dst)%8 != 0 { + dst = append(dst, 0) + } + return dst +} + +func TestDecodeRecordBatchRequiresSchemaAndRecordHeaders(t *testing.T) { + descriptor, err := NewTypeDescriptor(types.T_int64.ToType()) + require.NoError(t, err) + field, err := descriptor.Field("arg_0") + require.NoError(t, err) + builder := array.NewInt64Builder(memory.NewGoAllocator()) + builder.Append(1) + values := builder.NewInt64Array() + defer values.Release() + record := array.NewRecordBatch(arrow.NewSchema([]arrow.Field{field}, nil), []arrow.Array{values}, 1) + defer record.Release() + frames, err := EncodeRecordBatch(record, DefaultMaxBatchBytes) + require.NoError(t, err) + + _, err = DecodeRecordBatch(ArrowFrame{Header: frames[1].Header}, frames[1], DefaultMaxBatchBytes) + require.Error(t, err) + _, err = DecodeRecordBatch(frames[0], frames[0], DefaultMaxBatchBytes) + require.ErrorContains(t, err, "record frame header") + _, err = DecodeRecordBatch(ArrowFrame{Header: frames[0].Header, Body: []byte{1}}, frames[1], DefaultMaxBatchBytes) + require.ErrorContains(t, err, "schema frame body") +} + +func TestAppendArrowResultRejectsMissingConsumer(t *testing.T) { + builder := array.NewInt64Builder(memory.NewGoAllocator()) + builder.Append(1) + values := builder.NewInt64Array() + defer values.Release() + descriptor, err := NewTypeDescriptor(types.T_int64.ToType()) + require.NoError(t, err) + require.ErrorContains(t, AppendArrowResult(descriptor, values, nil, nil), "missing result wrapper") +} + +func TestAppendArrowResultValidatesEmptyArrayType(t *testing.T) { + allocator := memory.NewGoAllocator() + stringBuilder := array.NewStringBuilder(allocator) + values := stringBuilder.NewStringArray() + defer values.Release() + + mp := mpool.MustNewZeroNoFixed() + result := vector.NewFunctionResultWrapper(types.T_int64.ToType(), mp) + defer func() { + result.Free() + mpool.DeleteMPool(mp) + }() + descriptor, err := NewTypeDescriptor(types.T_int64.ToType()) + require.NoError(t, err) + + require.ErrorContains(t, AppendArrowResult(descriptor, values, result, mp), "Arrow type") +} + +func TestAppendArrowResultRejectsInvalidSemanticDescriptor(t *testing.T) { + mp := mpool.MustNewZeroNoFixed() + defer mpool.DeleteMPool(mp) + result := vector.NewFunctionResultWrapper(types.T_decimal64.ToType(), mp) + defer result.Free() + + decimalType := &arrow.Decimal128Type{Precision: 19, Scale: 0} + builder := array.NewDecimal128Builder(memory.NewGoAllocator(), decimalType) + builder.Append(decimal128.FromI64(1)) + values := builder.NewDecimal128Array() + defer values.Release() + + descriptor := TypeDescriptor{TypeID: int32(types.T_decimal64), Width: 19, OffsetWidth: 32} + require.ErrorContains(t, AppendArrowResult(descriptor, values, result, mp), "decimal precision") +} + +func TestZeroArgumentRecordPreservesRows(t *testing.T) { + record := array.NewRecordBatch(arrow.NewSchema(nil, nil), nil, 3) + defer record.Release() + frames, err := EncodeRecordBatch(record, DefaultMaxBatchBytes) + require.NoError(t, err) + require.Len(t, frames, 2) + decoded, err := DecodeRecordBatch(frames[0], frames[1], DefaultMaxBatchBytes) + require.NoError(t, err) + defer decoded.Release() + require.Equal(t, int64(3), decoded.NumRows()) + require.Equal(t, int64(0), decoded.NumCols()) +} + +func TestBuildInputRecordRejectsEmptyConstantVector(t *testing.T) { + mp := mpool.MustNewZeroNoFixed() + defer mpool.DeleteMPool(mp) + + input := vector.NewConstNull(types.T_int64.ToType(), 0, mp) + defer input.Free(mp) + + _, _, err := BuildInputRecordRange( + []*vector.Vector{input}, + []types.Type{types.T_int64.ToType()}, + 0, + 1, + ) + require.ErrorContains(t, err, "shorter than batch range") + + textInput, err := vector.NewConstBytes(types.T_varchar.ToType(), nil, 0, mp) + require.NoError(t, err) + defer textInput.Free(mp) + var record arrow.RecordBatch + require.NotPanics(t, func() { + record, _, err = BuildInputRecordRange( + []*vector.Vector{textInput}, + []types.Type{types.T_varchar.ToType()}, + 0, + 1, + ) + }) + if record != nil { + record.Release() + } + require.ErrorContains(t, err, "shorter than batch range") +} + +func TestInputBatchEncoderRejectsMismatchedVectorType(t *testing.T) { + mp := mpool.MustNewZeroNoFixed() + input := vector.NewVec(types.T_int32.ToType()) + defer func() { + input.Free(mp) + mpool.DeleteMPool(mp) + }() + + _, err := newInputBatchEncoder( + []*vector.Vector{input}, []types.Type{types.T_int64.ToType()}, + ) + require.ErrorContains(t, err, "does not match the frozen argument type") +} + +func TestInputBatchEncoderReusesSchemaAndPreservesRange(t *testing.T) { + mp := mpool.MustNewZeroNoFixed() + input := vector.NewVec(types.T_int64.ToType()) + defer func() { + input.Free(mp) + mpool.DeleteMPool(mp) + }() + for _, value := range []int64{10, 20, 30} { + require.NoError(t, vector.AppendFixed(input, value, false, mp)) + } + encoder, err := newInputBatchEncoder( + []*vector.Vector{input}, []types.Type{types.T_int64.ToType()}, + ) + require.NoError(t, err) + first, firstSchema, err := encoder.build(0, 2) + require.NoError(t, err) + defer first.Release() + second, secondSchema, err := encoder.build(2, 1) + require.NoError(t, err) + defer second.Release() + require.Same(t, firstSchema, secondSchema) + firstValues := first.Column(0).(*array.Int64) + secondValues := second.Column(0).(*array.Int64) + require.Equal(t, int64(10), firstValues.Value(0)) + require.Equal(t, int64(20), firstValues.Value(1)) + require.Equal(t, int64(30), secondValues.Value(0)) +} + +func TestInputBatchEncoderCachesVariableWidthParameterAcrossRanges(t *testing.T) { + mp := mpool.MustNewZeroNoFixed() + defer mpool.DeleteMPool(mp) + + input := vector.NewVec(types.T_varchar.ToType()) + defer input.Free(mp) + for index, value := range []string{"zero", "one", "two", "three"} { + require.NoError(t, vector.AppendBytes(input, []byte(value), index == 2, mp)) + } + encoder, err := newInputBatchEncoder( + []*vector.Vector{input}, []types.Type{types.T_varchar.ToType()}, + ) + require.NoError(t, err) + + first, _, err := encoder.build(0, 2) + require.NoError(t, err) + defer first.Release() + second, _, err := encoder.build(2, 2) + require.NoError(t, err) + defer second.Release() + + firstValues := first.Column(0).(*array.String) + require.Equal(t, "zero", firstValues.Value(0)) + require.Equal(t, "one", firstValues.Value(1)) + secondValues := second.Column(0).(*array.String) + require.True(t, secondValues.IsNull(0)) + require.Equal(t, "three", secondValues.Value(1)) +} + +func TestInputBatchEncoderBulkPrimitivePreservesRangeNullsAndConstants(t *testing.T) { + mp := mpool.MustNewZeroNoFixed() + defer mpool.DeleteMPool(mp) + + input := vector.NewVec(types.T_int64.ToType()) + defer input.Free(mp) + for row := 0; row < 128; row++ { + require.NoError(t, vector.AppendFixed(input, int64(row+100), row%19 == 0, mp)) + } + encoder, err := newInputBatchEncoder( + []*vector.Vector{input}, []types.Type{types.T_int64.ToType()}, + ) + require.NoError(t, err) + record, _, err := encoder.build(7, 100) + require.NoError(t, err) + defer record.Release() + values := record.Column(0).(*array.Int64) + for row := 0; row < 100; row++ { + sourceRow := row + 7 + require.Equal(t, sourceRow%19 == 0, values.IsNull(row), "row %d", row) + if !values.IsNull(row) { + require.Equal(t, int64(sourceRow+100), values.Value(row), "row %d", row) + } + } + + constant, err := vector.NewConstFixed(types.T_int64.ToType(), int64(42), 128, mp) + require.NoError(t, err) + defer constant.Free(mp) + constantEncoder, err := newInputBatchEncoder( + []*vector.Vector{constant}, []types.Type{types.T_int64.ToType()}, + ) + require.NoError(t, err) + constantRecord, _, err := constantEncoder.build(32, 96) + require.NoError(t, err) + defer constantRecord.Release() + constantValues := constantRecord.Column(0).(*array.Int64) + require.Equal(t, 96, int(constantRecord.NumRows())) + for row := 0; row < 96; row++ { + require.False(t, constantValues.IsNull(row)) + require.Equal(t, int64(42), constantValues.Value(row)) + } + + nullConstant := vector.NewConstNull(types.T_int64.ToType(), 128, mp) + defer nullConstant.Free(mp) + nullConstantEncoder, err := newInputBatchEncoder( + []*vector.Vector{nullConstant}, []types.Type{types.T_int64.ToType()}, + ) + require.NoError(t, err) + nullConstantRecord, _, err := nullConstantEncoder.build(0, 96) + require.NoError(t, err) + defer nullConstantRecord.Release() + nullConstantValues := nullConstantRecord.Column(0).(*array.Int64) + for row := 0; row < 96; row++ { + require.True(t, nullConstantValues.IsNull(row)) + } +} + +func TestInputBatchEncoderVectorSizeProbeDoesNotUseVarlenaWrapper(t *testing.T) { + mp := mpool.MustNewZeroNoFixed() + defer mpool.DeleteMPool(mp) + + for _, tc := range []struct { + name string + typ types.Type + }{ + {name: "vecf32", typ: types.New(types.T_array_float32, 3, 0)}, + {name: "vecf64", typ: types.New(types.T_array_float64, 3, 0)}, + } { + t.Run(tc.name, func(t *testing.T) { + input := vector.NewVec(tc.typ) + defer input.Free(mp) + for row := 0; row < 64; row++ { + var err error + switch tc.typ.Oid { + case types.T_array_float32: + err = vector.AppendArray(input, []float32{float32(row), 1, 2}, row%11 == 0, mp) + case types.T_array_float64: + err = vector.AppendArray(input, []float64{float64(row), 1, 2}, row%11 == 0, mp) + } + require.NoError(t, err) + } + + encoder, err := newInputBatchEncoder([]*vector.Vector{input}, []types.Type{tc.typ}) + require.NoError(t, err) + defer func() { require.NoError(t, encoder.close()) }() + + var batch encodedRecordBatch + require.NotPanics(t, func() { + batch, err = encodeInputBatchWithEncoder( + encoder, 0, 64, DefaultMaxBatchBytes, 64, + ) + }) + require.NoError(t, err) + require.Equal(t, int64(64), batch.Rows) + require.Len(t, batch.Frames, 2) + }) + } +} + +func TestInputBatchWireEncoderReusesSchemaAcrossBatches(t *testing.T) { + descriptor, err := NewTypeDescriptor(types.T_int64.ToType()) + require.NoError(t, err) + field, err := descriptor.Field("arg_0") + require.NoError(t, err) + schema := arrow.NewSchema([]arrow.Field{field}, nil) + makeRecord := func(value int64) arrow.RecordBatch { + builder := array.NewInt64Builder(memory.NewGoAllocator()) + builder.Append(value) + values := builder.NewInt64Array() + record := array.NewRecordBatch(schema, []arrow.Array{values}, 1) + values.Release() + return record + } + + encoder := &inputBatchWireEncoder{schema: schema} + first := makeRecord(1) + second := makeRecord(2) + defer first.Release() + defer second.Release() + defer func() { require.NoError(t, encoder.close()) }() + + firstFrames, err := encoder.encode(first, DefaultMaxBatchBytes) + require.NoError(t, err) + secondFrames, err := encoder.encode(second, DefaultMaxBatchBytes) + require.NoError(t, err) + require.Len(t, firstFrames, 2) + require.Len(t, secondFrames, 2) + require.Equal(t, firstFrames[0].Header, secondFrames[0].Header) + require.Equal(t, firstFrames[0].Body, secondFrames[0].Body) + require.NotEqual(t, firstFrames[1].Body, secondFrames[1].Body) +} + +func TestInputBatchWireEncoderRecoversAfterOversizeCandidate(t *testing.T) { + descriptor, err := NewTypeDescriptor(types.T_int64.ToType()) + require.NoError(t, err) + field, err := descriptor.Field("arg_0") + require.NoError(t, err) + schema := arrow.NewSchema([]arrow.Field{field}, nil) + makeRecord := func(values ...int64) arrow.RecordBatch { + builder := array.NewInt64Builder(memory.NewGoAllocator()) + builder.AppendValues(values, nil) + arrayValues := builder.NewInt64Array() + record := array.NewRecordBatch(schema, []arrow.Array{arrayValues}, int64(len(values))) + arrayValues.Release() + return record + } + + one := makeRecord(1) + defer one.Release() + measure := &inputBatchWireEncoder{schema: schema} + oneFrames, err := measure.encode(one, DefaultMaxBatchBytes) + require.NoError(t, err) + maxBytes := int64(len(oneFrames[0].Header) + len(oneFrames[0].Body) + len(oneFrames[1].Header) + len(oneFrames[1].Body)) + require.NoError(t, measure.close()) + + encoder := &inputBatchWireEncoder{schema: schema} + defer func() { require.NoError(t, encoder.close()) }() + wider := makeRecord(1, 2) + defer wider.Release() + _, err = encoder.encode(wider, maxBytes) + require.ErrorIs(t, err, errArrowBatchTooLarge) + frames, err := encoder.encode(one, maxBytes) + require.NoError(t, err) + require.Len(t, frames, 2) +} + +func TestInputBatchWireEncoderCloseIsIdempotent(t *testing.T) { + descriptor, err := NewTypeDescriptor(types.T_int64.ToType()) + require.NoError(t, err) + field, err := descriptor.Field("arg_0") + require.NoError(t, err) + schema := arrow.NewSchema([]arrow.Field{field}, nil) + builder := array.NewInt64Builder(memory.NewGoAllocator()) + builder.AppendValues([]int64{1}, nil) + values := builder.NewInt64Array() + record := array.NewRecordBatch(schema, []arrow.Array{values}, 1) + values.Release() + defer record.Release() + + encoder := &inputBatchWireEncoder{schema: schema} + _, err = encoder.encode(record, DefaultMaxBatchBytes) + require.NoError(t, err) + require.NoError(t, encoder.close()) + require.NoError(t, encoder.close()) + _, err = encoder.encode(record, DefaultMaxBatchBytes) + require.ErrorContains(t, err, "invalid Arrow record batch encoder") +} + +func TestArrowValueDomainRejectsWidthAndTimeOverflow(t *testing.T) { + allocator := memory.NewGoAllocator() + stringBuilder := array.NewStringBuilder(allocator) + stringBuilder.Append("abcd") + strings := stringBuilder.NewStringArray() + defer strings.Release() + stringDescriptor := TypeDescriptor{TypeID: int32(types.T_varchar), Width: 3, OffsetWidth: 32} + require.ErrorContains(t, validateArrowValueDomain(stringDescriptor, strings), "exceeds width") + + timeBuilder := array.NewDurationBuilder(allocator, &arrow.DurationType{Unit: arrow.Microsecond}) + timeBuilder.Append(arrow.Duration(types.MySQLTimeMax + 1)) + times := timeBuilder.NewDurationArray() + defer times.Release() + timeDescriptor := TypeDescriptor{TypeID: int32(types.T_time), Scale: 6, OffsetWidth: 32} + require.ErrorContains(t, validateArrowValueDomain(timeDescriptor, times), "outside the declared SQL domain") +} + +func TestArrowTypeValidationIncludesFixedBinaryWidth(t *testing.T) { + descriptor, err := NewTypeDescriptor(types.T_uuid.ToType()) + require.NoError(t, err) + fingerprint, err := descriptor.Fingerprint() + require.NoError(t, err) + require.Equal(t, "370e2939c178acee55aaae27a7bcf92937a203e2788e9e0140d84884be042780", fingerprint) + builder := array.NewFixedSizeBinaryBuilder(memory.NewGoAllocator(), &arrow.FixedSizeBinaryType{ByteWidth: 1}) + builder.Append([]byte{0xff}) + values := builder.NewFixedSizeBinaryArray() + defer values.Release() + require.ErrorContains(t, validateArrayType(descriptor, values), "does not match") + + field, err := descriptor.Field("uuid") + require.NoError(t, err) + field.Type = &arrow.FixedSizeBinaryType{ByteWidth: 1} + require.ErrorContains(t, descriptor.ValidateField(field), "does not match") +} + +func TestTypeDescriptorRejectsNonCanonicalDomain(t *testing.T) { + invalid := []TypeDescriptor{ + {TypeID: int32(types.T_varchar), Width: -1, OffsetWidth: 32}, + {TypeID: int32(types.T_int64), OffsetWidth: 64}, + {TypeID: int32(types.T_int64)}, + {TypeID: int32(types.T_decimal64), Width: 3, Scale: 4, OffsetWidth: 32}, + {TypeID: int32(types.T_json), OffsetWidth: 32}, + {TypeID: int32(types.T_date), OffsetWidth: 32}, + {TypeID: int32(types.T_array_float32), Width: types.MaxArrayDimension + 1}, + {TypeID: int32(types.T_varchar), Width: 16, Charset: types.CharsetBinary, OffsetWidth: 32}, + } + for _, descriptor := range invalid { + _, err := descriptor.Field("value") + require.Error(t, err, "%+v", descriptor) + } +} + +func TestTypeDescriptorRejectsUnusedDomainFields(t *testing.T) { + invalid := []TypeDescriptor{ + {TypeID: int32(types.T_date), Width: 1, OffsetWidth: 32, TemporalEncoding: "sql_zero_struct"}, + {TypeID: int32(types.T_datetime), Width: 1, OffsetWidth: 32, TemporalEncoding: "sql_zero_struct"}, + {TypeID: int32(types.T_time), Width: 1, Scale: 6, OffsetWidth: 32}, + {TypeID: int32(types.T_varchar), Width: 16, Scale: 1, Charset: types.CharsetUTF8, OffsetWidth: 32}, + {TypeID: int32(types.T_varbinary), Width: 16, Scale: 1, Charset: types.CharsetBinary, OffsetWidth: 32}, + } + for _, descriptor := range invalid { + _, err := descriptor.Field("value") + require.Error(t, err, "%+v", descriptor) + } +} + +func TestFloatDescriptorsRoundTripThroughArrowFieldContract(t *testing.T) { + for _, typ := range []types.T{types.T_float32, types.T_float64} { + descriptor, err := NewTypeDescriptor(typ.ToType()) + require.NoError(t, err) + field, err := descriptor.Field("value") + require.NoError(t, err) + require.NoError(t, descriptor.ValidateField(field)) + require.Equal(t, typ, types.T(descriptor.TypeID)) + } +} + +func TestNewTypeDescriptorNormalizesPlannerOnlySentinels(t *testing.T) { + integer := types.T_int32.ToTypeWithScale(-1) + integer.Width = 32 + descriptor, err := NewTypeDescriptor(integer) + require.NoError(t, err) + require.Equal(t, int32(0), descriptor.Width) + require.Equal(t, int32(0), descriptor.Scale) + + binaryType := types.T_binary.ToTypeWithScale(-1) + binaryType.Width = 8 + descriptor, err = NewTypeDescriptor(binaryType) + require.NoError(t, err) + require.Equal(t, int32(8), descriptor.Width) + require.Equal(t, int32(0), descriptor.Scale) + + temporal := types.T_datetime.ToTypeWithScale(-1) + descriptor, err = NewTypeDescriptor(temporal) + require.NoError(t, err) + require.Equal(t, int32(0), descriptor.Width) + require.Equal(t, int32(0), descriptor.Scale) +} + +func TestBuildInputRecordCanonicalizesJSONText(t *testing.T) { + mp := mpool.MustNewZeroNoFixed() + input := vector.NewVec(types.T_json.ToType()) + defer input.Free(mp) + bj, err := types.ParseStringToByteJson(`{"a":1,"b":[true,null,"中"]}`) + require.NoError(t, err) + raw, err := bj.Marshal() + require.NoError(t, err) + require.NoError(t, vector.AppendBytes(input, raw, false, mp)) + + record, _, err := BuildInputRecord([]*vector.Vector{input}, []types.Type{types.T_json.ToType()}, 1) + require.NoError(t, err) + defer record.Release() + values := record.Column(0).(*array.String) + require.Equal(t, `{"a":1,"b":[true,null,"中"]}`, values.Value(0)) +} + +func TestArrowValueDomainRequiresCanonicalJSONText(t *testing.T) { + descriptor, err := NewTypeDescriptor(types.T_json.ToType()) + require.NoError(t, err) + + for _, test := range []struct { + name string + value string + valid bool + }{ + {name: "canonical", value: `{"a":1,"b":[true,null]}`, valid: true}, + {name: "whitespace", value: ` { "a": 1, "b": [true, null] } `}, + {name: "invalid", value: `{"a":}`}, + } { + t.Run(test.name, func(t *testing.T) { + builder := array.NewStringBuilder(memory.NewGoAllocator()) + builder.Append(test.value) + values := builder.NewStringArray() + defer values.Release() + + err := validateArrowValueDomain(descriptor, values) + if test.valid { + require.NoError(t, err) + } else { + require.ErrorContains(t, err, "JSON row 0") + } + }) + } +} + +func TestGoPythonTypeDescriptorFixtures(t *testing.T) { + data, err := os.ReadFile("testdata/type_descriptors.json") + require.NoError(t, err) + var fixtures []struct { + Name string `json:"name"` + Descriptor TypeDescriptor `json:"descriptor"` + Fingerprint string `json:"fingerprint"` + } + require.NoError(t, json.Unmarshal(data, &fixtures)) + require.NotEmpty(t, fixtures) + for _, fixture := range fixtures { + require.NoError(t, fixture.Descriptor.Validate(), fixture.Name) + fingerprint, err := fixture.Descriptor.Fingerprint() + require.NoError(t, err, fixture.Name) + require.Equal(t, fixture.Fingerprint, fingerprint, fixture.Name) + field, err := fixture.Descriptor.Field("value") + require.NoError(t, err, fixture.Name) + require.NoError(t, fixture.Descriptor.ValidateField(field), fixture.Name) + } +} + +func TestBuildInputRecordCoversEverySupportedType(t *testing.T) { + mp := mpool.MustNewZeroNoFixed() + defer mpool.DeleteMPool(mp) + + jsonValue, err := types.ParseStringToByteJson(`{"a":1,"b":[true,null]}`) + require.NoError(t, err) + jsonBytes, err := jsonValue.Marshal() + require.NoError(t, err) + + cases := []struct { + name string + typ types.Type + append func(*vector.Vector) error + }{ + {"bool", types.T_bool.ToType(), func(v *vector.Vector) error { + if err := vector.AppendFixed(v, true, false, mp); err != nil { + return err + } + return vector.AppendFixed(v, false, true, mp) + }}, + {"int8", types.T_int8.ToType(), func(v *vector.Vector) error { + if err := vector.AppendFixed(v, int8(-1), false, mp); err != nil { + return err + } + return vector.AppendFixed(v, int8(0), true, mp) + }}, + {"int16", types.T_int16.ToType(), func(v *vector.Vector) error { + if err := vector.AppendFixed(v, int16(-1), false, mp); err != nil { + return err + } + return vector.AppendFixed(v, int16(0), true, mp) + }}, + {"int32", types.T_int32.ToType(), func(v *vector.Vector) error { + if err := vector.AppendFixed(v, int32(-1), false, mp); err != nil { + return err + } + return vector.AppendFixed(v, int32(0), true, mp) + }}, + {"int64", types.T_int64.ToType(), func(v *vector.Vector) error { + if err := vector.AppendFixed(v, int64(-1), false, mp); err != nil { + return err + } + return vector.AppendFixed(v, int64(0), true, mp) + }}, + {"uint8", types.T_uint8.ToType(), func(v *vector.Vector) error { + if err := vector.AppendFixed(v, uint8(1), false, mp); err != nil { + return err + } + return vector.AppendFixed(v, uint8(0), true, mp) + }}, + {"uint16", types.T_uint16.ToType(), func(v *vector.Vector) error { + if err := vector.AppendFixed(v, uint16(1), false, mp); err != nil { + return err + } + return vector.AppendFixed(v, uint16(0), true, mp) + }}, + {"uint32", types.T_uint32.ToType(), func(v *vector.Vector) error { + if err := vector.AppendFixed(v, uint32(1), false, mp); err != nil { + return err + } + return vector.AppendFixed(v, uint32(0), true, mp) + }}, + {"uint64", types.T_uint64.ToType(), func(v *vector.Vector) error { + if err := vector.AppendFixed(v, uint64(1), false, mp); err != nil { + return err + } + return vector.AppendFixed(v, uint64(0), true, mp) + }}, + {"float32", types.T_float32.ToType(), func(v *vector.Vector) error { + if err := vector.AppendFixed(v, float32(1.25), false, mp); err != nil { + return err + } + return vector.AppendFixed(v, float32(0), true, mp) + }}, + {"float64", types.T_float64.ToType(), func(v *vector.Vector) error { + if err := vector.AppendFixed(v, float64(1.25), false, mp); err != nil { + return err + } + return vector.AppendFixed(v, float64(0), true, mp) + }}, + {"decimal64", types.New(types.T_decimal64, 18, 6), func(v *vector.Vector) error { + if err := vector.AppendFixed(v, types.Decimal64(123456), false, mp); err != nil { + return err + } + return vector.AppendFixed(v, types.Decimal64(0), true, mp) + }}, + {"decimal128", types.New(types.T_decimal128, 38, 10), func(v *vector.Vector) error { + if err := vector.AppendFixed(v, types.Decimal128{B0_63: 123456}, false, mp); err != nil { + return err + } + return vector.AppendFixed(v, types.Decimal128{}, true, mp) + }}, + {"date", types.T_date.ToType(), func(v *vector.Vector) error { + if err := vector.AppendFixed(v, types.Date(1), false, mp); err != nil { + return err + } + return vector.AppendFixed(v, types.Date(0), true, mp) + }}, + {"time", types.New(types.T_time, 0, 6), func(v *vector.Vector) error { + if err := vector.AppendFixed(v, types.Time(123456), false, mp); err != nil { + return err + } + return vector.AppendFixed(v, types.Time(0), true, mp) + }}, + {"datetime", types.New(types.T_datetime, 0, 6), func(v *vector.Vector) error { + if err := vector.AppendFixed(v, types.Datetime(types.GetUnixEpochSecs()+1), false, mp); err != nil { + return err + } + return vector.AppendFixed(v, types.Datetime(0), true, mp) + }}, + {"timestamp", types.New(types.T_timestamp, 0, 6), func(v *vector.Vector) error { + if err := vector.AppendFixed(v, types.Timestamp(types.TimestampMinValue), false, mp); err != nil { + return err + } + return vector.AppendFixed(v, types.Timestamp(0), true, mp) + }}, + {"char", types.New(types.T_char, 16, 0), func(v *vector.Vector) error { + if err := vector.AppendBytes(v, []byte("中"), false, mp); err != nil { + return err + } + return vector.AppendBytes(v, nil, true, mp) + }}, + {"varchar", types.New(types.T_varchar, 64, 0), func(v *vector.Vector) error { + if err := vector.AppendBytes(v, []byte("matrixone"), false, mp); err != nil { + return err + } + return vector.AppendBytes(v, nil, true, mp) + }}, + {"text", types.T_text.ToType(), func(v *vector.Vector) error { + if err := vector.AppendBytes(v, []byte("matrixone"), false, mp); err != nil { + return err + } + return vector.AppendBytes(v, nil, true, mp) + }}, + {"json", types.T_json.ToType(), func(v *vector.Vector) error { + if err := vector.AppendBytes(v, jsonBytes, false, mp); err != nil { + return err + } + return vector.AppendBytes(v, nil, true, mp) + }}, + {"binary", types.New(types.T_binary, 8, 0), func(v *vector.Vector) error { + if err := vector.AppendBytes(v, []byte{1, 2}, false, mp); err != nil { + return err + } + return vector.AppendBytes(v, nil, true, mp) + }}, + {"varbinary", types.New(types.T_varbinary, 8, 0), func(v *vector.Vector) error { + if err := vector.AppendBytes(v, []byte{1, 2}, false, mp); err != nil { + return err + } + return vector.AppendBytes(v, nil, true, mp) + }}, + {"blob", types.T_blob.ToType(), func(v *vector.Vector) error { + if err := vector.AppendBytes(v, []byte{1, 2}, false, mp); err != nil { + return err + } + return vector.AppendBytes(v, nil, true, mp) + }}, + {"uuid", types.T_uuid.ToType(), func(v *vector.Vector) error { + if err := vector.AppendFixed(v, types.Uuid{1, 2, 3}, false, mp); err != nil { + return err + } + return vector.AppendFixed(v, types.Uuid{}, true, mp) + }}, + {"vecf32", types.New(types.T_array_float32, 3, 0), func(v *vector.Vector) error { + if err := vector.AppendArray(v, []float32{1, 2, 3}, false, mp); err != nil { + return err + } + return vector.AppendArray[float32](v, nil, true, mp) + }}, + {"vecf64", types.New(types.T_array_float64, 3, 0), func(v *vector.Vector) error { + if err := vector.AppendArray(v, []float64{1, 2, 3}, false, mp); err != nil { + return err + } + return vector.AppendArray[float64](v, nil, true, mp) + }}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + input := vector.NewVec(tc.typ) + require.NoError(t, tc.append(input)) + record, _, err := BuildInputRecord([]*vector.Vector{input}, []types.Type{tc.typ}, 2) + require.NoError(t, err) + defer record.Release() + input.Free(mp) + + descriptor, err := NewTypeDescriptor(tc.typ) + require.NoError(t, err) + require.NoError(t, descriptor.ValidateField(record.Schema().Field(0))) + require.Equal(t, int64(2), record.NumRows()) + require.False(t, record.Column(0).IsNull(0)) + require.True(t, record.Column(0).IsNull(1)) + + // Exercise the reverse boundary with the same SQL values. Re-encoding + // the returned MO vector must reproduce the Arrow values and validity + // bitmap for every supported SQL descriptor. + returned := vector.NewFunctionResultWrapper(tc.typ, mp) + defer returned.Free() + require.NoError(t, returned.PreExtendAndReset(2)) + require.NoError(t, AppendArrowResult(descriptor, record.Column(0), returned, mp)) + require.Equal(t, 2, returned.GetResultVector().Length()) + require.False(t, returned.GetResultVector().IsNull(0)) + require.True(t, returned.GetResultVector().IsNull(1)) + + returnedRecord, _, err := BuildInputRecord( + []*vector.Vector{returned.GetResultVector()}, []types.Type{tc.typ}, 2, + ) + require.NoError(t, err) + defer returnedRecord.Release() + require.True(t, array.Equal(record.Column(0), returnedRecord.Column(0)), tc.name) + }) + } +} + +func TestArrowValueDomainRejectsDecimalOverflowAndNullableVectorChild(t *testing.T) { + decimalType := &arrow.Decimal128Type{Precision: 3, Scale: 0} + decimalBuilder := array.NewDecimal128Builder(memory.NewGoAllocator(), decimalType) + decimalBuilder.Append(decimal128.FromI64(1000)) + decimals := decimalBuilder.NewDecimal128Array() + defer decimals.Release() + decimalDescriptor := TypeDescriptor{TypeID: int32(types.T_decimal128), Width: 3, OffsetWidth: 32} + require.ErrorContains(t, validateArrowValueDomain(decimalDescriptor, decimals), "exceeds precision") + + listBuilder := array.NewFixedSizeListBuilder(memory.NewGoAllocator(), 2, arrow.PrimitiveTypes.Float32) + listBuilder.Append(true) + listBuilder.ValueBuilder().(*array.Float32Builder).Append(1) + listBuilder.ValueBuilder().(*array.Float32Builder).AppendNull() + lists := listBuilder.NewArray() + defer lists.Release() + vectorDescriptor := TypeDescriptor{TypeID: int32(types.T_array_float32), Width: 2} + require.ErrorContains(t, validateArrowValueDomain(vectorDescriptor, lists), "vector child") +} + +func TestArrowStringWidthCountsUnicodeCharacters(t *testing.T) { + builder := array.NewStringBuilder(memory.NewGoAllocator()) + builder.Append("中") + values := builder.NewStringArray() + defer values.Release() + descriptor := TypeDescriptor{TypeID: int32(types.T_varchar), Width: 1, OffsetWidth: 32} + require.NoError(t, validateArrowValueDomain(descriptor, values)) +} + +func TestAppendArrowResultIgnoresNullDecimalPayload(t *testing.T) { + decimalType := &arrow.Decimal128Type{Precision: 18, Scale: 0} + validity := memory.NewBufferBytes([]byte{0}) + values := memory.NewBufferBytes(make([]byte, 16)) + // The physical coefficient of a NULL slot is unspecified. Make it a + // value that would not fit Decimal64 to ensure conversion never observes + // the payload after the validity check. + binary.LittleEndian.PutUint64(values.Bytes()[8:], 1) + data := array.NewData(decimalType, 1, []*memory.Buffer{validity, values}, nil, 1, 0) + decimals := array.NewDecimal128Data(data) + data.Release() + defer decimals.Release() + defer validity.Release() + defer values.Release() + + mp := mpool.MustNewZeroNoFixed() + result := vector.NewFunctionResultWrapper(types.T_decimal64.ToType(), mp) + defer result.Free() + require.NoError(t, result.PreExtendAndReset(1)) + + descriptor := TypeDescriptor{TypeID: int32(types.T_decimal64), Width: 18, OffsetWidth: 32} + require.NoError(t, AppendArrowResult(descriptor, decimals, result, mp)) + require.True(t, result.GetResultVector().IsNull(0)) +} + +func TestDecimal128ToDecimal64ChecksSignedRange(t *testing.T) { + max, err := decimalFromArray(decimal128.New(0, math.MaxInt64), true) + require.NoError(t, err) + require.Equal(t, types.Decimal64(math.MaxInt64), max) + + min, err := decimalFromArray(decimal128.New(-1, uint64(1)<<63), true) + require.NoError(t, err) + require.Equal(t, types.Decimal64(uint64(1)<<63), min) + + _, err = decimalFromArray(decimal128.New(0, uint64(1)<<63), true) + require.ErrorContains(t, err, "does not fit Decimal64") + _, err = decimalFromArray(decimal128.New(-1, uint64(1)<<63-1), true) + require.ErrorContains(t, err, "does not fit Decimal64") +} diff --git a/pkg/udf/python/artifact.go b/pkg/udf/python/artifact.go new file mode 100644 index 0000000000000..2c40c9a95edb1 --- /dev/null +++ b/pkg/udf/python/artifact.go @@ -0,0 +1,205 @@ +// Copyright 2026 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 python + +import ( + "context" + "fmt" + "strings" + "unicode/utf8" + + "github.com/matrixorigin/matrixone/pkg/udf/udferr" + "github.com/matrixorigin/matrixone/pkg/util/errutil" + + "github.com/matrixorigin/matrixone/pkg/common/moerr" + "github.com/matrixorigin/matrixone/pkg/defines" + "github.com/matrixorigin/matrixone/pkg/fileservice" + "github.com/matrixorigin/matrixone/pkg/udf" +) + +// DefaultMaxArtifactBytes bounds the inline source bundle used by the current +// Python contract. The bound is applied before a write and before a read, so a +// corrupt or malicious object cannot turn an artifact lookup into an +// unbounded allocation. +const DefaultMaxArtifactBytes int64 = 1 << 20 + +// ArtifactResolver supplies the immutable source bytes for an exact catalog +// artifact reference. The resolver is deliberately keyed by account and +// digest: a digest alone must not become a cross-account capability. +type ArtifactResolver interface { + Resolve(ctx context.Context, accountID uint64, handler, digest string) (string, error) +} + +// ArtifactPublisher publishes an immutable artifact before its catalog +// revision becomes visible. Implementations must make a digest collision or a +// corrupt pre-existing object an error; replacing an object at the same path +// would break old plans that still reference that digest. +type ArtifactPublisher interface { + Publish(ctx context.Context, accountID uint64, handler, source string) (string, error) +} + +// ArtifactStore is the current FileService-backed artifact implementation. +// Resolver and publisher are separate interfaces so execution only needs read +// capability and cannot accidentally publish from the hot path. +type ArtifactStore interface { + ArtifactResolver + ArtifactPublisher +} + +// FileArtifactStore stores content addressed inline source under the shared +// FileService. The account component is part of the object path even though +// the content digest is global, preventing one account from using another +// account's artifact as an execution capability. +type FileArtifactStore struct { + fs fileservice.FileService + maxSize int64 +} + +var _ ArtifactStore = (*FileArtifactStore)(nil) + +func NewFileArtifactStore(fs fileservice.FileService, maxSize int64) (*FileArtifactStore, error) { + if fs == nil { + return nil, udferr.Newf("RESOURCE_UNAVAILABLE: Python artifact store has no FileService") + } + shared, err := fileservice.Get[fileservice.FileService](fs, defines.SharedFileServiceName) + if err != nil { + return nil, errutil.Wrapf(err, "RESOURCE_UNAVAILABLE: Python artifact store has no shared FileService") + } + if maxSize <= 0 { + maxSize = DefaultMaxArtifactBytes + } + if maxSize > DefaultMaxArtifactBytes { + return nil, udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python artifact limit %d exceeds the current contract limit %d", maxSize, DefaultMaxArtifactBytes) + } + return &FileArtifactStore{fs: shared, maxSize: maxSize}, nil +} + +func (s *FileArtifactStore) Publish(ctx context.Context, accountID uint64, handler, source string) (string, error) { + if err := s.validate(); err != nil { + return "", err + } + if ctx == nil { + ctx = context.Background() + } + digest, err := validateArtifactInput(accountID, handler, source, s.maxSize) + if err != nil { + return "", err + } + path := artifactPath(accountID, digest) + data := []byte(source) + // FileService implementations may retain the caller's IOEntry until the + // write returns. Give the store its own immutable backing so later caller + // mutation cannot alter the bytes whose digest is being published. + owned := append([]byte(nil), data...) + err = s.fs.Write(ctx, fileservice.IOVector{ + FilePath: path, + Entries: []fileservice.IOEntry{{Offset: 0, Size: int64(len(owned)), Data: owned}}, + }) + if err == nil { + return digest, nil + } + if !moerr.IsMoErrCode(err, moerr.ErrFileAlreadyExists) { + return "", errutil.Wrapf(err, "python artifact publish %s", digest) + } + // A concurrent or retrying publisher is successful only after reading and + // validating the existing object. This closes the write-once collision + // boundary instead of treating path existence as proof of content identity. + existing, resolveErr := s.Resolve(ctx, accountID, handler, digest) + if resolveErr != nil { + return "", errutil.Wrapf(resolveErr, "python artifact publish %s found an invalid existing object", digest) + } + if existing != source { + return "", udferr.Newf("python artifact publish %s encountered a digest collision", digest) + } + return digest, nil +} + +func (s *FileArtifactStore) Resolve(ctx context.Context, accountID uint64, handler, digest string) (string, error) { + if err := s.validate(); err != nil { + return "", err + } + if ctx == nil { + ctx = context.Background() + } + if strings.TrimSpace(handler) == "" { + return "", udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python artifact has no handler") + } + if !udf.IsSHA256Digest(digest) { + return "", udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python artifact digest is invalid") + } + path := artifactPath(accountID, digest) + entry, err := s.fs.StatFile(ctx, path) + if err != nil { + return "", errutil.Wrapf(err, "RESOURCE_UNAVAILABLE: Python artifact %s is unavailable", digest) + } + if entry == nil || entry.IsDir || entry.Size <= 0 || entry.Size > s.maxSize { + return "", udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python artifact %s has invalid size", digest) + } + data := make([]byte, entry.Size) + readVector := &fileservice.IOVector{ + FilePath: path, + Entries: []fileservice.IOEntry{{Offset: 0, Size: entry.Size, Data: data}}, + } + if err := s.fs.Read(ctx, readVector); err != nil { + return "", errutil.Wrapf(err, "RESOURCE_UNAVAILABLE: Python artifact %s cannot be read", digest) + } + if len(readVector.Entries) != 1 || int64(len(readVector.Entries[0].Data)) != entry.Size { + return "", udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python artifact %s changed size while reading", digest) + } + source := string(readVector.Entries[0].Data) + if !utf8.ValidString(source) { + return "", udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python artifact %s is not valid UTF-8", digest) + } + if udf.PythonInlineArtifactDigest(handler, source) != digest { + return "", udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python artifact %s content digest mismatch", digest) + } + return source, nil +} + +func validateArtifactInput(accountID uint64, handler, source string, maxSize int64) (string, error) { + if maxSize <= 0 { + return "", udferr.Newf("RESOURCE_UNAVAILABLE: Python artifact store has an invalid size limit") + } + if strings.TrimSpace(handler) == "" { + return "", udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python artifact has no handler") + } + if source == "" { + return "", udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python artifact source is empty") + } + if !utf8.ValidString(source) { + return "", udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python artifact source is not valid UTF-8") + } + if int64(len([]byte(source))) > maxSize { + return "", udferr.Newf("RESOURCE_EXHAUSTED: Python artifact exceeds %d bytes", maxSize) + } + return udf.PythonInlineArtifactDigest(handler, source), nil +} + +func (s *FileArtifactStore) validate() error { + if s == nil || s.fs == nil { + return udferr.Newf("RESOURCE_UNAVAILABLE: Python artifact store has no FileService") + } + if s.maxSize <= 0 { + return udferr.Newf("RESOURCE_UNAVAILABLE: Python artifact store has an invalid size limit") + } + return nil +} + +func artifactPath(accountID uint64, digest string) string { + return fileservice.JoinPath( + defines.SharedFileServiceName, + fmt.Sprintf("udf-artifacts/%d/%s", accountID, digest), + ) +} diff --git a/pkg/udf/python/artifact_test.go b/pkg/udf/python/artifact_test.go new file mode 100644 index 0000000000000..4e1be71b90a12 --- /dev/null +++ b/pkg/udf/python/artifact_test.go @@ -0,0 +1,111 @@ +// Copyright 2026 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 python + +import ( + "context" + "strings" + "testing" + + "github.com/matrixorigin/matrixone/pkg/defines" + "github.com/matrixorigin/matrixone/pkg/fileservice" + "github.com/matrixorigin/matrixone/pkg/udf" + "github.com/stretchr/testify/require" +) + +func newTestArtifactStore(t *testing.T, maxSize int64) *FileArtifactStore { + t.Helper() + fs, err := fileservice.NewMemoryFS(defines.SharedFileServiceName, fileservice.DisabledCacheConfig, nil) + require.NoError(t, err) + store, err := NewFileArtifactStore(fs, maxSize) + require.NoError(t, err) + return store +} + +func TestFileArtifactStorePublishesAndResolvesByAccount(t *testing.T) { + store := newTestArtifactStore(t, DefaultMaxArtifactBytes) + ctx := context.Background() + source := "def add(ctx, value):\n return value + 1\n" + digest := udf.PythonInlineArtifactDigest("add", source) + + published, err := store.Publish(ctx, 7, "add", source) + require.NoError(t, err) + require.Equal(t, digest, published) + resolved, err := store.Resolve(ctx, 7, "add", digest) + require.NoError(t, err) + require.Equal(t, source, resolved) + + _, err = store.Resolve(ctx, 8, "add", digest) + require.ErrorContains(t, err, "unavailable") + second, err := store.Publish(ctx, 7, "add", source) + require.NoError(t, err) + require.Equal(t, digest, second, "republication of the exact immutable object is idempotent") +} + +func TestFileArtifactStoreRejectsCorruptionAndDigestCollision(t *testing.T) { + store := newTestArtifactStore(t, DefaultMaxArtifactBytes) + ctx := context.Background() + source := "def add(ctx, value): return value + 1" + digest := udf.PythonInlineArtifactDigest("add", source) + + path := artifactPath(7, digest) + err := store.fs.Write(ctx, fileservice.IOVector{ + FilePath: path, + Entries: []fileservice.IOEntry{{Offset: 0, Size: int64(len("corrupt")), Data: []byte("corrupt")}}, + }) + require.NoError(t, err) + _, err = store.Resolve(ctx, 7, "add", digest) + require.ErrorContains(t, err, "content digest mismatch") + _, err = store.Publish(ctx, 7, "add", source) + require.ErrorContains(t, err, "invalid existing object") +} + +func TestFileArtifactStoreRejectsOversizedSourceBeforeWrite(t *testing.T) { + store := newTestArtifactStore(t, 4) + _, err := store.Publish(context.Background(), 7, "add", "12345") + require.ErrorContains(t, err, "exceeds 4 bytes") + _, statErr := store.fs.StatFile(context.Background(), artifactPath(7, udf.PythonInlineArtifactDigest("add", "12345"))) + require.Error(t, statErr) +} + +func TestNewFileArtifactStoreRequiresSharedFileService(t *testing.T) { + local, err := fileservice.NewMemoryFS("LOCAL", fileservice.DisabledCacheConfig, nil) + require.NoError(t, err) + _, err = NewFileArtifactStore(local, 0) + require.ErrorContains(t, err, "shared FileService") + + shared, err := fileservice.NewMemoryFS(defines.SharedFileServiceName, fileservice.DisabledCacheConfig, nil) + require.NoError(t, err) + _, err = NewFileArtifactStore(shared, DefaultMaxArtifactBytes+1) + require.ErrorContains(t, err, "exceeds the current contract limit") +} + +func TestFileArtifactStoreRejectsInvalidDirectConstruction(t *testing.T) { + var nilStore *FileArtifactStore + _, err := nilStore.Publish(context.Background(), 7, "add", "source") + require.ErrorContains(t, err, "no FileService") + _, err = nilStore.Resolve(context.Background(), 7, "add", strings.Repeat("a", 64)) + require.ErrorContains(t, err, "no FileService") + + store := &FileArtifactStore{} + _, err = store.Publish(context.Background(), 7, "add", "source") + require.ErrorContains(t, err, "no FileService") +} + +func TestFileArtifactStoreRejectsInvalidUTF8(t *testing.T) { + store := newTestArtifactStore(t, DefaultMaxArtifactBytes) + _, err := store.Publish(context.Background(), 7, "add", string([]byte{'\xff'})) + require.ErrorContains(t, err, "not valid UTF-8") +} diff --git a/pkg/udf/python/capability_lifecycle_test.go b/pkg/udf/python/capability_lifecycle_test.go new file mode 100644 index 0000000000000..36ca4d7eaf8ec --- /dev/null +++ b/pkg/udf/python/capability_lifecycle_test.go @@ -0,0 +1,207 @@ +// Copyright 2026 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 python + +import ( + "context" + "encoding/json" + "errors" + "sync" + "testing" + "time" + + "github.com/apache/arrow-go/v18/arrow/flight/gen/flight" + "github.com/matrixorigin/matrixone/pkg/udf" + "github.com/matrixorigin/matrixone/pkg/udf/protocol" + "google.golang.org/grpc" +) + +type blockedCapabilityClient struct { + flight.FlightServiceClient + started chan struct{} + release chan struct{} + once sync.Once +} + +func (c *blockedCapabilityClient) DoAction(ctx context.Context, _ *flight.Action, _ ...grpc.CallOption) (flight.FlightService_DoActionClient, error) { + c.once.Do(func() { close(c.started) }) + select { + case <-c.release: + if err := ctx.Err(); err != nil { + return nil, err + } + return nil, errors.New("released test capability probe") + case <-ctx.Done(): + return nil, ctx.Err() + } +} + +func TestCancelledReadinessDoesNotWaitForOtherProbe(t *testing.T) { + gateway, err := NewGateway(ClientConfig{Enabled: true, AllowUnisolated: true, ServerAddress: "127.0.0.1:1", RequestTimeout: 30 * time.Second}) + if err != nil { + t.Fatal(err) + } + defer gateway.Close() + client := &blockedCapabilityClient{started: make(chan struct{}), release: make(chan struct{})} + gateway.flight = client + firstDone := make(chan error, 1) + go func() { firstDone <- gateway.CheckLanguageReady(context.Background(), udf.LanguagePython) }() + select { + case <-client.started: + case <-time.After(time.Second): + t.Fatal("first probe did not reach the Flight boundary") + } + ctx, cancel := context.WithCancel(context.Background()) + cancel() + secondStarted := make(chan struct{}) + secondDone := make(chan error, 1) + go func() { + close(secondStarted) + secondDone <- gateway.CheckLanguageReady(ctx, udf.LanguagePython) + }() + <-secondStarted + blocked := false + select { + case err := <-secondDone: + if !errors.Is(err, context.Canceled) { + t.Errorf("cancelled probe returned %v", err) + } + case <-time.After(200 * time.Millisecond): + blocked = true + } + close(client.release) + <-firstDone + if blocked { + if err := <-secondDone; !errors.Is(err, context.Canceled) { + t.Errorf("released cancelled probe returned %v", err) + } + t.Fatal("already-cancelled readiness blocked behind another request's capabilityMu/Flight probe; it returned only after the unrelated probe was released") + } +} + +func TestCapabilityInvalidationDoesNotWaitForProbe(t *testing.T) { + g, err := NewGateway(ClientConfig{Enabled: true, AllowUnisolated: true, ServerAddress: "127.0.0.1:1", RequestTimeout: time.Second}) + if err != nil { + t.Fatal(err) + } + defer g.Close() + c := &blockedCapabilityClient{started: make(chan struct{}), release: make(chan struct{})} + done := make(chan error, 1) + go func() { done <- g.ensureCapabilities(context.Background(), c, true) }() + <-c.started + invalidated := make(chan struct{}) + go func() { g.invalidateCapabilities(); close(invalidated) }() + select { + case <-invalidated: + case <-time.After(time.Second): + close(c.release) + <-done + t.Fatal("invalidation blocked on RPC") + } + if err := <-done; err == nil { + t.Fatal("invalidated probe succeeded") + } + g.mu.Lock() + defer g.mu.Unlock() + if g.capabilityReady || g.workerLeaseEpoch != 0 || g.capabilityProbe != nil { + t.Fatal("probe retained state") + } +} + +func TestStaleCapabilityFailurePreservesNewGeneration(t *testing.T) { + g := &Gateway{capabilityGeneration: 2, capabilityReady: true, workerLeaseEpoch: 42} + g.invalidateCapabilities(1) + if !g.capabilityReady || g.workerLeaseEpoch != 42 { + t.Fatal("old failure invalidated new lease") + } + g.invalidateCapabilities(2) + if g.capabilityReady || g.workerLeaseEpoch != 0 { + t.Fatal("current failure retained lease") + } +} + +func currentTestCapabilities() capabilityResponse { + response := capabilityResponse{ + ProtocolVersion: protocol.Version, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + SDKVersion: udf.PythonSDKVersion, + DefinitionSchemaVersion: udf.PythonDefinitionSchemaVersion, + PlanContractVersion: udf.PythonPlanContractVersion, + TypeDescriptorContract: udf.PythonTypeDescriptorContract, + TimezoneDatabaseVersion: currentTimezoneDatabaseVersion(), + Modes: []string{ModeScalar, ModeVector}, + NullPolicies: []string{NullCallHandler, NullReturnNull}, + WindowBatches: 1, + MaxExecutionFrameBytes: 1 << 30, + MaxHandlerProcesses: DefaultWorkerMaxHandlerProcesses, + MaxAccountHandlerProcesses: DefaultWorkerMaxAccountHandlers, + MaxOwnerHandlerProcesses: DefaultWorkerMaxOwnerHandlers, + } + response.LeaseEpoch = 42 + return response +} + +type delayedCapabilityClient struct { + flight.FlightServiceClient + started chan struct{} + release chan struct{} + response capabilityResponse +} + +func (c *delayedCapabilityClient) DoAction(ctx context.Context, _ *flight.Action, _ ...grpc.CallOption) (flight.FlightService_DoActionClient, error) { + close(c.started) + <-c.release // Deliberately ignore cancellation: exercise the publication fence. + payload, err := json.Marshal(c.response) + return &finishAckActionStream{result: &flight.Result{Body: payload}}, err +} +func TestCapabilityLateResponseCannotRepublish(t *testing.T) { + for _, closeGateway := range []bool{false, true} { + t.Run(map[bool]string{false: "invalidate", true: "close"}[closeGateway], func(t *testing.T) { + g, err := NewGateway(ClientConfig{Enabled: true, AllowUnisolated: true, ServerAddress: "127.0.0.1:1", RequestTimeout: time.Second}) + if err != nil { + t.Fatal(err) + } + defer g.Close() + c := &delayedCapabilityClient{started: make(chan struct{}), release: make(chan struct{}), response: currentTestCapabilities()} + done := make(chan error, 1) + go func() { done <- g.ensureCapabilities(context.Background(), c, true) }() + <-c.started + // Close/invalidation must return while a misbehaving transport is blocked. + if closeGateway { + if err := g.Close(); err != nil { + t.Fatal(err) + } + } else { + g.invalidateCapabilities() + } + g.mu.Lock() + occupied := g.capabilityProbe != nil + g.mu.Unlock() + if !occupied { + t.Error("cancelled physical probe released its slot too early") + } + close(c.release) + if err := <-done; err == nil { + t.Fatal("late success escaped generation fence") + } + g.mu.Lock() + defer g.mu.Unlock() + if g.capabilityReady || g.workerLeaseEpoch != 0 || g.capability != nil || g.capabilityProbe != nil { + t.Fatal("late response republished state") + } + }) + } +} diff --git a/pkg/udf/python/config.go b/pkg/udf/python/config.go new file mode 100644 index 0000000000000..021e4f5cc90c8 --- /dev/null +++ b/pkg/udf/python/config.go @@ -0,0 +1,117 @@ +// Copyright 2026 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 python + +import ( + "context" + "time" + + "github.com/matrixorigin/matrixone/pkg/common/moerr" +) + +// maxHandlerTimeout is part of the current Gateway/worker payload contract. +// The worker rejects a handler timeout above one hour; reject it while loading +// the CN configuration so an enabled runtime cannot appear healthy and then +// fail every invocation at the Flight boundary. +const maxHandlerTimeout = time.Hour + +type Config struct { + UUID string `toml:"uuid"` + Address string `toml:"address"` + Path string `toml:"path"` + Python string `toml:"python"` +} + +func (c *Config) Validate() error { + if c.Address == "" { + return moerr.NewInternalError(context.Background(), "missing python udf address") + } + if c.Path == "" { + return moerr.NewInternalError(context.Background(), "missing python udf path") + } + return nil +} + +type ClientConfig struct { + // Enabled is deliberately false by default. The Python worker is an + // unisolated development adapter until the production sandbox contract is + // deployed, so a generic CN launch must never attach it implicitly. + Enabled bool `toml:"enabled"` + AllowUnisolated bool `toml:"allow-unisolated"` + ServerAddress string `toml:"server-address"` + MaxBatchBytes int64 `toml:"max-batch-bytes"` + MaxBatchRows int64 `toml:"max-batch-rows"` + // MaxInvocationRows bounds the rows retained by one physical invocation. + // It is checked before OpenInvocation so a large request cannot reserve a + // worker or run user code before the CN has accepted its result shape. + MaxInvocationRows int64 `toml:"max-invocation-rows"` + // MaxInvocationResultBytes bounds the retained MO result vector for one + // invocation. Arrow frames remain subject to MaxBatchBytes; this separate + // limit prevents many individually valid batches from accumulating an + // unbounded result in the Gateway. + MaxInvocationResultBytes int64 `toml:"max-invocation-result-bytes"` + // MaxActiveInvocations is K: a CN refuses a new physical invocation when + // all slots are in use. It deliberately does not queue, because queued + // execution would retain the caller's input vectors and their allocation + // accounts while waiting for a worker slot. + MaxActiveInvocations int `toml:"max-active-invocations"` + RequestTimeout time.Duration `toml:"request-timeout"` + // Terminal limits cover both active and retained completion tombstones. + // They are reserved before an invocation is sent, so a long stream of + // short calls cannot grow the deduplication ledger without bound. + MaxTerminalEntries int `toml:"max-terminal-entries"` + MaxTerminalBytes int64 `toml:"max-terminal-bytes"` + TerminalRecordTTL time.Duration `toml:"terminal-record-ttl"` +} + +func (c *ClientConfig) Validate() error { + if !c.Enabled { + return nil + } + if !c.AllowUnisolated { + return moerr.NewInternalError(context.Background(), "python udf requires explicit allow-unisolated until the sandbox is configured") + } + if c.ServerAddress == "" { + return moerr.NewInternalError(context.Background(), "missing python udf address") + } + if c.MaxBatchBytes < 0 || c.MaxBatchBytes > 1<<30 { + return moerr.NewInternalError(context.Background(), "invalid python udf max batch bytes") + } + if c.MaxBatchRows < 0 || c.MaxBatchRows > 1<<30 { + return moerr.NewInternalError(context.Background(), "invalid python udf max batch rows") + } + if c.MaxInvocationRows < 0 || c.MaxInvocationRows > 1<<32 { + return moerr.NewInternalError(context.Background(), "invalid python udf max invocation rows") + } + if c.MaxInvocationResultBytes < 0 || c.MaxInvocationResultBytes > 1<<40 { + return moerr.NewInternalError(context.Background(), "invalid python udf max invocation result bytes") + } + if c.MaxActiveInvocations < 0 || c.MaxActiveInvocations > 1<<20 { + return moerr.NewInternalError(context.Background(), "invalid python udf max active invocations") + } + if c.RequestTimeout < 0 || c.RequestTimeout > maxHandlerTimeout { + return moerr.NewInternalError(context.Background(), "invalid python udf request timeout") + } + if c.MaxTerminalEntries < 0 || c.MaxTerminalEntries > 1<<30 { + return moerr.NewInternalError(context.Background(), "invalid python udf max terminal entries") + } + if c.MaxTerminalBytes < 0 || c.MaxTerminalBytes > 1<<40 { + return moerr.NewInternalError(context.Background(), "invalid python udf max terminal bytes") + } + if c.TerminalRecordTTL < 0 { + return moerr.NewInternalError(context.Background(), "invalid python udf terminal record ttl") + } + return nil +} diff --git a/pkg/udf/python/config_test.go b/pkg/udf/python/config_test.go new file mode 100644 index 0000000000000..dad3c7473e9b4 --- /dev/null +++ b/pkg/udf/python/config_test.go @@ -0,0 +1,110 @@ +// Copyright 2026 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 python + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestClientConfigRequiresExplicitUnisolatedOptIn(t *testing.T) { + require.NoError(t, (&ClientConfig{}).Validate()) + require.NoError(t, (&ClientConfig{ServerAddress: "127.0.0.1:50051"}).Validate()) + + config := &ClientConfig{Enabled: true, ServerAddress: "127.0.0.1:50051"} + require.ErrorContains(t, config.Validate(), "allow-unisolated") + + config.AllowUnisolated = true + config.RequestTimeout = time.Second + require.NoError(t, config.Validate()) +} + +func TestClientConfigRejectsUnboundedInvocationAdmission(t *testing.T) { + config := &ClientConfig{ + Enabled: true, + AllowUnisolated: true, + ServerAddress: "127.0.0.1:50051", + MaxActiveInvocations: -1, + } + require.ErrorContains(t, config.Validate(), "max active invocations") + config.MaxActiveInvocations = 1 << 20 + require.NoError(t, config.Validate()) + config.MaxActiveInvocations++ + require.ErrorContains(t, config.Validate(), "max active invocations") +} + +func TestClientConfigRejectsInvalidInvocationBudgets(t *testing.T) { + config := &ClientConfig{ + Enabled: true, AllowUnisolated: true, ServerAddress: "127.0.0.1:50051", + MaxInvocationRows: -1, + } + require.ErrorContains(t, config.Validate(), "max invocation rows") + config.MaxInvocationRows = 1 + config.MaxInvocationResultBytes = -1 + require.ErrorContains(t, config.Validate(), "max invocation result bytes") +} + +func TestClientConfigMatchesWorkerHandlerTimeoutContract(t *testing.T) { + config := &ClientConfig{ + Enabled: true, AllowUnisolated: true, ServerAddress: "127.0.0.1:50051", + RequestTimeout: maxHandlerTimeout, + } + require.NoError(t, config.Validate()) + + config.RequestTimeout = maxHandlerTimeout + time.Nanosecond + require.ErrorContains(t, config.Validate(), "request timeout") +} + +func TestClientConfigRejectsEveryOutOfRangeBudget(t *testing.T) { + for _, tc := range []struct { + name string + mutate func(*ClientConfig) + want string + }{ + {name: "missing worker address", mutate: func(c *ClientConfig) { c.ServerAddress = "" }, want: "missing python udf address"}, + {name: "negative input bytes", mutate: func(c *ClientConfig) { c.MaxBatchBytes = -1 }, want: "max batch bytes"}, + {name: "input bytes exceed wire bound", mutate: func(c *ClientConfig) { c.MaxBatchBytes = 1<<30 + 1 }, want: "max batch bytes"}, + {name: "negative input rows", mutate: func(c *ClientConfig) { c.MaxBatchRows = -1 }, want: "max batch rows"}, + {name: "input rows exceed bound", mutate: func(c *ClientConfig) { c.MaxBatchRows = 1<<30 + 1 }, want: "max batch rows"}, + {name: "invocation rows exceed bound", mutate: func(c *ClientConfig) { c.MaxInvocationRows = 1<<32 + 1 }, want: "max invocation rows"}, + {name: "result bytes exceed bound", mutate: func(c *ClientConfig) { c.MaxInvocationResultBytes = 1<<40 + 1 }, want: "max invocation result bytes"}, + {name: "active slots exceed bound", mutate: func(c *ClientConfig) { c.MaxActiveInvocations = 1<<20 + 1 }, want: "max active invocations"}, + {name: "negative request timeout", mutate: func(c *ClientConfig) { c.RequestTimeout = -time.Nanosecond }, want: "request timeout"}, + {name: "terminal entries exceed bound", mutate: func(c *ClientConfig) { c.MaxTerminalEntries = 1<<30 + 1 }, want: "max terminal entries"}, + {name: "negative terminal bytes", mutate: func(c *ClientConfig) { c.MaxTerminalBytes = -1 }, want: "max terminal bytes"}, + {name: "terminal bytes exceed bound", mutate: func(c *ClientConfig) { c.MaxTerminalBytes = 1<<40 + 1 }, want: "max terminal bytes"}, + {name: "negative tombstone lifetime", mutate: func(c *ClientConfig) { c.TerminalRecordTTL = -time.Nanosecond }, want: "terminal record ttl"}, + } { + t.Run(tc.name, func(t *testing.T) { + config := &ClientConfig{ + Enabled: true, AllowUnisolated: true, ServerAddress: "127.0.0.1:50051", + } + tc.mutate(config) + require.ErrorContains(t, config.Validate(), tc.want) + }) + } +} + +func TestWorkerConfigRequiresAddressAndPath(t *testing.T) { + config := &Config{Path: "/opt/matrixone/pkg/udf/python/worker/worker.py"} + require.ErrorContains(t, config.Validate(), "missing python udf address") + config.Address = "127.0.0.1:50051" + config.Path = "" + require.ErrorContains(t, config.Validate(), "missing python udf path") + config.Path = "/opt/matrixone/pkg/udf/python/worker/worker.py" + require.NoError(t, config.Validate()) +} diff --git a/pkg/udf/python/definition.go b/pkg/udf/python/definition.go new file mode 100644 index 0000000000000..a2617025e597e --- /dev/null +++ b/pkg/udf/python/definition.go @@ -0,0 +1,89 @@ +// Copyright 2026 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 python + +import ( + "crypto/sha256" + "encoding/hex" + "encoding/json" + + "github.com/matrixorigin/matrixone/pkg/udf/udferr" + "github.com/matrixorigin/matrixone/pkg/util/errutil" +) + +// definitionFingerprintBody is the canonical executable contract. Source is +// deliberately absent: original source is a catalog/audit payload, while the +// immutable artifact digest identifies the exact bytes that may be executed. +// Changing a type or execution policy must invalidate the definition even +// when the artifact bytes stay unchanged. +type definitionFingerprintBody struct { + DefinitionSchemaVersion int `json:"definition_schema_version"` + Handler string `json:"handler"` + Mode string `json:"mode"` + NullPolicy string `json:"null_policy"` + ABIContract string `json:"abi_contract"` + AdapterVersion string `json:"adapter_version"` + ArtifactDigest string `json:"artifact_digest"` + EnvironmentDigest string `json:"environment_digest"` + SDKVersion string `json:"sdk_version"` + ArgTypes []TypeDescriptor `json:"arg_types,omitempty"` + ReturnType *TypeDescriptor `json:"return_type,omitempty"` +} + +// DefinitionFingerprint computes the canonical current Python definition +// fingerprint. Callers must pass descriptors produced by NewTypeDescriptor; +// validating here makes the worker and Gateway reject an identity whose type +// metadata is not part of the supported Arrow contract before user code runs. +func DefinitionFingerprint( + definitionSchemaVersion int, + handler, mode, nullPolicy, abiContract, adapterVersion string, + artifactDigest, environmentDigest, sdkVersion string, + args []TypeDescriptor, + returnType TypeDescriptor, +) (string, error) { + if definitionSchemaVersion <= 0 || handler == "" || + mode == "" || nullPolicy == "" || abiContract == "" || + adapterVersion == "" || sdkVersion == "" || artifactDigest == "" || + environmentDigest == "" { + return "", udferr.Newf("python definition fingerprint has incomplete metadata") + } + for index, descriptor := range args { + if err := descriptor.Validate(); err != nil { + return "", errutil.Wrapf(err, "argument descriptor %d", index) + } + } + if err := returnType.Validate(); err != nil { + return "", errutil.Wrapf(err, "return descriptor") + } + body := definitionFingerprintBody{ + DefinitionSchemaVersion: definitionSchemaVersion, + Handler: handler, + Mode: mode, + NullPolicy: nullPolicy, + ABIContract: abiContract, + AdapterVersion: adapterVersion, + ArtifactDigest: artifactDigest, + EnvironmentDigest: environmentDigest, + SDKVersion: sdkVersion, + ArgTypes: args, + ReturnType: &returnType, + } + canonical, err := json.Marshal(body) + if err != nil { + return "", errutil.Wrapf(err, "marshal definition fingerprint") + } + digest := sha256.Sum256(canonical) + return hex.EncodeToString(digest[:]), nil +} diff --git a/pkg/udf/python/definition_test.go b/pkg/udf/python/definition_test.go new file mode 100644 index 0000000000000..9dbeace96877d --- /dev/null +++ b/pkg/udf/python/definition_test.go @@ -0,0 +1,60 @@ +// Copyright 2026 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 python + +import ( + "encoding/json" + "strings" + "testing" + + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/udf" + "github.com/stretchr/testify/require" +) + +func TestDefinitionFingerprintCanonicalContractExcludesSource(t *testing.T) { + argument, err := NewTypeDescriptor(types.T_int64.ToType()) + require.NoError(t, err) + returnType, err := NewTypeDescriptor(types.T_int64.ToType()) + require.NoError(t, err) + artifactDigest := udf.PythonInlineArtifactDigest("add", "def add(ctx, value): return value") + first, err := DefinitionFingerprint( + udf.PythonDefinitionSchemaVersion, + "add", ModeScalar, NullCallHandler, + udf.PythonABIContract, udf.PythonAdapterVersion, + artifactDigest, strings.Repeat("e", 64), udf.PythonSDKVersion, + []TypeDescriptor{argument}, returnType, + ) + require.NoError(t, err) + require.Equal(t, "d0348f99deac2a1518fdf0f32d37a4e7924acbce450c7328d1e83d67d5f7e635", first) + require.True(t, udf.IsSHA256Digest(first)) + + canonical, err := json.Marshal(definitionFingerprintBody{ + DefinitionSchemaVersion: udf.PythonDefinitionSchemaVersion, + Handler: "add", + Mode: ModeScalar, + NullPolicy: NullCallHandler, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + ArtifactDigest: artifactDigest, + EnvironmentDigest: strings.Repeat("e", 64), + SDKVersion: udf.PythonSDKVersion, + ArgTypes: []TypeDescriptor{argument}, + ReturnType: &returnType, + }) + require.NoError(t, err) + require.NotContains(t, string(canonical), `"source"`) + require.Contains(t, string(canonical), `"artifact_digest"`) +} diff --git a/pkg/udf/python/gateway.go b/pkg/udf/python/gateway.go new file mode 100644 index 0000000000000..861885bc9dc7e --- /dev/null +++ b/pkg/udf/python/gateway.go @@ -0,0 +1,2072 @@ +// Copyright 2026 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 python + +import ( + "bytes" + "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "errors" + "io" + "strconv" + "strings" + "sync" + "time" + "unicode/utf8" + + "github.com/matrixorigin/matrixone/pkg/udf/udferr" + "github.com/matrixorigin/matrixone/pkg/util/errutil" + + "github.com/apache/arrow-go/v18/arrow/flight/gen/flight" + "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/udf" + "github.com/matrixorigin/matrixone/pkg/udf/protocol" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +const ( + ModeScalar = "SCALAR" + ModeVector = "VECTOR" + NullCallHandler = "CALLED_ON_NULL_INPUT" + NullReturnNull = "RETURNS_NULL_ON_NULL_INPUT" + DefaultMaxActiveInvocations = 8 + DefaultMaxInvocationRows = 1 << 20 + DefaultMaxInvocationResultBytes = 256 << 20 + DefaultMaxTerminalEntries = 8192 + DefaultMaxTerminalBytes = 8 << 20 + DefaultTerminalRecordTTL = 10 * time.Minute + // These limits are part of the current worker capability contract. H is + // the worker-wide child budget; account and owner limits are narrower + // fairness fences enforced before a handler child is started. + DefaultWorkerMaxHandlerProcesses = 8 + DefaultWorkerMaxAccountHandlers = 8 + DefaultWorkerMaxOwnerHandlers = 4 + statusOK = "OK" +) + +var errGatewayClosed = udferr.New("python udf gateway is closed") + +var _ udf.RuntimeDefinitionValidator = (*Gateway)(nil) +var _ udf.RuntimeStatusProvider = (*Gateway)(nil) + +type Gateway struct { + cfg ClientConfig + artifactResolver ArtifactResolver + allowInlineSource bool + conn *grpc.ClientConn + flight flight.FlightServiceClient + mu sync.Mutex + lifecycleCtx context.Context + lifecycleCancel context.CancelFunc + capabilityGeneration uint64 + capabilityProbe *capabilityProbe + admissionMu sync.Mutex + capabilityReady bool + workerLeaseEpoch uint64 + capability *capabilityResponse + closed bool + active chan struct{} + ledger *protocol.TerminalLedger + ledgerTTL time.Duration + // admittedGroups and closedGroups are the Gateway's ownership fence for + // the current one-member adapter. A group epoch may be admitted only once; + // a terminal tombstone is reclaimable only after its exact group epoch has + // been closed by this owner. closedGroups stores a monotonic high-water + // epoch per group so a late lower-epoch retry cannot become executable + // after its ledger tombstone is collected. + admittedGroups map[string]uint64 + closedGroups map[string]uint64 + closedGroupBytes int64 + reservedGroupBytes int64 + closedGroupLimit int + closedGroupByteLimit int64 +} + +func NewGateway(cfg ClientConfig) (*Gateway, error) { + // NewGateway is kept for direct adapter tests and local development. CN + // production construction uses NewGatewayWithArtifactStore so an + // executable plan can never supply source bytes itself. + return newGateway(cfg, nil, true) +} + +// NewGatewayWithArtifactStore constructs the CN data-plane client for the +// current typed contract. Source is resolved from the exact account/digest +// reference before Open is sent to the worker; a plan carrying source is +// rejected at this boundary. +func NewGatewayWithArtifactStore(cfg ClientConfig, resolver ArtifactResolver) (*Gateway, error) { + if resolver == nil { + return nil, udferr.Newf("RESOURCE_UNAVAILABLE: Python artifact resolver is not configured") + } + return newGateway(cfg, resolver, false) +} + +func newGateway(cfg ClientConfig, resolver ArtifactResolver, allowInlineSource bool) (*Gateway, error) { + if err := cfg.Validate(); err != nil { + return nil, err + } + if cfg.MaxBatchBytes == 0 { + cfg.MaxBatchBytes = DefaultMaxBatchBytes + } + if cfg.MaxBatchRows == 0 { + cfg.MaxBatchRows = DefaultMaxBatchRows + } + if cfg.MaxInvocationRows == 0 { + cfg.MaxInvocationRows = DefaultMaxInvocationRows + } + if cfg.MaxInvocationResultBytes == 0 { + cfg.MaxInvocationResultBytes = DefaultMaxInvocationResultBytes + } + if cfg.RequestTimeout == 0 { + cfg.RequestTimeout = 30 * time.Second + } + if cfg.MaxActiveInvocations == 0 { + cfg.MaxActiveInvocations = DefaultMaxActiveInvocations + } + if cfg.MaxTerminalEntries == 0 { + cfg.MaxTerminalEntries = DefaultMaxTerminalEntries + } + if cfg.MaxTerminalBytes == 0 { + cfg.MaxTerminalBytes = DefaultMaxTerminalBytes + } + if cfg.TerminalRecordTTL == 0 { + cfg.TerminalRecordTTL = DefaultTerminalRecordTTL + } + ledger, err := protocol.NewTerminalLedger(cfg.MaxTerminalEntries, cfg.MaxTerminalBytes) + if err != nil { + return nil, err + } + lifecycleCtx, lifecycleCancel := context.WithCancel(context.Background()) + return &Gateway{ + cfg: cfg, + artifactResolver: resolver, + allowInlineSource: allowInlineSource, + lifecycleCtx: lifecycleCtx, + lifecycleCancel: lifecycleCancel, + active: make(chan struct{}, cfg.MaxActiveInvocations), + ledger: ledger, + ledgerTTL: cfg.TerminalRecordTTL, + admittedGroups: make(map[string]uint64), + closedGroups: make(map[string]uint64), + closedGroupLimit: cfg.MaxTerminalEntries, + closedGroupByteLimit: cfg.MaxTerminalBytes, + }, nil +} + +func (g *Gateway) Language() string { return udf.LanguagePython } + +func (g *Gateway) CheckLanguageReady(ctx context.Context, language string) error { + if ctx == nil { + ctx = context.Background() + } + if language != udf.LanguagePython { + return udferr.Newf("python udf: unsupported readiness language %q", language) + } + if !g.cfg.Enabled { + return udferr.Newf("RESOURCE_UNAVAILABLE: Python UDF runtime is disabled") + } + if !g.cfg.AllowUnisolated { + return udferr.Newf("RESOURCE_UNAVAILABLE: Python UDF runtime requires explicit unisolated opt-in") + } + requestCtx, release := g.withLifecycleContext(ctx) + defer release() + client, err := g.flightClient() + if err != nil { + return err + } + // Readiness is an external admission decision. Refresh the worker + // capability record so a worker replacement at the same endpoint cannot + // inherit a stale success from the previous process. + return g.ensureCapabilities(requestCtx, client, true) +} + +// StatusSnapshot is the control-plane view of the current Python runtime. It +// deliberately reuses CheckLanguageReady, so the status reported for a +// same-Pod CN is the same capability handshake that gates an invocation. The +// action only probes the worker and does not acquire an invocation, handler, +// input credit, or terminal-ledger entry. +func (g *Gateway) StatusSnapshot(ctx context.Context, language string) udf.RuntimeStatusSnapshot { + if ctx == nil { + ctx = context.Background() + } + snapshot := udf.RuntimeStatusSnapshot{ + Language: language, + Enabled: g.cfg.Enabled, + AllowUnisolated: g.cfg.AllowUnisolated, + } + if language != udf.LanguagePython { + snapshot.ErrorClass = udf.RuntimeStatusInvalid + snapshot.Reason = udf.RuntimeStatusReasonInvalidLanguage + return snapshot + } + if !g.cfg.Enabled { + snapshot.ErrorClass = udf.RuntimeStatusDisabled + snapshot.Reason = udf.RuntimeStatusReasonRuntimeDisabled + return snapshot + } + if !g.cfg.AllowUnisolated { + snapshot.ErrorClass = udf.RuntimeStatusNotAllowed + snapshot.Reason = udf.RuntimeStatusReasonUnisolatedNotAllowed + return snapshot + } + + err := g.CheckLanguageReady(ctx, language) + g.mu.Lock() + capability := g.capability + ready := g.capabilityReady && g.workerLeaseEpoch != 0 && !g.closed + if capability != nil { + snapshot.ProtocolVersion = int32(capability.ProtocolVersion) + snapshot.ABIContract = capability.ABIContract + snapshot.AdapterVersion = capability.AdapterVersion + snapshot.SDKVersion = capability.SDKVersion + snapshot.DefinitionSchemaVersion = int32(capability.DefinitionSchemaVersion) + snapshot.PlanContractVersion = int32(capability.PlanContractVersion) + snapshot.TypeDescriptorContract = capability.TypeDescriptorContract + snapshot.TimezoneDatabaseVersion = capability.TimezoneDatabaseVersion + snapshot.WindowBatches = int32(capability.WindowBatches) + snapshot.CumulativeAck = capability.CumulativeAck + snapshot.MaxExecutionFrameBytes = capability.MaxExecutionFrameBytes + snapshot.MaxHandlerProcesses = int32(capability.MaxHandlerProcesses) + snapshot.MaxAccountHandlerProcesses = int32(capability.MaxAccountHandlerProcesses) + snapshot.MaxOwnerHandlerProcesses = int32(capability.MaxOwnerHandlerProcesses) + snapshot.LeaseEpoch = capability.LeaseEpoch + snapshot.Modes = append([]string(nil), capability.Modes...) + snapshot.NullPolicies = append([]string(nil), capability.NullPolicies...) + } + g.mu.Unlock() + + if err == nil && ready { + snapshot.Ready = true + snapshot.ErrorClass = "" + snapshot.Reason = udf.RuntimeStatusReasonReady + return snapshot + } + if err == nil { + snapshot.ErrorClass = udf.RuntimeStatusUnavailable + snapshot.Reason = udf.RuntimeStatusReasonWorkerUnavailable + return snapshot + } + snapshot.ErrorClass, snapshot.Reason = classifyStatusError(err) + return snapshot +} + +func classifyStatusError(err error) (string, string) { + if err == nil { + return "", udf.RuntimeStatusReasonReady + } + if errors.Is(err, context.DeadlineExceeded) { + return udf.RuntimeStatusTimeout, udf.RuntimeStatusReasonRequestTimeout + } + if errors.Is(err, errGatewayClosed) { + return udf.RuntimeStatusClosed, udf.RuntimeStatusReasonRuntimeClosed + } + message := strings.ToLower(err.Error()) + switch { + case strings.Contains(message, "contract does not match"), + strings.Contains(message, "capability set does not match"): + return udf.RuntimeStatusContractMismatch, udf.RuntimeStatusReasonCapabilityMismatch + case strings.Contains(message, "deadline exceeded"), strings.Contains(message, "timeout"): + return udf.RuntimeStatusTimeout, udf.RuntimeStatusReasonRequestTimeout + case strings.Contains(message, "connection"), strings.Contains(message, "transport"), + strings.Contains(message, "flight"), strings.Contains(message, "unavailable"): + return udf.RuntimeStatusUnavailable, udf.RuntimeStatusReasonWorkerUnavailable + default: + return udf.RuntimeStatusInternal, udf.RuntimeStatusReasonRuntimeError + } +} + +// ValidateDefinition asks the current worker to compile the exact artifact +// that a CREATE or REPLACE is about to publish. This action has no +// FunctionRef, invocation lease, handler slot, or ledger entry: a definition +// has not acquired a Catalog identity and must not consume execution state. +// The worker performs compile(source, ..., "exec") only; it does not execute +// top-level code, import dependencies, or call the handler. +func (g *Gateway) ValidateDefinition(ctx context.Context, definition *udf.RoutineDefinition) error { + g.mu.Lock() + closed := g.closed + g.mu.Unlock() + if closed { + return errGatewayClosed + } + if !g.cfg.Enabled { + return udferr.Newf("RESOURCE_UNAVAILABLE: Python UDF runtime is disabled") + } + if !g.cfg.AllowUnisolated { + return udferr.Newf("RESOURCE_UNAVAILABLE: Python UDF runtime requires explicit unisolated opt-in") + } + requestCtx, release := g.withLifecycleContext(ctx) + defer release() + var cancel context.CancelFunc + if g.cfg.RequestTimeout > 0 { + requestCtx, cancel = context.WithTimeout(requestCtx, g.cfg.RequestTimeout) + defer cancel() + } + if definition == nil { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: nil Python routine definition") + } + if definition.Language != udf.LanguagePython { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: unsupported UDF language %q", definition.Language) + } + if strings.TrimSpace(definition.Handler) == "" { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python handler is required") + } + if strings.Contains(definition.Handler, ":") { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python external handler import requires the immutable artifact catalog") + } + if definition.DefinitionSchemaVersion != udf.PythonDefinitionSchemaVersion || + definition.ABIContract != udf.PythonABIContract || + definition.AdapterVersion != udf.PythonAdapterVersion || + definition.SDKVersion != udf.PythonSDKVersion { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python definition contract is not supported") + } + if definition.Mode != ModeScalar && definition.Mode != ModeVector { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: unsupported Python mode %q", definition.Mode) + } + if definition.NullPolicy != NullCallHandler && definition.NullPolicy != NullReturnNull { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: unsupported Python NULL policy %q", definition.NullPolicy) + } + if !udf.IsSHA256Digest(definition.ArtifactDigest) || !udf.IsSHA256Digest(definition.EnvironmentDigest) { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python definition digest is invalid") + } + currentEnvironment, err := udf.PythonEnvironmentDigest() + if err != nil || currentEnvironment != definition.EnvironmentDigest { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python environment digest does not match the current contract") + } + if !udf.IsSHA256Digest(definition.DefinitionFingerprint) { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python definition fingerprint is invalid") + } + args := make([]TypeDescriptor, len(definition.Args)) + for index, typ := range definition.Args { + args[index], err = NewTypeDescriptor(typ) + if err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: Python argument descriptor %d", index) + } + } + returnDescriptor, err := NewTypeDescriptor(definition.ReturnType) + if err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: Python return descriptor") + } + expectedFingerprint, err := DefinitionFingerprint( + definition.DefinitionSchemaVersion, + definition.Handler, definition.Mode, definition.NullPolicy, + definition.ABIContract, definition.AdapterVersion, + definition.ArtifactDigest, definition.EnvironmentDigest, definition.SDKVersion, + args, returnDescriptor, + ) + if err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: Python definition fingerprint cannot be computed") + } + if definition.DefinitionFingerprint != expectedFingerprint { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python definition fingerprint does not match the typed definition") + } + + source := definition.Source + if g.artifactResolver != nil { + resolved, resolveErr := g.artifactResolver.Resolve( + requestCtx, definition.AccountID, definition.Handler, definition.ArtifactDigest, + ) + if resolveErr != nil { + return resolveErr + } + if source != "" && source != resolved { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python artifact source does not match the immutable artifact") + } + source = resolved + } else if !g.allowInlineSource { + return udferr.Newf("RESOURCE_UNAVAILABLE: Python artifact resolver is not configured") + } + if source == "" || !utf8.ValidString(source) { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python artifact source is empty or not valid UTF-8") + } + if int64(len([]byte(source))) > DefaultMaxArtifactBytes { + return udferr.Newf("RESOURCE_EXHAUSTED: Python artifact exceeds %d bytes", DefaultMaxArtifactBytes) + } + if udf.PythonInlineArtifactDigest(definition.Handler, source) != definition.ArtifactDigest { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python artifact digest does not match the immutable source") + } + + client, err := g.flightClient() + if err != nil { + return err + } + // Definition validation is a Flight Action and therefore has no invocation + // lease in its request. It must perform its own worker-instance handshake; + // relying on a cached readiness result could validate against a replacement + // worker with a different contract. + capability, err := g.ensureCapabilitySnapshot(requestCtx, client, true) + if err != nil { + return err + } + payload, err := json.Marshal(definitionValidationPayload{ + AccountID: definition.AccountID, + Handler: definition.Handler, + Source: source, + Mode: definition.Mode, + NullPolicy: definition.NullPolicy, + ABIContract: definition.ABIContract, + AdapterVersion: definition.AdapterVersion, + SDKVersion: definition.SDKVersion, + DefinitionSchemaVersion: definition.DefinitionSchemaVersion, + ArtifactDigest: definition.ArtifactDigest, + EnvironmentDigest: definition.EnvironmentDigest, + DefinitionFingerprint: definition.DefinitionFingerprint, + Args: args, + Return: returnDescriptor, + }) + if err != nil { + return errutil.Wrapf(err, "python udf: encode definition validation") + } + actionCtx := requestCtx + var actionCancel context.CancelFunc + if g.cfg.RequestTimeout > 0 { + actionCtx, actionCancel = context.WithTimeout(requestCtx, g.cfg.RequestTimeout) + defer actionCancel() + } + stream, err := client.DoAction(actionCtx, &flight.Action{Type: "ValidatePythonDefinition", Body: payload}) + if err != nil { + g.invalidateCapabilities(capability.generation) + return errutil.Wrapf(err, "python udf: definition validation action") + } + result, err := stream.Recv() + if err != nil { + g.invalidateCapabilities(capability.generation) + return errutil.Wrapf(err, "python udf: definition validation response") + } + if result == nil { + g.invalidateCapabilities(capability.generation) + return udferr.Newf("python udf: empty definition validation response") + } + var response definitionValidationResponse + decoder := json.NewDecoder(bytes.NewReader(result.Body)) + decoder.DisallowUnknownFields() + if err := decoder.Decode(&response); err != nil { + g.invalidateCapabilities(capability.generation) + return errutil.Wrapf(err, "python udf: decode definition validation response") + } + var trailing any + if err := decoder.Decode(&trailing); err != io.EOF { + g.invalidateCapabilities(capability.generation) + return udferr.Newf("python udf: definition validation response has trailing JSON") + } + if response.Status == "ERROR" { + if _, err := stream.Recv(); err != io.EOF { + g.invalidateCapabilities(capability.generation) + if err == nil { + return udferr.Newf("python udf: definition validation returned multiple results") + } + return errutil.Wrapf(err, "python udf: definition validation stream") + } + if response.Reason == "" { + return udferr.Newf("USER_CODE: Python definition validation failed") + } + return udferr.New(response.Reason) + } + if response.Status != statusOK || response.ArtifactDigest != definition.ArtifactDigest || + response.DefinitionFingerprint != definition.DefinitionFingerprint { + g.invalidateCapabilities(capability.generation) + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python definition validation returned an invalid result") + } + if _, err := stream.Recv(); err != io.EOF { + g.invalidateCapabilities(capability.generation) + if err == nil { + return udferr.Newf("python udf: definition validation returned multiple results") + } + return errutil.Wrapf(err, "python udf: definition validation stream") + } + return nil +} + +func (g *Gateway) connect() error { + _, err := g.flightClient() + return err +} + +func (g *Gateway) flightClient() (flight.FlightServiceClient, error) { + g.mu.Lock() + defer g.mu.Unlock() + if g.closed { + return nil, errGatewayClosed + } + if g.flight != nil { + return g.flight, nil + } + conn, err := grpc.NewClient(g.cfg.ServerAddress, + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithDefaultCallOptions( + grpc.MaxCallSendMsgSize(int(g.cfg.MaxBatchBytes)+1<<20), + grpc.MaxCallRecvMsgSize(int(g.cfg.MaxBatchBytes)+1<<20), + ), + ) + if err != nil { + return nil, err + } + g.conn = conn + g.flight = flight.NewFlightServiceClient(conn) + return g.flight, nil +} + +func (g *Gateway) Close() error { + g.mu.Lock() + if g.closed { + g.mu.Unlock() + return nil + } + if g.lifecycleCancel != nil { + g.lifecycleCancel() + } + // Serialize the close barrier with group admission. Once this lock is + // released, no caller can pass the admission check after Close returns. + g.admissionMu.Lock() + g.closed = true + g.capabilityGeneration++ + g.capabilityReady, g.workerLeaseEpoch, g.capability = false, 0, nil + var probeCancel context.CancelFunc + if g.capabilityProbe != nil { + probeCancel = g.capabilityProbe.cancel + } + conn := g.conn + g.conn = nil + g.admissionMu.Unlock() + g.mu.Unlock() + if probeCancel != nil { + probeCancel() + } + if conn == nil { + return nil + } + // Closing the connection is deliberately outside the mutex. gRPC uses + // this operation to interrupt in-flight exchanges; holding a lifecycle + // read lock until Execute returns would make shutdown wait for the very RPC + // it needs to cancel. + return conn.Close() +} + +// withLifecycleContext combines a caller's cancellation with the Gateway +// lifetime. A resolver or a readiness action can run before a Flight stream +// exists, so closing the gRPC connection alone cannot interrupt it. The +// returned release function removes the AfterFunc callback and cancels the +// derived context when the operation completes. +func (g *Gateway) withLifecycleContext(parent context.Context) (context.Context, func()) { + if parent == nil { + parent = context.Background() + } + combined, cancel := context.WithCancel(parent) + g.mu.Lock() + lifecycle := g.lifecycleCtx + g.mu.Unlock() + if lifecycle == nil { + return combined, cancel + } + stop := context.AfterFunc(lifecycle, cancel) + return combined, func() { + stop() + cancel() + } +} + +type openPayload struct { + FunctionRef udf.FunctionRef `json:"function_ref"` + Handler string `json:"handler"` + Source string `json:"source"` + Mode string `json:"mode"` + NullPolicy string `json:"null_policy"` + ABIContract string `json:"abi_contract"` + AdapterVersion string `json:"adapter_version"` + SDKVersion string `json:"sdk_version"` + DefinitionSchemaVersion int `json:"definition_schema_version"` + ArtifactDigest string `json:"artifact_digest"` + EnvironmentDigest string `json:"environment_digest"` + DefinitionFingerprint string `json:"definition_fingerprint"` + Context map[string]string `json:"context,omitempty"` + CallsiteID string `json:"callsite_id"` + MayError bool `json:"may_error"` + SecurityMode string `json:"security_mode"` + Leakproof bool `json:"leakproof"` + StatementContext *udf.StatementContext `json:"statement_context,omitempty"` + SecurityFrame *udf.SecurityFrame `json:"security_frame,omitempty"` + Args []TypeDescriptor `json:"args"` + Return TypeDescriptor `json:"return"` + MaxBatchBytes int64 `json:"max_batch_bytes"` + MaxBatchRows int64 `json:"max_batch_rows"` + MaxInvocationRows int64 `json:"max_invocation_rows"` + MaxInvocationResultBytes int64 `json:"max_invocation_result_bytes"` + HandlerTimeoutSeconds float64 `json:"handler_timeout_seconds"` +} + +func (g *Gateway) Execute(ctx context.Context, invocation *udf.Invocation, result vector.FunctionResultWrapper, mp *mpool.MPool) (err error) { + g.mu.Lock() + closed := g.closed + g.mu.Unlock() + if closed { + return errGatewayClosed + } + if !g.cfg.Enabled { + return udferr.Newf("RESOURCE_UNAVAILABLE: Python UDF runtime is disabled") + } + if !g.cfg.AllowUnisolated { + return udferr.Newf("RESOURCE_UNAVAILABLE: Python UDF runtime requires explicit unisolated opt-in") + } + requestCtx, release := g.withLifecycleContext(ctx) + defer release() + streamCtx, cancel := context.WithTimeout(requestCtx, g.cfg.RequestTimeout) + defer cancel() + if invocation == nil || result == nil || mp == nil { + return udferr.Newf("python udf: nil invocation, result, or memory pool") + } + execution := *invocation + if g.artifactResolver != nil { + if execution.Source != "" { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: typed Python invocation contains source; use its immutable artifact digest") + } + // Validate the identity, semantic contract, descriptors, and resource + // shape before resolving an account-scoped artifact. Resolution is a + // read with tenant-sensitive error/latency behavior; it must not become + // the first operation performed on an untrusted or stale plan. The + // source-dependent digest check is repeated after the resolver returns. + if err := validateInvocationHeader(&execution); err != nil { + return err + } + execution.Source, err = g.artifactResolver.Resolve( + streamCtx, + execution.FunctionRef.AccountID, + execution.Handler, + execution.ArtifactDigest, + ) + if err != nil { + return err + } + } else if !g.allowInlineSource && execution.Source == "" { + return udferr.Newf("RESOURCE_UNAVAILABLE: Python artifact resolver is not configured") + } + if err := validateInvocation(&execution); err != nil { + return err + } + args := make([]TypeDescriptor, len(execution.Args)) + for i, typ := range execution.Args { + args[i], err = NewTypeDescriptor(typ) + if err != nil { + return err + } + } + returnDescriptor, err := NewTypeDescriptor(invocation.ReturnType) + if err != nil { + return err + } + if err := validateInvocationBudget(executionBudget{ + rows: int64(execution.Length), + maxRows: g.cfg.MaxInvocationRows, + returnType: execution.ReturnType, + maxResultBytes: g.cfg.MaxInvocationResultBytes, + }); err != nil { + return err + } + if execution.Length == 0 { + return result.PreExtendAndReset(0) + } + inputEncoder, err := newInputBatchEncoder(execution.Inputs, execution.Args) + if err != nil { + return err + } + inputEncoderClosed := false + closeInputEncoder := func() error { + if inputEncoderClosed { + return nil + } + if err := inputEncoder.close(); err != nil { + return err + } + inputEncoderClosed = true + return nil + } + defer func() { + if closeErr := closeInputEncoder(); err == nil && closeErr != nil { + err = closeErr + } + }() + client, err := g.flightClient() + if err != nil { + return err + } + capability, err := g.ensureCapabilitySnapshot(streamCtx, client, false) + if err != nil { + return err + } + // The worker instance owns the lease epoch. Copy the invocation before + // attaching it so a caller cannot observe or reuse an identity issued for + // another worker process. If the worker was restarted after the cached + // handshake, the exchange fails with STALE_LEASE_EPOCH and the deferred + // invalidation below forces a fresh handshake on the next call. + workerLeaseEpoch := capability.response.LeaseEpoch + if workerLeaseEpoch == 0 { + return udferr.Newf("python udf: capability handshake did not return a worker lease epoch") + } + execution.Tuple.LeaseEpoch = workerLeaseEpoch + if err := validateInvocation(&execution); err != nil { + return err + } + defer func() { + if err != nil { + g.invalidateCapabilities(capability.generation) + } + }() + openBody, err := json.Marshal(openPayload{ + FunctionRef: execution.FunctionRef, Handler: execution.Handler, Source: execution.Source, + Mode: execution.Mode, NullPolicy: execution.NullPolicy, ABIContract: execution.ABIContract, + AdapterVersion: execution.AdapterVersion, SDKVersion: execution.SDKVersion, + DefinitionSchemaVersion: execution.DefinitionSchemaVersion, + ArtifactDigest: execution.ArtifactDigest, EnvironmentDigest: execution.EnvironmentDigest, + DefinitionFingerprint: execution.DefinitionFingerprint, + Context: cloneMap(execution.Context), CallsiteID: execution.CallsiteID, + MayError: execution.MayError, SecurityMode: execution.SecurityMode, + Leakproof: execution.Leakproof, StatementContext: execution.StatementContext, + SecurityFrame: execution.SecurityFrame, Args: args, Return: returnDescriptor, + MaxBatchBytes: g.cfg.MaxBatchBytes, MaxBatchRows: g.cfg.MaxBatchRows, + MaxInvocationRows: g.cfg.MaxInvocationRows, MaxInvocationResultBytes: g.cfg.MaxInvocationResultBytes, + HandlerTimeoutSeconds: g.cfg.RequestTimeout.Seconds(), + }) + if err != nil { + return errutil.Wrapf(err, "python udf: encode open payload") + } + open, err := protocol.MarshalControl(protocol.Control{Kind: "OpenInvocation", Tuple: execution.Tuple, Payload: openBody}) + if err != nil { + return err + } + admission, err := g.admitInvocation(&execution) + if err != nil { + return err + } + openAttempted := false + defer func() { + reason := admissionReason(streamCtx, openAttempted, err) + // Cancel the Flight exchange before returning the local K slot and + // terminal-ledger ownership. On an input/send/receive failure the + // worker may still be running; releasing admission first would let a + // replacement invocation start while the old handler has not yet seen + // its cancellation. + cancel() + if cleanupErr := admission.finish(openAttempted, reason); err == nil && cleanupErr != nil { + err = cleanupErr + } + }() + + stream, err := client.DoExchange(streamCtx) + if err != nil { + return errutil.Wrapf(err, "python udf: open Arrow Flight exchange") + } + // Flight carries the invocation command in the descriptor. The descriptor + // is delivered to the server separately from the Arrow IPC reader; putting + // the JSON command in AppMetadata on this message makes PyArrow try to + // decode it as an IPC message. + // Once Send is attempted the remote side may have accepted the command. The + // admission is therefore terminalized conservatively even when Send returns + // a transport error; transparent replay would violate VOLATILE semantics. + openAttempted = true + if err := stream.Send(&flight.FlightData{FlightDescriptor: &flight.FlightDescriptor{Type: flight.FlightDescriptor_CMD, Cmd: open}}); err != nil { + return err + } + if err := result.PreExtendAndReset(execution.Length); err != nil { + return err + } + + var sequence protocol.Sequence + var schemaFrame *ArrowFrame + schemaReady := false + var inputSchema []byte + rows := 0 + var start int64 + var batchIndex uint64 + var lastSequence uint64 + var inputEnded bool + for start < int64(execution.Length) { + batch, err := encodeInputBatchWithEncoder(inputEncoder, start, int64(execution.Length)-start, g.cfg.MaxBatchBytes, g.cfg.MaxBatchRows) + if err != nil { + return err + } + if len(batch.Frames) != 2 { + return udferr.Newf("python udf: input batch contains %d Arrow frames", len(batch.Frames)) + } + if batchIndex == 0 { + inputSchema = append([]byte(nil), batch.Frames[0].Header...) + if err := stream.Send(&flight.FlightData{DataHeader: batch.Frames[0].Header}); err != nil { + return err + } + } else if !bytes.Equal(inputSchema, batch.Frames[0].Header) { + return udferr.Newf("python udf: input batches do not share one Arrow schema") + } + sequenceNumber := batchIndex + 1 + if err := sequence.AcceptInput(sequenceNumber); err != nil { + return err + } + inputControl, err := protocol.MarshalControl(protocol.Control{Kind: "InputBatch", Tuple: execution.Tuple, Sequence: sequenceNumber}) + if err != nil { + return err + } + if err := stream.Send(&flight.FlightData{DataHeader: batch.Frames[1].Header, DataBody: batch.Frames[1].Body, AppMetadata: inputControl}); err != nil { + return err + } + lastSequence = sequenceNumber + isLastBatch := start+batch.Rows == int64(execution.Length) + if isLastBatch { + // EndInput is an application-level half-close. Send it before + // waiting for the final result so the runtime must keep its result + // direction alive when that result is delayed on the wire. + endInput, err := protocol.MarshalControl(protocol.Control{Kind: "EndInput", Tuple: execution.Tuple, LastSequence: lastSequence}) + if err != nil { + return err + } + if err := stream.Send(&flight.FlightData{AppMetadata: endInput}); err != nil { + return err + } + if err := sequence.EndInput(lastSequence); err != nil { + return err + } + if err := stream.CloseSend(); err != nil { + return err + } + inputEnded = true + } + batchRows, err := g.receiveResultBatch(streamCtx, client, stream, execution.Tuple, sequenceNumber, batch.Rows, &schemaFrame, &schemaReady, returnDescriptor, result, mp, &sequence) + if err != nil { + return err + } + rows += batchRows + start += batch.Rows + batchIndex++ + if isLastBatch { + break + } + } + if !inputEnded || lastSequence != batchIndex { + return udferr.Newf("python udf: input stream did not reach EndInput") + } + // Close the local Arrow writer before accepting the worker's terminal + // Finish. If finalizing the local input owner fails, the admission cleanup + // still has a chance to cancel/close the remote invocation; acknowledging + // Finish first would publish remote success while returning a local error. + if err := closeInputEncoder(); err != nil { + return err + } + if err := g.receiveFinish(streamCtx, client, stream, execution.Tuple, execution.Length, rows, &sequence); err != nil { + return err + } + return nil +} + +// invocationAdmission is the real Gateway owner for the CN-side execution +// resources. K is the active slot, the group owns its release, and the ledger +// retains the fencing key after completion so a late retry cannot create a new +// execution. The current W=1 exchange has one member per physical invocation; +// the group API remains able to grow to a multi-member scheduler later. +type invocationAdmission struct { + gateway *Gateway + group *protocol.ExecutionGroup + credit *protocol.LedgerCredit + key string + groupKey string + invocationID string + + mu sync.Mutex + finished bool + memberOpen bool +} + +func (g *Gateway) admitInvocation(invocation *udf.Invocation) (*invocationAdmission, error) { + if invocation == nil { + return nil, udferr.Newf("python udf: cannot admit a nil invocation") + } + if err := invocation.Tuple.Validate(); err != nil { + return nil, err + } + if err := g.ensureAdmissionState(); err != nil { + return nil, err + } + + key, err := invocationLedgerKey(invocation.Tuple) + if err != nil { + return nil, err + } + groupKey := scopedGroupKey(invocation.Tuple.AccountID, invocation.Tuple.GroupID) + // g.mu -> admissionMu is the lifecycle lock order. Close uses the same + // order so a concurrent shutdown cannot return while this invocation is + // still being admitted. Keep g.mu held until the complete claim is either + // published or rolled back; otherwise Close could return in the gap between + // the group claim and the ledger/K reservation becoming owned. + g.mu.Lock() + if g.closed { + g.mu.Unlock() + return nil, errGatewayClosed + } + g.admissionMu.Lock() + ledger := g.ledger + ttl := g.ledgerTTL + active := g.active + if err := g.claimGroupLocked(groupKey, invocation.Tuple.GroupEpoch); err != nil { + g.admissionMu.Unlock() + g.mu.Unlock() + return nil, err + } + g.admissionMu.Unlock() + if ledger == nil || active == nil { + g.releaseGroupClaim(groupKey, invocation.Tuple.GroupEpoch) + g.mu.Unlock() + return nil, udferr.Newf("python udf: admission state is not initialized") + } + // Expire is intentionally limited to tombstones by TerminalLedger. An + // active invocation can leave this path only through finish/abandon. + // TTL alone cannot prove that a stale tuple can no longer receive a grant. + // The group owner supplies that proof; a closed epoch is the only fence + // that permits an expired tombstone to release its reserved capacity. + ledger.Expire(time.Now(), g.epochClosed) + entryBytes := int64(len(key)) + credit, err := ledger.Reserve(groupKey, invocation.Tuple.GroupEpoch, 1, entryBytes) + if err != nil { + g.releaseGroupClaim(groupKey, invocation.Tuple.GroupEpoch) + g.mu.Unlock() + return nil, errutil.Wrapf(err, "RESOURCE_EXHAUSTED: Python UDF terminal ledger") + } + if err := credit.Add(key, entryBytes, time.Now().Add(ttl)); err != nil { + credit.ReleaseUnused() + g.releaseGroupClaim(groupKey, invocation.Tuple.GroupEpoch) + g.mu.Unlock() + return nil, err + } + select { + case active <- struct{}{}: + // The group release callback returns this slot after the member is + // terminal. No queue is created, so caller vectors are never held while + // waiting for K. + default: + _ = ledger.Abandon(key) + credit.ReleaseUnused() + g.releaseGroupClaim(groupKey, invocation.Tuple.GroupEpoch) + g.mu.Unlock() + return nil, udferr.Newf("RESOURCE_EXHAUSTED: Python UDF active invocation slots are full") + } + + var releaseOnce sync.Once + release := func() error { + releaseOnce.Do(func() { + <-active + }) + credit.ReleaseUnused() + return nil + } + group, err := protocol.NewExecutionGroup(invocation.Tuple.GroupID, invocation.Tuple.GroupEpoch, 1, release) + if err != nil { + <-active + _ = ledger.Abandon(key) + credit.ReleaseUnused() + g.releaseGroupClaim(groupKey, invocation.Tuple.GroupEpoch) + g.mu.Unlock() + return nil, err + } + token, err := group.BeginOpen(invocation.Tuple.InvocationID) + if err != nil { + _ = group.Close(protocol.ReasonPartialOpenError) + _ = ledger.Abandon(key) + g.releaseGroupClaim(groupKey, invocation.Tuple.GroupEpoch) + g.mu.Unlock() + return nil, err + } + if err := token.Commit(); err != nil { + _ = group.Close(protocol.ReasonPartialOpenError) + _ = ledger.Abandon(key) + g.releaseGroupClaim(groupKey, invocation.Tuple.GroupEpoch) + g.mu.Unlock() + return nil, err + } + g.mu.Unlock() + return &invocationAdmission{ + gateway: g, + group: group, + credit: credit, + key: key, + groupKey: groupKey, + invocationID: invocation.Tuple.InvocationID, + memberOpen: true, + }, nil +} + +func (g *Gateway) ensureAdmissionState() error { + g.admissionMu.Lock() + defer g.admissionMu.Unlock() + if g.active == nil { + maxActive := g.cfg.MaxActiveInvocations + if maxActive <= 0 { + maxActive = DefaultMaxActiveInvocations + } + g.active = make(chan struct{}, maxActive) + } + if g.ledger == nil { + maxEntries := g.cfg.MaxTerminalEntries + if maxEntries <= 0 { + maxEntries = DefaultMaxTerminalEntries + } + maxBytes := g.cfg.MaxTerminalBytes + if maxBytes <= 0 { + maxBytes = DefaultMaxTerminalBytes + } + ledger, err := protocol.NewTerminalLedger(maxEntries, maxBytes) + if err != nil { + return err + } + g.ledger = ledger + } + if g.ledgerTTL <= 0 { + g.ledgerTTL = g.cfg.TerminalRecordTTL + if g.ledgerTTL <= 0 { + g.ledgerTTL = DefaultTerminalRecordTTL + } + } + if g.admittedGroups == nil { + g.admittedGroups = make(map[string]uint64) + } + if g.closedGroups == nil { + g.closedGroups = make(map[string]uint64) + } + if g.closedGroupLimit <= 0 { + g.closedGroupLimit = g.cfg.MaxTerminalEntries + if g.closedGroupLimit <= 0 { + g.closedGroupLimit = DefaultMaxTerminalEntries + } + } + if g.closedGroupByteLimit <= 0 { + g.closedGroupByteLimit = g.cfg.MaxTerminalBytes + if g.closedGroupByteLimit <= 0 { + g.closedGroupByteLimit = DefaultMaxTerminalBytes + } + } + return nil +} + +func (g *Gateway) claimGroupLocked(groupID string, groupEpoch uint64) error { + if closedEpoch, ok := g.closedGroups[groupID]; ok && groupEpoch <= closedEpoch { + return errutil.WrapfCauseFirst(protocol.ErrDuplicate, "execution group %q epoch %d is already closed", groupID, groupEpoch) + } + if admittedEpoch, ok := g.admittedGroups[groupID]; ok { + return errutil.WrapfCauseFirst(protocol.ErrDuplicate, "execution group %q epoch %d is already admitted", groupID, admittedEpoch) + } + if _, exists := g.closedGroups[groupID]; !exists { + // Reserve the future tombstone while the group is active. Checking only + // closedGroups admits an unbounded number of concurrent groups between + // two completions and can overflow the bounded fence ledger when they + // drain together. + if len(g.closedGroups)+len(g.admittedGroups) >= g.closedGroupLimit || + g.closedGroupBytes+g.reservedGroupBytes+int64(len(groupID)+8) > g.closedGroupByteLimit { + return errutil.WrapfCauseFirst(protocol.ErrLedgerFull, "Python UDF closed-group fence is full") + } + g.reservedGroupBytes += int64(len(groupID) + 8) + } + g.admittedGroups[groupID] = groupEpoch + return nil +} + +func (g *Gateway) releaseGroupClaim(groupID string, groupEpoch uint64) { + g.admissionMu.Lock() + if admittedEpoch, ok := g.admittedGroups[groupID]; ok && admittedEpoch == groupEpoch { + delete(g.admittedGroups, groupID) + if _, closed := g.closedGroups[groupID]; !closed { + g.reservedGroupBytes -= int64(len(groupID) + 8) + } + } + g.admissionMu.Unlock() +} + +func (g *Gateway) closeGroupEpoch(groupID string, groupEpoch uint64) { + g.admissionMu.Lock() + if admittedEpoch, ok := g.admittedGroups[groupID]; ok && admittedEpoch == groupEpoch { + delete(g.admittedGroups, groupID) + if _, closed := g.closedGroups[groupID]; !closed { + g.reservedGroupBytes -= int64(len(groupID) + 8) + } + } + if closedEpoch := g.closedGroups[groupID]; groupEpoch > closedEpoch { + g.closedGroups[groupID] = groupEpoch + if closedEpoch == 0 { + g.closedGroupBytes += int64(len(groupID) + 8) + } + } + g.admissionMu.Unlock() +} + +func (g *Gateway) epochClosed(groupID string, groupEpoch uint64) bool { + g.admissionMu.Lock() + defer g.admissionMu.Unlock() + closedEpoch, ok := g.closedGroups[groupID] + return ok && groupEpoch <= closedEpoch +} + +// scopedGroupKey is an internal ownership key. The wire protocol keeps the +// original group id, but group reservations and terminal fences are scoped by +// account because the tuple identity is {account_id, group_id, group_epoch}. +func scopedGroupKey(accountID uint64, groupID string) string { + return strconv.FormatUint(accountID, 10) + "\x00" + groupID +} + +func invocationLedgerKey(tuple protocol.FencingTuple) (string, error) { + wire, err := json.Marshal(tuple) + if err != nil { + return "", errutil.Wrapf(err, "python udf: encode invocation identity") + } + digest := sha256.Sum256(wire) + return hex.EncodeToString(digest[:]), nil +} + +func admissionReason(ctx context.Context, attempted bool, err error) protocol.CloseReason { + if err == nil { + return protocol.ReasonInputEOF + } + if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) || + (ctx != nil && ctx.Err() != nil) { + return protocol.ReasonCancel + } + if !attempted { + return protocol.ReasonPartialOpenError + } + return protocol.ReasonFailure +} + +func (a *invocationAdmission) finish(attempted bool, reason protocol.CloseReason) error { + if a == nil { + return nil + } + a.mu.Lock() + defer a.mu.Unlock() + if a.finished { + return nil + } + + // The admission owner is normally reached from one defer. A release + // callback can still fail after the terminal protocol state is frozen, so + // perform one bounded retry here before returning. The group and ledger + // operations are idempotent; only the group release callback has meaningful + // retry state. If both attempts fail, leave `finished` false so a higher + // level shutdown/recovery owner can call finish again without losing the + // resources still owned by this admission. + for attempt := 0; attempt < 2; attempt++ { + var errs []error + if attempted { + if err := a.gateway.ledger.Complete(a.key); err != nil && !errors.Is(err, protocol.ErrUnknownIdentity) { + errs = append(errs, err) + } + } else if err := a.gateway.ledger.Abandon(a.key); err != nil && !errors.Is(err, protocol.ErrUnknownIdentity) { + errs = append(errs, err) + } + if a.memberOpen { + if err := a.group.MemberTerminal(a.invocationID); err != nil && !errors.Is(err, protocol.ErrUnknownIdentity) { + errs = append(errs, err) + } + } + if err := a.group.Close(reason); err != nil { + errs = append(errs, err) + } + if a.group.State() == protocol.GroupReleased { + groupKey := a.groupKey + if groupKey == "" { + // Keep manually constructed admission records safe for protocol + // tests; all production admissions set the account-scoped key. + groupKey = a.group.ID() + } + a.gateway.closeGroupEpoch(groupKey, a.group.Epoch()) + } + if err := errors.Join(errs...); err == nil { + a.finished = true + return nil + } else if attempt == 1 { + return err + } + } + return nil +} + +type capabilityRequest struct { + ProtocolVersion int `json:"protocol_version"` +} + +// definitionValidationPayload is a create-time action payload. It is not a +// plan or an invocation envelope: it carries the source only after the +// Gateway has resolved the exact account-scoped artifact digest. +type definitionValidationPayload struct { + AccountID uint64 `json:"account_id"` + Handler string `json:"handler"` + Source string `json:"source"` + Mode string `json:"mode"` + NullPolicy string `json:"null_policy"` + ABIContract string `json:"abi_contract"` + AdapterVersion string `json:"adapter_version"` + SDKVersion string `json:"sdk_version"` + DefinitionSchemaVersion int `json:"definition_schema_version"` + ArtifactDigest string `json:"artifact_digest"` + EnvironmentDigest string `json:"environment_digest"` + DefinitionFingerprint string `json:"definition_fingerprint"` + Args []TypeDescriptor `json:"args"` + Return TypeDescriptor `json:"return"` +} + +type definitionValidationResponse struct { + Status string `json:"status"` + Reason string `json:"reason,omitempty"` + ArtifactDigest string `json:"artifact_digest,omitempty"` + DefinitionFingerprint string `json:"definition_fingerprint,omitempty"` +} + +type capabilityResponse struct { + ProtocolVersion int `json:"protocol_version"` + ABIContract string `json:"abi_contract"` + AdapterVersion string `json:"adapter_version"` + SDKVersion string `json:"sdk_version"` + DefinitionSchemaVersion int `json:"definition_schema_version"` + PlanContractVersion int `json:"plan_contract_version"` + TypeDescriptorContract string `json:"type_descriptor_contract"` + TimezoneDatabaseVersion string `json:"timezone_database_version"` + Modes []string `json:"modes"` + NullPolicies []string `json:"null_policies"` + WindowBatches int `json:"window_batches"` + CumulativeAck bool `json:"cumulative_ack"` + MaxExecutionFrameBytes int64 `json:"max_execution_frame_bytes"` + MaxHandlerProcesses int `json:"max_handler_processes"` + MaxAccountHandlerProcesses int `json:"max_account_handler_processes"` + MaxOwnerHandlerProcesses int `json:"max_owner_handler_processes"` + LeaseEpoch uint64 `json:"lease_epoch"` +} + +// ensureCapabilities is the feature-level readiness gate. It runs once per +// Gateway connection before OpenInvocation, and it caches only a successful +// match. A worker with an unknown or different contract therefore cannot run +// user code, while ordinary SQL remains independent of this client. +type capabilitySnapshot struct { + generation uint64 + response capabilityResponse +} + +type capabilityProbe struct { + generation uint64 + done chan struct{} + cancel context.CancelFunc + snapshot capabilitySnapshot + err error +} + +func (g *Gateway) ensureCapabilities(ctx context.Context, client flight.FlightServiceClient, forceRefresh bool) error { + _, err := g.ensureCapabilitySnapshot(ctx, client, forceRefresh) + return err +} + +// One caller owns the RPC. Joiners wait with their own deadline and cancellation; +// no network operation or wait holds mu. The owner alone retires the probe. +func (g *Gateway) ensureCapabilitySnapshot(ctx context.Context, client flight.FlightServiceClient, forceRefresh bool) (capabilitySnapshot, error) { + ctx, release := g.withLifecycleContext(ctx) + defer release() + ctx, cancel := context.WithTimeout(ctx, g.cfg.RequestTimeout) + defer cancel() + if err := ctx.Err(); err != nil { + return capabilitySnapshot{}, err + } + g.mu.Lock() + if g.closed { + g.mu.Unlock() + return capabilitySnapshot{}, errGatewayClosed + } + if !forceRefresh && g.capabilityReady && g.capability != nil && g.workerLeaseEpoch != 0 { + snapshot := capabilitySnapshot{g.capabilityGeneration, *g.capability} + g.mu.Unlock() + return snapshot, ctx.Err() + } + if p := g.capabilityProbe; p != nil { + g.mu.Unlock() + select { + case <-ctx.Done(): + return capabilitySnapshot{}, ctx.Err() + case <-p.done: + if err := ctx.Err(); err != nil { + return capabilitySnapshot{}, err + } + return p.snapshot, p.err + } + } + g.capabilityGeneration++ + g.capabilityReady, g.workerLeaseEpoch, g.capability = false, 0, nil + p := &capabilityProbe{generation: g.capabilityGeneration, done: make(chan struct{}), cancel: cancel} + g.capabilityProbe = p + g.mu.Unlock() + response, err := readCapabilities(ctx, client) + g.mu.Lock() + if g.closed { + err = errGatewayClosed + } else if p.generation != g.capabilityGeneration { + err = udferr.New("python udf: capability probe invalidated") + } else if ctx.Err() != nil { + err = ctx.Err() + } + if err == nil { + // response is immutable after publication, including its decoded slices. + g.capabilityReady, g.workerLeaseEpoch, g.capability = true, response.LeaseEpoch, response + p.snapshot = capabilitySnapshot{p.generation, *response} + } + p.err = err + g.capabilityProbe = nil + close(p.done) + g.mu.Unlock() + return p.snapshot, p.err +} + +func readCapabilities(ctx context.Context, client flight.FlightServiceClient) (*capabilityResponse, error) { + request, err := json.Marshal(capabilityRequest{ProtocolVersion: protocol.Version}) + if err != nil { + return nil, err + } + stream, err := client.DoAction(ctx, &flight.Action{Type: "GetPythonCapabilities", Body: request}) + if err != nil { + return nil, errutil.Wrapf(err, "python udf: capability handshake") + } + result, err := stream.Recv() + if err != nil { + return nil, errutil.Wrapf(err, "python udf: capability handshake response") + } + if result == nil { + return nil, udferr.Newf("python udf: empty capability handshake response") + } + var response capabilityResponse + decoder := json.NewDecoder(bytes.NewReader(result.Body)) + decoder.DisallowUnknownFields() + if err := decoder.Decode(&response); err != nil { + return nil, errutil.Wrapf(err, "python udf: decode capability handshake") + } + var trailing any + if err := decoder.Decode(&trailing); err != io.EOF { + return nil, udferr.Newf("python udf: capability handshake has trailing JSON") + } + if err := validateCapabilities(response); err != nil { + return nil, err + } + if _, err := stream.Recv(); err != io.EOF { + if err == nil { + return nil, udferr.Newf("python udf: capability handshake returned multiple results") + } + return nil, errutil.Wrapf(err, "python udf: capability handshake stream") + } + return &response, nil +} + +// Invalidating an old execution must not evict a newer worker handshake. Keep a +// cancelled probe in its physical slot until its owner exits, bounding RPCs even +// if the transport is slow to acknowledge cancellation. +func (g *Gateway) invalidateCapabilities(expected ...uint64) { + g.mu.Lock() + if len(expected) != 0 && expected[0] != g.capabilityGeneration { + g.mu.Unlock() + return + } + g.capabilityGeneration++ + g.capabilityReady, g.workerLeaseEpoch, g.capability = false, 0, nil + var cancel context.CancelFunc + if g.capabilityProbe != nil { + cancel = g.capabilityProbe.cancel + } + g.mu.Unlock() + if cancel != nil { + cancel() + } +} + +func validateCapabilities(response capabilityResponse) error { + if response.ProtocolVersion != protocol.Version || + response.ABIContract != udf.PythonABIContract || + response.AdapterVersion != udf.PythonAdapterVersion || + response.SDKVersion != udf.PythonSDKVersion || + response.DefinitionSchemaVersion != udf.PythonDefinitionSchemaVersion || + response.PlanContractVersion != udf.PythonPlanContractVersion || + response.TypeDescriptorContract != udf.PythonTypeDescriptorContract || + response.TimezoneDatabaseVersion != currentTimezoneDatabaseVersion() || + response.WindowBatches != 1 || response.CumulativeAck || + response.MaxExecutionFrameBytes != 1<<30 || + response.MaxHandlerProcesses != DefaultWorkerMaxHandlerProcesses || + response.MaxAccountHandlerProcesses != DefaultWorkerMaxAccountHandlers || + response.MaxOwnerHandlerProcesses != DefaultWorkerMaxOwnerHandlers || + response.LeaseEpoch == 0 { + return udferr.Newf("python udf: worker capability contract does not match the current contract") + } + if !sameStrings(response.Modes, []string{ModeScalar, ModeVector}) || + !sameStrings(response.NullPolicies, []string{NullCallHandler, NullReturnNull}) { + return udferr.Newf("python udf: worker capability set does not match the current contract") + } + return nil +} + +func currentTimezoneDatabaseVersion() string { + version, err := udf.TimezoneDatabaseVersion() + if err != nil { + return "" + } + return version +} + +func sameStrings(actual, expected []string) bool { + if len(actual) != len(expected) { + return false + } + for i := range expected { + if actual[i] != expected[i] { + return false + } + } + return true +} + +func encodeInputBatchWithEncoder(encoder *inputBatchEncoder, start, remaining, maxBytes, maxRows int64) (encodedRecordBatch, error) { + if start < 0 || remaining <= 0 { + return encodedRecordBatch{}, udferr.Newf("invalid Python UDF input batch range") + } + if maxRows <= 0 { + return encodedRecordBatch{}, udferr.Newf("invalid Python UDF max batch rows") + } + if remaining > maxRows { + remaining = maxRows + } + // Fixed-width input records can be materialized once at the bounded row + // limit and sliced for each size probe. This removes repeated Arrow builder + // work without assuming anything about variable-length SQL values. The + // slice keeps the same backing buffers, and every candidate is still encoded + // and checked against maxBytes before publication. + if encoder == nil { + return encodedRecordBatch{}, udferr.Newf("invalid Python UDF input encoder") + } + if encoder.fixedWidth { + record, _, err := encoder.build(int(start), int(remaining)) + if err != nil { + return encodedRecordBatch{}, err + } + defer record.Release() + tryEncode := func(rows int64) ([]ArrowFrame, error) { + candidate := record.NewSlice(0, rows) + defer candidate.Release() + return encoder.encode(candidate, maxBytes) + } + // The full fixed-width record is already materialized under the + // invocation's bounded input range. Try publishing it once before the + // size search; the normal SQL batch fits in the limit and avoids a + // logarithmic series of identical IPC encodes. + return chooseInputBatchWithFullCandidate(remaining, maxBytes, tryEncode, true) + } + tryEncode := func(rows int64) ([]ArrowFrame, error) { + record, _, err := encoder.build(int(start), int(rows)) + if err != nil { + return nil, err + } + frames, encodeErr := encoder.encode(record, maxBytes) + record.Release() + return frames, encodeErr + } + return chooseInputBatchWithFullCandidate( + remaining, maxBytes, tryEncode, + encoder.canBuildFullBatch(start, remaining, maxBytes), + ) +} + +func chooseInputBatch(remaining, maxBytes int64, tryEncode func(int64) ([]ArrowFrame, error)) (encodedRecordBatch, error) { + return chooseInputBatchWithFullCandidate(remaining, maxBytes, tryEncode, false) +} + +func chooseInputBatchWithFullCandidate(remaining, maxBytes int64, tryEncode func(int64) ([]ArrowFrame, error), tryFull bool) (encodedRecordBatch, error) { + if tryFull { + frames, err := tryEncode(remaining) + if err == nil { + return encodedRecordBatch{Frames: frames, Rows: remaining}, nil + } + if !errors.Is(err, errArrowBatchTooLarge) { + return encodedRecordBatch{}, err + } + } + best, probe := int64(0), int64(1) + var bestFrames []ArrowFrame + failedAt := int64(0) + for { + frames, err := tryEncode(probe) + if err == nil { + best, bestFrames = probe, frames + if probe == remaining { + return encodedRecordBatch{Frames: bestFrames, Rows: best}, nil + } + if probe > remaining/2 { + probe = remaining + } else { + probe *= 2 + } + continue + } + if !errors.Is(err, errArrowBatchTooLarge) { + return encodedRecordBatch{}, err + } + failedAt = probe + break + } + low, high := best+1, failedAt-1 + for low <= high { + middle := low + (high-low)/2 + frames, err := tryEncode(middle) + if err == nil { + best, bestFrames = middle, frames + low = middle + 1 + continue + } + if !errors.Is(err, errArrowBatchTooLarge) { + return encodedRecordBatch{}, err + } + high = middle - 1 + } + if best == 0 { + return encodedRecordBatch{}, errutil.WrapfCauseFirst(errArrowBatchTooLarge, "one Arrow row exceeds %d bytes", maxBytes) + } + return encodedRecordBatch{Frames: bestFrames, Rows: best}, nil +} + +func (g *Gateway) receiveResultBatch( + ctx context.Context, + client flight.FlightServiceClient, + stream flight.FlightService_DoExchangeClient, + tuple protocol.FencingTuple, + sequenceNumber uint64, + expectedRows int64, + schemaFrame **ArrowFrame, + schemaReady *bool, + returnDescriptor TypeDescriptor, + result vector.FunctionResultWrapper, + mp *mpool.MPool, + sequence *protocol.Sequence, +) (int, error) { + inputConsumed := false + for { + data, err := stream.Recv() + if err != nil { + if err == io.EOF { + return 0, udferr.Newf("python udf: exchange ended before result sequence %d", sequenceNumber) + } + return 0, errutil.Wrapf(err, "python udf: receive result") + } + if data == nil || (len(data.AppMetadata) == 0 && len(data.DataHeader) == 0) { + return 0, udferr.Newf("python udf: empty Flight result") + } + if len(data.DataHeader) > 0 { + if *schemaFrame == nil { + if len(data.DataBody) != 0 { + return 0, udferr.Newf("python udf: result schema contains a body") + } + *schemaFrame = &ArrowFrame{Header: append([]byte(nil), data.DataHeader...)} + if len(data.AppMetadata) != 0 { + if err := validateResultSchemaMetadata(data.AppMetadata, tuple); err != nil { + return 0, err + } + *schemaReady = true + } + continue + } + if !*schemaReady { + return 0, udferr.Newf("python udf: result schema metadata was not received") + } + control, err := protocol.UnmarshalControl(data.AppMetadata) + if err != nil { + return 0, err + } + if control.Tuple != tuple || control.Kind != "ResultBatch" || control.Sequence != sequenceNumber { + return 0, udferr.Newf("python udf: unexpected result sequence %d", control.Sequence) + } + if !inputConsumed { + return 0, udferr.Newf("python udf: result sequence %d arrived before InputConsumed", sequenceNumber) + } + if err := sequence.AcceptResult(control.Sequence); err != nil { + return 0, err + } + headerSnapshot, bodySnapshot, err := freezeResultFrames( + data.DataHeader, + data.DataBody, + g.cfg.MaxBatchBytes, + ) + if err != nil { + return 0, err + } + // Both Flight buffers are now private snapshots. DecodeRecordBatch + // consumes exactly those validated backings; no later mutation of the + // received FlightData can change the bytes that crossed the trusted + // validation/publication boundary. + decoded, err := DecodeRecordBatch(**schemaFrame, ArrowFrame{Header: headerSnapshot.TrustedBytes(), Body: bodySnapshot.TrustedBytes()}, g.cfg.MaxBatchBytes) + if err != nil { + return 0, errutil.Wrapf(err, "python udf: decode result") + } + decodedRows := decoded.NumRows() + if decoded.NumCols() != 1 || decodedRows <= 0 || decodedRows != expectedRows { + decoded.Release() + return 0, udferr.Newf("python udf: result batch row count %d, expected %d", decodedRows, expectedRows) + } + if decoded.Schema().Field(0).Name != "result" { + decoded.Release() + return 0, udferr.Newf("python udf: result field has unexpected name %q", decoded.Schema().Field(0).Name) + } + if err := returnDescriptor.ValidateField(decoded.Schema().Field(0)); err != nil { + decoded.Release() + return 0, err + } + if err := AppendArrowResult(returnDescriptor, decoded.Column(0), result, mp); err != nil { + decoded.Release() + return 0, err + } + if limit := g.cfg.MaxInvocationResultBytes; limit > 0 && result.GetResultVector() != nil && int64(result.GetResultVector().Size()) > limit { + decoded.Release() + return 0, udferr.Newf("RESOURCE_EXHAUSTED: Python UDF invocation result exceeds %d bytes", limit) + } + decoded.Release() + if err := g.action(ctx, client, "AcknowledgeResults", protocol.Control{Kind: "AcknowledgeResults", Tuple: tuple, AckSequence: control.Sequence}); err != nil { + return 0, err + } + if err := sequence.AcknowledgeResults(control.Sequence); err != nil { + return 0, err + } + return int(expectedRows), nil + } + if len(data.DataBody) != 0 { + return 0, udferr.Newf("python udf: control frame contains an Arrow body") + } + control, err := protocol.UnmarshalControl(data.AppMetadata) + if err != nil { + return 0, err + } + if control.Tuple != tuple { + return 0, udferr.Newf("python udf: result tuple changed") + } + switch control.Kind { + case "ResultSchema": + if *schemaFrame == nil || *schemaReady { + return 0, udferr.Newf("python udf: invalid result schema metadata") + } + *schemaReady = true + continue + case "InputConsumed": + if control.Sequence != sequenceNumber { + return 0, udferr.Newf("python udf: input sequence %d was consumed while waiting for result %d", control.Sequence, sequenceNumber) + } + if control.ReleasedBatches != 1 || control.ReleasedBytes <= 0 || control.ReleasedBytes > g.cfg.MaxBatchBytes { + return 0, udferr.Newf("python udf: input sequence %d released invalid bytes/batches (%d/%d)", sequenceNumber, control.ReleasedBytes, control.ReleasedBatches) + } + if inputConsumed { + return 0, udferr.Newf("python udf: input sequence %d was consumed more than once", sequenceNumber) + } + inputConsumed = true + continue + case "Error": + return 0, udferr.Newf("python udf: worker error: %s", control.Reason) + case "Finish": + return 0, udferr.Newf("python udf: Finish arrived before result sequence %d", sequenceNumber) + default: + return 0, udferr.Newf("python udf: unexpected control %q", control.Kind) + } + } +} + +// freezeResultFrames takes ownership of both IPC pieces before either one is +// validated or decoded. MaxBatchBytes describes the complete per-batch +// payload, including the record message header and body; otherwise a large +// header could bypass the body-only limit used by the old result path. +func freezeResultFrames(header, body []byte, maxBytes int64) (*protocol.OutputSnapshot, *protocol.OutputSnapshot, error) { + if maxBytes <= 0 { + return nil, nil, udferr.Newf("invalid Python UDF result batch limit") + } + headerBytes := int64(len(header)) + bodyBytes := int64(len(body)) + if headerBytes > maxBytes || bodyBytes > maxBytes-headerBytes { + return nil, nil, udferr.Newf("RESOURCE_EXHAUSTED: Arrow result batch exceeds %d bytes", maxBytes) + } + headerSnapshot, err := protocol.FreezeOutput(header, maxBytes) + if err != nil { + return nil, nil, err + } + bodySnapshot, err := protocol.FreezeOutput(body, maxBytes) + if err != nil { + return nil, nil, err + } + if err := headerSnapshot.Validate(len(header), headerSnapshot.Digest()); err != nil { + return nil, nil, err + } + if err := bodySnapshot.Validate(len(body), bodySnapshot.Digest()); err != nil { + return nil, nil, err + } + return headerSnapshot, bodySnapshot, nil +} + +type executionBudget struct { + rows int64 + maxRows int64 + returnType types.Type + maxResultBytes int64 +} + +func validateInvocationBudget(budget executionBudget) error { + if budget.rows < 0 { + return udferr.Newf("python udf: invocation row count is negative") + } + if budget.maxRows > 0 && budget.rows > budget.maxRows { + return udferr.Newf("RESOURCE_EXHAUSTED: Python UDF invocation has %d rows, limit is %d", budget.rows, budget.maxRows) + } + if budget.maxResultBytes <= 0 || budget.rows == 0 { + return nil + } + // PreExtendAndReset allocates the fixed-width payload and the validity + // domain before the first result arrives. Check that unavoidable portion + // before OpenInvocation; variable-width payloads are checked again after + // each validated append because their area size depends on user values. + validityBytes := (budget.rows-1)/8 + 1 + if validityBytes >= budget.maxResultBytes { + return udferr.Newf("RESOURCE_EXHAUSTED: Python UDF invocation result reservation exceeds %d bytes", budget.maxResultBytes) + } + perRow := int64(budget.returnType.TypeSize()) + if perRow > 0 && budget.rows > (budget.maxResultBytes-validityBytes)/perRow { + return udferr.Newf("RESOURCE_EXHAUSTED: Python UDF invocation result reservation exceeds %d bytes", budget.maxResultBytes) + } + return nil +} + +func validateResultSchemaMetadata(metadata []byte, tuple protocol.FencingTuple) error { + control, err := protocol.UnmarshalControl(metadata) + if err != nil || control.Tuple != tuple || control.Kind != "ResultSchema" { + return udferr.Newf("python udf: invalid result schema metadata") + } + return nil +} + +func (g *Gateway) receiveFinish( + ctx context.Context, + client flight.FlightServiceClient, + stream flight.FlightService_DoExchangeClient, + tuple protocol.FencingTuple, + expectedRows, rows int, + sequence *protocol.Sequence, +) error { + for { + data, err := stream.Recv() + if err != nil { + if err == io.EOF { + return udferr.Newf("python udf: exchange ended before Finish") + } + return errutil.Wrapf(err, "python udf: receive Finish") + } + if data == nil || len(data.DataHeader) > 0 || len(data.DataBody) > 0 { + return udferr.Newf("python udf: unexpected Arrow data while finishing") + } + control, err := protocol.UnmarshalControl(data.AppMetadata) + if err != nil { + return err + } + if control.Tuple != tuple { + return udferr.Newf("python udf: Finish tuple changed") + } + switch control.Kind { + case "InputConsumed", "ResultSchema": + return udferr.Newf("python udf: %s arrived after result stream was drained", control.Kind) + case "Error": + return udferr.Newf("python udf: worker error: %s", control.Reason) + case "Finish": + lastInput, lastResult, acked, inputEnded := sequence.State() + if control.Status != statusOK || control.FinishID == "" || rows != expectedRows || + !inputEnded || control.LastSequence != lastInput || lastResult != lastInput || acked != lastInput || !sequence.ReadyToFinish() { + return udferr.Newf("python udf: invalid Finish status=%q rows=%d", control.Status, rows) + } + if control.LastResultSequence != lastResult { + return udferr.Newf("python udf: invalid Finish result sequence %d, expected %d", control.LastResultSequence, lastResult) + } + if err := g.acknowledgeFinish(ctx, client, "AcknowledgeFinish", protocol.Control{Kind: "AcknowledgeFinish", Tuple: tuple, FinishID: control.FinishID}); err != nil { + return err + } + // AcknowledgeFinish is accepted by the worker's action RPC before + // the DoExchange callback runs its finally block. The callback owns + // the input reader, handler process, and worker group fence, so the + // action ACK alone is not a safe re-entry boundary. Wait for the + // exchange to reach EOF; Flight reports EOF only after the callback + // has returned and its cleanup owner has completed. + return g.waitExchangeEOF(ctx, stream) + default: + return udferr.Newf("python udf: unexpected control %q", control.Kind) + } + } +} + +func (g *Gateway) waitExchangeEOF(ctx context.Context, stream flight.FlightService_DoExchangeClient) error { + for { + data, err := stream.Recv() + if err == io.EOF { + return nil + } + if err != nil { + return errutil.Wrapf(err, "python udf: wait for exchange completion") + } + if data == nil || len(data.DataHeader) != 0 || len(data.DataBody) != 0 || len(data.AppMetadata) != 0 { + return udferr.Newf("python udf: exchange returned data after Finish ACK") + } + } +} + +// acknowledgeFinish retries only the idempotent terminal ACK. A lost ACK +// request or response must not replay any STARTED input or handler work. +// Once the request budget is exhausted the caller preserves the distinction +// between an accepted terminal result and a locally unconfirmed Finish. +func (g *Gateway) acknowledgeFinish(ctx context.Context, client flight.FlightServiceClient, kind string, finish protocol.Control) error { + if client == nil { + return udferr.Newf("FINISH_UNCONFIRMED: finish ACK client is unavailable") + } + firstErr := g.action(ctx, client, kind, finish) + if firstErr == nil { + return nil + } + if ctx != nil && ctx.Err() != nil { + return errutil.Wrapf(firstErr, "FINISH_UNCONFIRMED: finish ACK budget expired") + } + if retryErr := g.action(ctx, client, kind, finish); retryErr == nil { + return nil + } else { + return errutil.Wrapf(retryErr, "FINISH_UNCONFIRMED: finish ACK was not confirmed after idempotent retry: %v; retry", firstErr) + } +} + +func validateInvocation(invocation *udf.Invocation) error { + if err := validateInvocationHeader(invocation); err != nil { + return err + } + if invocation.Source == "" { + return udferr.Newf("python udf: handler and source are required") + } + // ArtifactResolver is an execution boundary, so the Gateway must enforce + // the same immutable source contract even when a custom resolver does not + // use FileArtifactStore. Do this before hashing or building the Open frame; + // otherwise an oversized or invalid source can consume a large temporary + // allocation and only fail at the Flight control-size boundary. + if !utf8.ValidString(invocation.Source) { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python artifact source is not valid UTF-8") + } + if int64(len([]byte(invocation.Source))) > DefaultMaxArtifactBytes { + return udferr.Newf("RESOURCE_EXHAUSTED: Python artifact exceeds %d bytes", DefaultMaxArtifactBytes) + } + if invocation.ArtifactDigest != udf.PythonInlineArtifactDigest(invocation.Handler, invocation.Source) { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python artifact digest does not match the immutable source") + } + return nil +} + +// validateInvocationHeader checks every field that is independent of the +// artifact bytes. The CN must run this before an account-scoped artifact +// lookup; otherwise a malformed plan could make the resolver inspect an +// arbitrary tenant path before its FunctionRef and fencing tuple are known to +// be valid. +func validateInvocationHeader(invocation *udf.Invocation) error { + if invocation == nil { + return udferr.Newf("python udf: nil invocation") + } + if invocation.Language != udf.LanguagePython { + return udferr.Newf("python udf: unsupported language %q", invocation.Language) + } + if invocation.Handler == "" { + return udferr.Newf("python udf: handler is required") + } + if strings.Contains(invocation.Handler, ":") { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python external handler import requires an immutable artifact catalog") + } + if invocation.Length < 0 || len(invocation.Args) != len(invocation.Inputs) { + return udferr.Newf("python udf: invalid input shape") + } + if invocation.Mode != ModeScalar && invocation.Mode != ModeVector { + return udferr.Newf("python udf: unsupported mode %q", invocation.Mode) + } + if invocation.CallsiteID == "" || len(invocation.CallsiteID) > 256 || strings.ContainsAny(invocation.CallsiteID, "\r\n") { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python invocation has no valid callsite id") + } + if !invocation.MayError || invocation.SecurityMode != "INVOKER" || invocation.Leakproof { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python invocation semantic contract is not supported") + } + if invocation.StatementContext == nil { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python invocation has no statement context") + } + if err := invocation.StatementContext.Validate(); err != nil { + return err + } + if invocation.SecurityFrame == nil { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python invocation has no security frame") + } + if err := invocation.SecurityFrame.Validate(); err != nil { + return err + } + if invocation.SecurityFrame.Mode != invocation.SecurityMode { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python invocation security mode does not match its frame") + } + if invocation.NullPolicy != NullCallHandler && invocation.NullPolicy != NullReturnNull { + return udferr.Newf("python udf: unsupported NULL policy %q", invocation.NullPolicy) + } + if invocation.ABIContract != udf.PythonABIContract || invocation.AdapterVersion != udf.PythonAdapterVersion { + return udferr.Newf("python udf: unsupported Python ABI contract %q/%q", invocation.ABIContract, invocation.AdapterVersion) + } + if invocation.SDKVersion != udf.PythonSDKVersion { + return udferr.Newf("python udf: unsupported Python SDK %q", invocation.SDKVersion) + } + if invocation.DefinitionSchemaVersion != udf.PythonDefinitionSchemaVersion { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: unsupported Python definition schema %d", invocation.DefinitionSchemaVersion) + } + if !udf.IsSHA256Digest(invocation.ArtifactDigest) { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python artifact digest does not match the immutable source") + } + environmentDigest, err := udf.PythonEnvironmentDigest() + if err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: Python environment digest is unavailable") + } + if invocation.EnvironmentDigest != environmentDigest { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python environment digest does not match the current worker contract") + } + if !udf.IsSHA256Digest(invocation.DefinitionFingerprint) { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python definition fingerprint is invalid") + } + args := make([]TypeDescriptor, len(invocation.Args)) + for index, typ := range invocation.Args { + descriptor, err := NewTypeDescriptor(typ) + if err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: Python argument descriptor %d", index) + } + args[index] = descriptor + } + returnDescriptor, err := NewTypeDescriptor(invocation.ReturnType) + if err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: Python return descriptor") + } + if err := validateInvocationInputs(invocation, args); err != nil { + return err + } + expectedFingerprint, err := DefinitionFingerprint( + invocation.DefinitionSchemaVersion, + invocation.Handler, invocation.Mode, invocation.NullPolicy, + invocation.ABIContract, invocation.AdapterVersion, + invocation.ArtifactDigest, invocation.EnvironmentDigest, invocation.SDKVersion, + args, returnDescriptor, + ) + if err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION: Python definition fingerprint cannot be computed") + } + if invocation.DefinitionFingerprint != expectedFingerprint { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python definition fingerprint does not match the typed definition") + } + if err := invocation.FunctionRef.Validate(); err != nil { + return errutil.Wrapf(err, "UNSUPPORTED_ROUTINE_VERSION") + } + if invocation.FunctionRef.AccountID != invocation.Tuple.AccountID { + return udferr.Newf("python udf: FunctionRef account does not match the fencing tuple") + } + return invocation.Tuple.Validate() +} + +func validateInvocationInputs(invocation *udf.Invocation, args []TypeDescriptor) error { + if invocation == nil || len(invocation.Inputs) != len(args) { + return udferr.Newf("python udf: invalid input shape") + } + // An empty physical selection has no input backing to inspect. Nil inputs + // are valid in this case, but a vector supplied by a caller still has to + // match the frozen descriptor. Otherwise a zero-row invocation could + // bypass the same type boundary enforced for non-empty execution. + if invocation.Length == 0 { + for index, input := range invocation.Inputs { + if input == nil { + continue + } + if input.GetType() == nil || !input.GetType().Eq(invocation.Args[index]) { + return udferr.Newf("python udf: input column %d type does not match the frozen argument type", index) + } + } + return nil + } + for index, input := range invocation.Inputs { + if input == nil || input.GetType() == nil || input.Length() == 0 { + return udferr.Newf("python udf: input column %d has no backing vector", index) + } + if !input.GetType().Eq(invocation.Args[index]) { + return udferr.Newf("python udf: input column %d type %s does not match the frozen argument type %s", index, input.GetType().DescString(), invocation.Args[index].DescString()) + } + if !input.IsConst() && input.Length() < invocation.Length { + return udferr.Newf("python udf: input column %d has %d rows, expected at least %d", index, input.Length(), invocation.Length) + } + } + return nil +} + +func (g *Gateway) action(ctx context.Context, client flight.FlightServiceClient, kind string, control protocol.Control) error { + body, err := protocol.MarshalControl(control) + if err != nil { + return err + } + actionCtx, cancel := context.WithTimeout(ctx, g.cfg.RequestTimeout) + defer cancel() + stream, err := client.DoAction(actionCtx, &flight.Action{Type: kind, Body: body}) + if err != nil { + return errutil.Wrapf(err, "python udf: %s", kind) + } + result, err := stream.Recv() + if err != nil { + return err + } + if result == nil { + return udferr.Newf("python udf: empty %s response", kind) + } + ack, err := protocol.UnmarshalControl(result.Body) + if err != nil { + return err + } + if err := validateActionAck(kind, control, ack); err != nil { + return err + } + if ack.Status != statusOK { + return udferr.Newf("python udf: %s rejected: %s", kind, ack.Reason) + } + if _, err := stream.Recv(); err != io.EOF { + if err == nil { + return udferr.Newf("python udf: %s returned multiple results", kind) + } + return err + } + return nil +} + +func validateActionAck(kind string, request, ack protocol.Control) error { + if ack.Tuple != request.Tuple || ack.Kind != "Ack" { + return udferr.Newf("python udf: %s returned an invalid ACK", kind) + } + switch kind { + case "AcknowledgeResults": + if ack.AckSequence != request.AckSequence { + return udferr.Newf("python udf: %s ACK sequence %d, expected %d", kind, ack.AckSequence, request.AckSequence) + } + case "AcknowledgeFinish": + if ack.FinishID != request.FinishID { + return udferr.Newf("python udf: %s ACK finish ID does not match the request", kind) + } + default: + return udferr.Newf("python udf: unsupported action %q", kind) + } + return nil +} + +func cloneMap(input map[string]string) map[string]string { + if len(input) == 0 { + return nil + } + out := make(map[string]string, len(input)) + for k, v := range input { + out[k] = v + } + return out +} diff --git a/pkg/udf/python/gateway_admission_test.go b/pkg/udf/python/gateway_admission_test.go new file mode 100644 index 0000000000000..fd4d96e5e63d5 --- /dev/null +++ b/pkg/udf/python/gateway_admission_test.go @@ -0,0 +1,251 @@ +// Copyright 2026 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 python + +import ( + "errors" + "testing" + "time" + + "github.com/matrixorigin/matrixone/pkg/udf/protocol" + "github.com/stretchr/testify/require" +) + +func newAdmissionTestGateway(t *testing.T, maxActive int) *Gateway { + t.Helper() + gateway, err := NewGateway(ClientConfig{ + Enabled: true, + AllowUnisolated: true, + ServerAddress: "127.0.0.1:1", + MaxActiveInvocations: maxActive, + MaxTerminalEntries: 8, + MaxTerminalBytes: 1 << 20, + TerminalRecordTTL: time.Minute, + }) + require.NoError(t, err) + return gateway +} + +func TestGatewayAdmissionFencesDuplicateAndReleasesOnce(t *testing.T) { + gateway := newAdmissionTestGateway(t, 1) + in := validInvocation() + admission, err := gateway.admitInvocation(in) + require.NoError(t, err) + registered, active, inFlight := admission.group.Counts() + require.Equal(t, 1, registered) + require.Equal(t, 1, active) + require.Equal(t, 0, inFlight) + + _, err = gateway.admitInvocation(in) + require.ErrorIs(t, err, protocol.ErrDuplicate) + entries, _ := gateway.ledger.Counts() + require.Equal(t, 1, entries) + require.Len(t, gateway.active, 1) + + require.NoError(t, admission.finish(true, protocol.ReasonInputEOF)) + require.NoError(t, admission.finish(true, protocol.ReasonInputEOF)) + entries, _ = gateway.ledger.Counts() + require.Equal(t, 1, entries, "accepted execution keeps its tombstone") + require.Len(t, gateway.active, 0, "group owner releases K exactly once") + require.Equal(t, protocol.GroupReleased, admission.group.State()) + _, err = gateway.admitInvocation(in) + require.ErrorIs(t, err, protocol.ErrDuplicate) +} + +func TestGatewayAdmissionRejectsAfterClose(t *testing.T) { + gateway := newAdmissionTestGateway(t, 1) + require.NoError(t, gateway.Close()) + + _, err := gateway.admitInvocation(validInvocation()) + require.ErrorIs(t, err, errGatewayClosed) + if gateway.ledger != nil { + entries, _ := gateway.ledger.Counts() + require.Zero(t, entries) + } + require.Len(t, gateway.active, 0) +} + +func TestGatewayAdmissionRejectsAtKWithoutLeavingLedgerEntry(t *testing.T) { + gateway := newAdmissionTestGateway(t, 1) + first := validInvocation() + firstAdmission, err := gateway.admitInvocation(first) + require.NoError(t, err) + + second := validInvocation() + second.Tuple.GroupID = "second-group" + second.Tuple.InvocationID = "second-invocation" + _, err = gateway.admitInvocation(second) + require.ErrorContains(t, err, "active invocation slots are full") + entries, _ := gateway.ledger.Counts() + require.Equal(t, 1, entries, "K rejection abandons the speculative ledger entry") + require.Len(t, gateway.active, 1) + + require.NoError(t, firstAdmission.finish(true, protocol.ReasonFailure)) + secondAdmission, err := gateway.admitInvocation(second) + require.NoError(t, err) + require.NoError(t, secondAdmission.finish(false, protocol.ReasonPartialOpenError)) + entries, _ = gateway.ledger.Counts() + require.Equal(t, 1, entries, "a pre-send failure abandons instead of tombstoning") + require.Len(t, gateway.active, 0) +} + +func TestGatewayAdmissionReclaimsOnlyClosedEpochTombstones(t *testing.T) { + gateway := newAdmissionTestGateway(t, 1) + gateway.cfg.MaxTerminalEntries = 1 + gateway.ledgerTTL = time.Nanosecond + first := validInvocation() + first.Tuple.GroupID = "reclaim-first" + first.Tuple.InvocationID = "reclaim-first-invocation" + firstAdmission, err := gateway.admitInvocation(first) + require.NoError(t, err) + require.NoError(t, firstAdmission.finish(true, protocol.ReasonInputEOF)) + entries, _ := gateway.ledger.Counts() + require.Equal(t, 1, entries) + gateway.ledgerTTL = time.Nanosecond + + replay := validInvocation() + replay.Tuple.GroupID = first.Tuple.GroupID + replay.Tuple.InvocationID = "reclaim-replay" + _, err = gateway.admitInvocation(replay) + require.ErrorIs(t, err, protocol.ErrDuplicate, "a closed group epoch remains fenced after its TTL") + + second := validInvocation() + second.Tuple.GroupID = "reclaim-second" + second.Tuple.InvocationID = "reclaim-second-invocation" + secondAdmission, err := gateway.admitInvocation(second) + require.NoError(t, err, "an owner-closed tombstone can release bounded ledger capacity") + require.NoError(t, secondAdmission.finish(false, protocol.ReasonPartialOpenError)) + entries, _ = gateway.ledger.Counts() + require.Zero(t, entries) +} + +func TestGatewayAdmissionAcceptedSendIsTerminalOnTransportFailure(t *testing.T) { + gateway := newAdmissionTestGateway(t, 1) + in := validInvocation() + admission, err := gateway.admitInvocation(in) + require.NoError(t, err) + require.NoError(t, admission.finish(true, protocol.ReasonFailure)) + _, err = gateway.admitInvocation(in) + require.Error(t, err) + require.True(t, errors.Is(err, protocol.ErrDuplicate)) + require.Len(t, gateway.active, 0) +} + +func TestGatewayAdmissionRetriesOwnerCleanupAfterGroupReleaseFailure(t *testing.T) { + gateway := newAdmissionTestGateway(t, 1) + require.NoError(t, gateway.ensureAdmissionState()) + + var releaseAttempts int + group, err := protocol.NewExecutionGroup( + "release-retry", 1, 1, + func() error { + releaseAttempts++ + if releaseAttempts <= 2 { + return errors.New("injected group release failure") + } + return nil + }, + ) + require.NoError(t, err) + token, err := group.BeginOpen("member") + require.NoError(t, err) + require.NoError(t, token.Commit()) + credit, err := gateway.ledger.Reserve("release-retry", 1, 1, 16) + require.NoError(t, err) + require.NoError(t, credit.Add("release-retry-key", 16, time.Now().Add(time.Minute))) + + admission := &invocationAdmission{ + gateway: gateway, group: group, credit: credit, + key: "release-retry-key", groupKey: "release-retry", invocationID: "member", memberOpen: true, + } + require.ErrorContains(t, admission.finish(true, protocol.ReasonFailure), "injected group release failure") + require.Equal(t, protocol.GroupDraining, group.State()) + require.NoError(t, admission.finish(true, protocol.ReasonFailure)) + require.Equal(t, 3, releaseAttempts) + require.Equal(t, protocol.GroupReleased, group.State()) + require.NoError(t, admission.finish(true, protocol.ReasonFailure)) +} + +func TestGatewayAdmissionReservesClosedGroupCapacityWhileActive(t *testing.T) { + gateway := newAdmissionTestGateway(t, 2) + gateway.closedGroupLimit = 1 + gateway.closedGroupByteLimit = 1 << 20 + + first := validInvocation() + first.Tuple.GroupID = "reserved-first" + first.Tuple.InvocationID = "first" + firstAdmission, err := gateway.admitInvocation(first) + require.NoError(t, err) + + second := validInvocation() + second.Tuple.GroupID = "reserved-second" + second.Tuple.InvocationID = "second" + _, err = gateway.admitInvocation(second) + require.ErrorIs(t, err, protocol.ErrLedgerFull) + gateway.admissionMu.Lock() + require.Len(t, gateway.admittedGroups, 1) + require.Positive(t, gateway.reservedGroupBytes) + gateway.admissionMu.Unlock() + + require.NoError(t, firstAdmission.finish(true, protocol.ReasonInputEOF)) + gateway.admissionMu.Lock() + require.Empty(t, gateway.admittedGroups) + require.Zero(t, gateway.reservedGroupBytes) + require.Equal(t, uint64(1), gateway.closedGroups[scopedGroupKey(first.Tuple.AccountID, first.Tuple.GroupID)]) + gateway.admissionMu.Unlock() + + // A new epoch of the same group reuses its already-reserved fence. A + // different group remains rejected until the closed fence is reclaimed by a + // future owner protocol. + reentry := validInvocation() + reentry.Tuple.GroupID = first.Tuple.GroupID + reentry.Tuple.GroupEpoch = 2 + reentry.Tuple.InvocationID = "reentry" + reentryAdmission, err := gateway.admitInvocation(reentry) + require.NoError(t, err) + require.NoError(t, reentryAdmission.finish(false, protocol.ReasonPartialOpenError)) + + _, err = gateway.admitInvocation(second) + require.ErrorIs(t, err, protocol.ErrLedgerFull) +} + +func TestGatewayAdmissionScopesGroupByAccount(t *testing.T) { + gateway := newAdmissionTestGateway(t, 2) + first := validInvocation() + first.Tuple.GroupID = "same-name" + first.Tuple.InvocationID = "account-one" + second := validInvocation() + second.Tuple.AccountID = 2 + second.Tuple.GroupID = first.Tuple.GroupID + second.Tuple.InvocationID = "account-two" + + firstAdmission, err := gateway.admitInvocation(first) + require.NoError(t, err) + secondAdmission, err := gateway.admitInvocation(second) + require.NoError(t, err) + require.Len(t, gateway.active, 2) + + require.NoError(t, firstAdmission.finish(true, protocol.ReasonInputEOF)) + require.Len(t, gateway.active, 1) + gateway.admissionMu.Lock() + require.Equal(t, uint64(1), gateway.closedGroups[scopedGroupKey(1, "same-name")]) + require.NotContains(t, gateway.closedGroups, scopedGroupKey(2, "same-name")) + gateway.admissionMu.Unlock() + + require.NoError(t, secondAdmission.finish(true, protocol.ReasonInputEOF)) + gateway.admissionMu.Lock() + require.Equal(t, uint64(1), gateway.closedGroups[scopedGroupKey(2, "same-name")]) + gateway.admissionMu.Unlock() +} diff --git a/pkg/udf/python/gateway_benchmark_test.go b/pkg/udf/python/gateway_benchmark_test.go new file mode 100644 index 0000000000000..ba245079f8fb3 --- /dev/null +++ b/pkg/udf/python/gateway_benchmark_test.go @@ -0,0 +1,169 @@ +// Copyright 2026 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 python + +import ( + "testing" + + "github.com/matrixorigin/matrixone/pkg/common/mpool" + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/container/vector" +) + +func benchmarkInputVector(b *testing.B, typ types.Type, rows int) (*vector.Vector, *mpool.MPool) { + b.Helper() + mp := mpool.MustNewZeroNoFixed() + input := vector.NewVec(typ) + for row := 0; row < rows; row++ { + var err error + switch typ.Oid { + case types.T_int64: + err = vector.AppendFixed(input, int64(row), false, mp) + case types.T_varchar: + err = vector.AppendBytes(input, []byte("matrixone-python-udf"), false, mp) + default: + b.Fatalf("unsupported benchmark type %s", typ) + } + if err != nil { + input.Free(mp) + mpool.DeleteMPool(mp) + b.Fatal(err) + } + } + return input, mp +} + +func BenchmarkEncodeInputBatchFixedWidth(b *testing.B) { + benchmarkEncodeInputBatch(b, types.T_int64.ToType()) +} + +func BenchmarkEncodeInputBatchFixedWidthRebuildBaseline(b *testing.B) { + const rows = 8192 + input, mp := benchmarkInputVector(b, types.T_int64.ToType(), rows) + defer func() { + input.Free(mp) + mpool.DeleteMPool(mp) + }() + encoder, err := newInputBatchEncoder([]*vector.Vector{input}, []types.Type{types.T_int64.ToType()}) + if err != nil { + b.Fatal(err) + } + defer func() { _ = encoder.close() }() + + b.ReportAllocs() + b.SetBytes(int64(rows)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + batch, err := encodeInputBatchRebuildBaseline( + encoder, + 0, rows, DefaultMaxBatchBytes, rows, + ) + if err != nil { + b.Fatal(err) + } + if batch.Rows != rows || len(batch.Frames) != 2 { + b.Fatalf("unexpected encoded batch rows=%d frames=%d", batch.Rows, len(batch.Frames)) + } + } +} + +func BenchmarkEncodeInputBatchVariableWidth(b *testing.B) { + benchmarkEncodeInputBatch(b, types.New(types.T_varchar, 64, 0)) +} + +func BenchmarkEncodeInputBatchVariableWidthRebuildBaseline(b *testing.B) { + const rows = 8192 + typ := types.New(types.T_varchar, 64, 0) + input, mp := benchmarkInputVector(b, typ, rows) + defer func() { + input.Free(mp) + mpool.DeleteMPool(mp) + }() + encoder, err := newInputBatchEncoder([]*vector.Vector{input}, []types.Type{typ}) + if err != nil { + b.Fatal(err) + } + defer func() { _ = encoder.close() }() + + b.ReportAllocs() + b.SetBytes(int64(rows)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + batch, err := encodeInputBatchRebuildBaseline( + encoder, + 0, rows, DefaultMaxBatchBytes, rows, + ) + if err != nil { + b.Fatal(err) + } + if batch.Rows != rows || len(batch.Frames) != 2 { + b.Fatalf("unexpected encoded batch rows=%d frames=%d", batch.Rows, len(batch.Frames)) + } + } +} + +func benchmarkEncodeInputBatch(b *testing.B, typ types.Type) { + const rows = 8192 + input, mp := benchmarkInputVector(b, typ, rows) + defer func() { + input.Free(mp) + mpool.DeleteMPool(mp) + }() + encoder, err := newInputBatchEncoder([]*vector.Vector{input}, []types.Type{typ}) + if err != nil { + b.Fatal(err) + } + defer func() { _ = encoder.close() }() + + b.ReportAllocs() + b.SetBytes(int64(rows)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + batch, err := encodeInputBatchWithEncoder( + encoder, 0, rows, + DefaultMaxBatchBytes, rows, + ) + if err != nil { + b.Fatal(err) + } + if batch.Rows != rows || len(batch.Frames) != 2 { + b.Fatalf("unexpected encoded batch rows=%d frames=%d", batch.Rows, len(batch.Frames)) + } + } +} + +// encodeInputBatchRebuildBaseline is a benchmark-only reference for repeated +// Arrow record construction. It intentionally rebuilds the record and its +// input encoder for every size probe while sharing the reusable Flight writer +// with production. This measures record construction and probe avoidance +// without counting repeated schema serialization as a second optimization. +func encodeInputBatchRebuildBaseline( + encoder *inputBatchEncoder, + start, remaining, maxBytes, maxRows int64, +) (encodedRecordBatch, error) { + if remaining > maxRows { + remaining = maxRows + } + tryEncode := func(rows int64) ([]ArrowFrame, error) { + record, _, err := BuildInputRecordRange(encoder.inputs, encoder.args, int(start), int(rows)) + if err != nil { + return nil, err + } + frames, encodeErr := encoder.encode(record, maxBytes) + record.Release() + return frames, encodeErr + } + return chooseInputBatch(remaining, maxBytes, tryEncode) +} diff --git a/pkg/udf/python/gateway_integration_test.go b/pkg/udf/python/gateway_integration_test.go new file mode 100644 index 0000000000000..14661b2f88706 --- /dev/null +++ b/pkg/udf/python/gateway_integration_test.go @@ -0,0 +1,885 @@ +// Copyright 2026 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 python + +import ( + "context" + "fmt" + "net" + "os" + "os/exec" + "path/filepath" + "runtime" + "strconv" + "strings" + "sync/atomic" + "syscall" + "testing" + "time" + + "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/defines" + "github.com/matrixorigin/matrixone/pkg/fileservice" + "github.com/matrixorigin/matrixone/pkg/udf" + "github.com/matrixorigin/matrixone/pkg/udf/protocol" + "github.com/stretchr/testify/require" +) + +var realWorkerBenchmarkRun atomic.Uint64 + +func TestGatewayExecutesAgainstRealPythonWorker(t *testing.T) { + python, err := exec.LookPath("python3") + require.NoError(t, err, "python3 is required for the real worker contract test") + workerPath := realWorkerPath(t) + port := freeTCPPort(t) + + cmd := startRealWorker(t, python, workerPath, port) + artifactFS, err := fileservice.NewMemoryFS(defines.SharedFileServiceName, fileservice.DisabledCacheConfig, nil) + require.NoError(t, err) + artifactStore, err := NewFileArtifactStore(artifactFS, DefaultMaxArtifactBytes) + require.NoError(t, err) + + cfg := ClientConfig{ + Enabled: true, + AllowUnisolated: true, + ServerAddress: "127.0.0.1:" + strconv.Itoa(port), + MaxBatchBytes: 1 << 20, + // Keep the integration path deliberately smaller than the input so a + // single Gateway.Execute exercises more than one W=1 batch and the + // bounded handler burst reuse contract. + MaxBatchRows: 2, + MaxActiveInvocations: 2, + RequestTimeout: 5 * time.Second, + MaxTerminalEntries: 32, + MaxTerminalBytes: 1 << 20, + TerminalRecordTTL: time.Minute, + } + gateway, err := NewGatewayWithArtifactStore(cfg, artifactStore) + require.NoError(t, err) + defer func() { + _ = gateway.Close() + stopRealWorker(cmd) + }() + + readyContext, cancel := context.WithTimeout(context.Background(), 5*time.Second) + require.NoError(t, gateway.CheckLanguageReady(readyContext, udf.LanguagePython)) + cancel() + + t.Run("definition validation", func(t *testing.T) { + marker := filepath.Join(t.TempDir(), "executed") + source := fmt.Sprintf( + "from pathlib import Path\nPath(%q).write_text('executed')\ndef add(ctx, value): return value\n", + marker, + ) + valid := integrationInvocationForArgs( + ModeScalar, "add", source, + []types.Type{types.T_int64.ToType()}, nil, 0, + protocol.FencingTuple{AccountID: 1, StatementID: "definition-validation", GroupID: "definition-validation-group", GroupEpoch: 1, InvocationID: "valid", LeaseEpoch: 1}, + ) + publishIntegrationArtifact(t, artifactStore, valid) + definition := routineDefinitionForIntegration(valid) + validationContext, cancel := context.WithTimeout(context.Background(), 5*time.Second) + require.NoError(t, gateway.ValidateDefinition(validationContext, definition)) + cancel() + require.NoFileExists(t, marker, "definition validation executed top-level Python code") + + invalidLanguage := routineDefinitionForIntegration(valid) + invalidLanguage.Language = "" + validationContext, cancel = context.WithTimeout(context.Background(), 5*time.Second) + err = gateway.ValidateDefinition(validationContext, invalidLanguage) + cancel() + require.ErrorContains(t, err, "unsupported UDF language") + + invalid := integrationInvocationForArgs( + ModeScalar, "add", "def add(ctx, value) return value", + []types.Type{types.T_int64.ToType()}, nil, 0, + protocol.FencingTuple{AccountID: 1, StatementID: "definition-validation-invalid", GroupID: "definition-validation-invalid-group", GroupEpoch: 1, InvocationID: "invalid", LeaseEpoch: 1}, + ) + publishIntegrationArtifact(t, artifactStore, invalid) + validationContext, cancel = context.WithTimeout(context.Background(), 5*time.Second) + err := gateway.ValidateDefinition(validationContext, routineDefinitionForIntegration(invalid)) + cancel() + require.ErrorContains(t, err, "USER_CODE: Python syntax error") + }) + + t.Run("scalar", func(t *testing.T) { + input, mp := integrationInput(t, []int64{1, 2, 3}) + defer func() { + input.Free(mp) + mpool.DeleteMPool(mp) + }() + result := vector.NewFunctionResultWrapper(types.T_int64.ToType(), mp) + defer result.Free() + invocation := integrationInvocation(ModeScalar, "def add(ctx, value): return value + 10", input, protocol.FencingTuple{ + AccountID: 1, StatementID: "real-flight-scalar", GroupID: "real-flight-scalar-group", + GroupEpoch: 1, InvocationID: "real-flight-scalar-invocation", LeaseEpoch: 1, + }) + publishIntegrationArtifact(t, artifactStore, invocation) + require.NoError(t, gateway.Execute(context.Background(), invocation, result, mp)) + require.Equal(t, uint64(1), invocation.Tuple.LeaseEpoch, "Gateway must not mutate the caller's tuple when attaching the worker lease") + require.Equal(t, []int64{11, 12, 13}, vector.MustFixedColNoTypeCheck[int64](result.GetResultVector())) + }) + + for _, mode := range []string{ModeScalar, ModeVector} { + t.Run("JSON canonical text/"+mode, func(t *testing.T) { + mp := mpool.MustNewZeroNoFixed() + defer mpool.DeleteMPool(mp) + typ := types.T_json.ToType() + input := vector.NewVec(typ) + defer input.Free(mp) + // ByteJson renders this finite number as 0.000001. Python's + // loads/dumps would rewrite it to 1e-06, violating the shared + // compact-text contract before the handler even runs. + value, err := types.ParseStringToByteJson("0.000001") + require.NoError(t, err) + raw, err := value.Marshal() + require.NoError(t, err) + for _, null := range []bool{false, true, false} { + require.NoError(t, vector.AppendBytes(input, raw, null, mp)) + } + result := vector.NewFunctionResultWrapper(typ, mp) + defer result.Free() + invocation := integrationInvocationForArgs( + mode, "identity", "def identity(ctx, value): return value", + []types.Type{typ}, []*vector.Vector{input}, 3, + protocol.FencingTuple{AccountID: 1, StatementID: "json-" + mode, + GroupID: "json-group-" + mode, GroupEpoch: 1, InvocationID: "json-" + mode, LeaseEpoch: 1}, + ) + invocation.ReturnType = typ + descriptor, err := NewTypeDescriptor(typ) + require.NoError(t, err) + invocation.DefinitionFingerprint, err = DefinitionFingerprint( + invocation.DefinitionSchemaVersion, invocation.Handler, invocation.Mode, + invocation.NullPolicy, invocation.ABIContract, invocation.AdapterVersion, + invocation.ArtifactDigest, invocation.EnvironmentDigest, invocation.SDKVersion, + []TypeDescriptor{descriptor}, descriptor, + ) + require.NoError(t, err) + publishIntegrationArtifact(t, artifactStore, invocation) + require.NoError(t, gateway.Execute(context.Background(), invocation, result, mp)) + output := result.GetResultVector() + require.Equal(t, 3, output.Length()) + require.True(t, output.IsNull(1)) + for _, row := range []int{0, 2} { + require.False(t, output.IsNull(uint64(row))) + require.Equal(t, "0.000001", types.DecodeJson(output.GetBytesAt(row)).String()) + } + }) + } + + t.Run("zero-argument scalar", func(t *testing.T) { + mp := mpool.MustNewZeroNoFixed() + defer mpool.DeleteMPool(mp) + result := vector.NewFunctionResultWrapper(types.T_int64.ToType(), mp) + defer result.Free() + invocation := integrationInvocationForArgs( + ModeScalar, + "add", + "def add(ctx): return 42", + nil, + nil, + 1, + protocol.FencingTuple{ + AccountID: 1, StatementID: "real-flight-zero-arg-scalar", GroupID: "real-flight-zero-arg-scalar-group", + GroupEpoch: 1, InvocationID: "real-flight-zero-arg-scalar-invocation", LeaseEpoch: 1, + }, + ) + publishIntegrationArtifact(t, artifactStore, invocation) + require.NoError(t, gateway.Execute(context.Background(), invocation, result, mp)) + require.Equal(t, []int64{42}, vector.MustFixedColNoTypeCheck[int64](result.GetResultVector())) + }) + + t.Run("vector", func(t *testing.T) { + input, mp := integrationInput(t, []int64{4, 5, 6}) + defer func() { + input.Free(mp) + mpool.DeleteMPool(mp) + }() + result := vector.NewFunctionResultWrapper(types.T_int64.ToType(), mp) + defer result.Free() + invocation := integrationInvocation( + ModeVector, + "import pyarrow as pa\ndef add(ctx, values): return pa.array([value.as_py() + 20 for value in values], type=pa.int64())", + input, + protocol.FencingTuple{ + AccountID: 1, StatementID: "real-flight-vector", GroupID: "real-flight-vector-group", + GroupEpoch: 1, InvocationID: "real-flight-vector-invocation", LeaseEpoch: 1, + }, + ) + publishIntegrationArtifact(t, artifactStore, invocation) + require.NoError(t, gateway.Execute(context.Background(), invocation, result, mp)) + require.Equal(t, []int64{24, 25, 26}, vector.MustFixedColNoTypeCheck[int64](result.GetResultVector())) + }) + + t.Run("zero-argument vector", func(t *testing.T) { + const rows = 4 + resultMP := mpool.MustNewZeroNoFixed() + defer mpool.DeleteMPool(resultMP) + result := vector.NewFunctionResultWrapper(types.T_int64.ToType(), resultMP) + defer result.Free() + source := "import pyarrow as pa\ndef add(ctx): return pa.array([ctx.num_rows] * ctx.num_rows, type=pa.int64())" + invocation := integrationZeroArgVectorInvocation(source, rows, protocol.FencingTuple{ + AccountID: 1, StatementID: "real-flight-zero-arg", GroupID: "real-flight-zero-arg-group", + GroupEpoch: 1, InvocationID: "real-flight-zero-arg-invocation", LeaseEpoch: 1, + }) + publishIntegrationArtifact(t, artifactStore, invocation) + require.NoError(t, gateway.Execute(context.Background(), invocation, result, resultMP)) + // MaxBatchRows is two, so each vector invocation receives the exact + // physical batch shape rather than the total statement length. + require.Equal(t, []int64{2, 2, 2, 2}, vector.MustFixedColNoTypeCheck[int64](result.GetResultVector())) + }) +} + +func TestSupervisorExecutesAgainstRealPythonWorker(t *testing.T) { + python, err := exec.LookPath("python3") + require.NoError(t, err, "python3 is required for the Supervisor integration test") + workerPath := realWorkerPath(t) + port := freeTCPPort(t) + supervisor, err := NewSupervisor(Config{ + Address: "127.0.0.1:" + strconv.Itoa(port), + Path: filepath.Dir(workerPath), + Python: python, + }) + require.NoError(t, err) + require.NoError(t, supervisor.Start()) + workerDone := supervisor.Done() + require.NotNil(t, workerDone) + t.Cleanup(func() { + _ = supervisor.Close() + }) + waitForWorkerPort(t, port) + + artifactFS, err := fileservice.NewMemoryFS(defines.SharedFileServiceName, fileservice.DisabledCacheConfig, nil) + require.NoError(t, err) + artifactStore, err := NewFileArtifactStore(artifactFS, DefaultMaxArtifactBytes) + require.NoError(t, err) + gateway, err := NewGatewayWithArtifactStore(ClientConfig{ + Enabled: true, + AllowUnisolated: true, + ServerAddress: "127.0.0.1:" + strconv.Itoa(port), + MaxBatchBytes: 1 << 20, + MaxBatchRows: 2, + MaxInvocationRows: 32, + MaxInvocationResultBytes: 1 << 20, + MaxActiveInvocations: 1, + RequestTimeout: 5 * time.Second, + MaxTerminalEntries: 16, + MaxTerminalBytes: 1 << 20, + TerminalRecordTTL: time.Minute, + }, artifactStore) + require.NoError(t, err) + defer gateway.Close() + readyContext, cancel := context.WithTimeout(context.Background(), 5*time.Second) + require.NoError(t, gateway.CheckLanguageReady(readyContext, udf.LanguagePython)) + cancel() + + input, mp := integrationInput(t, []int64{5, 6, 7}) + defer func() { + input.Free(mp) + mpool.DeleteMPool(mp) + }() + result := vector.NewFunctionResultWrapper(types.T_int64.ToType(), mp) + defer result.Free() + invocation := integrationInvocation(ModeScalar, "def add(ctx, value): return value + 30", input, protocol.FencingTuple{ + AccountID: 1, StatementID: "supervisor-flight", GroupID: "supervisor-flight-group", + GroupEpoch: 1, InvocationID: "supervisor-flight-invocation", LeaseEpoch: 1, + }) + publishIntegrationArtifact(t, artifactStore, invocation) + require.NoError(t, gateway.Execute(context.Background(), invocation, result, mp)) + require.Equal(t, []int64{35, 36, 37}, vector.MustFixedColNoTypeCheck[int64](result.GetResultVector())) + select { + case <-workerDone: + t.Fatal("Python worker exited during a successful Supervisor integration") + default: + } +} + +func publishIntegrationArtifact(t testing.TB, store *FileArtifactStore, invocation *udf.Invocation) { + t.Helper() + source := invocation.Source + require.NotEmpty(t, source) + _, err := store.Publish(context.Background(), invocation.FunctionRef.AccountID, invocation.Handler, source) + require.NoError(t, err) + invocation.Source = "" +} + +func TestGatewayRejectsThePreviousWorkerLeaseAfterRestart(t *testing.T) { + python, err := exec.LookPath("python3") + require.NoError(t, err, "python3 is required for the real worker contract test") + workerPath := realWorkerPath(t) + port := freeTCPPort(t) + first := startRealWorker(t, python, workerPath, port) + + cfg := ClientConfig{ + Enabled: true, + AllowUnisolated: true, + ServerAddress: "127.0.0.1:" + strconv.Itoa(port), + MaxBatchBytes: 1 << 20, + MaxBatchRows: 1024, + MaxActiveInvocations: 1, + RequestTimeout: 2 * time.Second, + MaxTerminalEntries: 32, + MaxTerminalBytes: 1 << 20, + TerminalRecordTTL: time.Minute, + } + gateway, err := NewGateway(cfg) + require.NoError(t, err) + defer gateway.Close() + readyContext, cancel := context.WithTimeout(context.Background(), 5*time.Second) + require.NoError(t, gateway.CheckLanguageReady(readyContext, udf.LanguagePython)) + cancel() + + stopRealWorker(first) + second := startRealWorker(t, python, workerPath, port) + defer stopRealWorker(second) + + input, mp := integrationInput(t, []int64{9}) + defer func() { + input.Free(mp) + mpool.DeleteMPool(mp) + }() + firstResult := vector.NewFunctionResultWrapper(types.T_int64.ToType(), mp) + defer firstResult.Free() + firstInvocation := integrationInvocation(ModeScalar, "def add(ctx, value): return value + 1", input, protocol.FencingTuple{ + AccountID: 1, StatementID: "restart-statement", GroupID: "restart-group", GroupEpoch: 1, + InvocationID: "restart-invocation", LeaseEpoch: 1, + }) + // The Gateway has a cached lease from the first worker. The second worker + // must reject it before handler admission; the failed invocation is never + // transparently replayed. + require.Error(t, gateway.Execute(context.Background(), firstInvocation, firstResult, mp)) + require.Equal(t, uint64(1), firstInvocation.Tuple.LeaseEpoch) + + secondResult := vector.NewFunctionResultWrapper(types.T_int64.ToType(), mp) + defer secondResult.Free() + secondInvocation := integrationInvocation(ModeScalar, "def add(ctx, value): return value + 1", input, protocol.FencingTuple{ + AccountID: 1, StatementID: "restart-statement", GroupID: "restart-group-2", GroupEpoch: 1, + InvocationID: "restart-invocation-2", LeaseEpoch: 1, + }) + require.NoError(t, gateway.Execute(context.Background(), secondInvocation, secondResult, mp)) + require.Equal(t, []int64{10}, vector.MustFixedColNoTypeCheck[int64](secondResult.GetResultVector())) +} + +func TestGatewayReadinessRefreshesLeaseAfterWorkerRestart(t *testing.T) { + python, err := exec.LookPath("python3") + require.NoError(t, err, "python3 is required for the real worker contract test") + workerPath := realWorkerPath(t) + port := freeTCPPort(t) + first := startRealWorker(t, python, workerPath, port) + + gateway, err := NewGateway(ClientConfig{ + Enabled: true, + AllowUnisolated: true, + ServerAddress: "127.0.0.1:" + strconv.Itoa(port), + MaxBatchBytes: 1 << 20, + MaxBatchRows: 1024, + MaxActiveInvocations: 1, + RequestTimeout: 2 * time.Second, + MaxTerminalEntries: 32, + MaxTerminalBytes: 1 << 20, + TerminalRecordTTL: time.Minute, + }) + require.NoError(t, err) + defer gateway.Close() + + readyContext, cancel := context.WithTimeout(context.Background(), 5*time.Second) + require.NoError(t, gateway.CheckLanguageReady(readyContext, udf.LanguagePython)) + cancel() + gateway.mu.Lock() + firstEpoch := gateway.workerLeaseEpoch + gateway.mu.Unlock() + require.NotZero(t, firstEpoch) + + stopRealWorker(first) + second := startRealWorker(t, python, workerPath, port) + defer stopRealWorker(second) + + // CheckLanguageReady is a live admission check. It must probe the + // replacement worker rather than returning the cached success from the + // previous process, even though the endpoint and software contract are the + // same. + readyContext, cancel = context.WithTimeout(context.Background(), 5*time.Second) + require.NoError(t, gateway.CheckLanguageReady(readyContext, udf.LanguagePython)) + cancel() + gateway.mu.Lock() + secondEpoch := gateway.workerLeaseEpoch + gateway.mu.Unlock() + require.NotZero(t, secondEpoch) + require.NotEqual(t, firstEpoch, secondEpoch, "readiness must bind to the replacement worker instance") +} + +func TestGatewayCloseCancelsAnInFlightExchange(t *testing.T) { + python, err := exec.LookPath("python3") + require.NoError(t, err, "python3 is required for the real worker contract test") + workerPath := realWorkerPath(t) + port := freeTCPPort(t) + worker := startRealWorker(t, python, workerPath, port) + + marker := filepath.Join(t.TempDir(), "handler-started") + // The handler has a deterministic start barrier and then never returns on + // its own. Gateway.Close must cancel the Flight exchange and cause the + // worker's independent cleanup path to terminate this process group. + source := fmt.Sprintf(`import pathlib +import time + +def add(ctx, value): + pathlib.Path(%q).write_text(str(__import__("os").getpid())) + while True: + time.sleep(1) +`, marker) + + gateway, err := NewGateway(ClientConfig{ + Enabled: true, + AllowUnisolated: true, + ServerAddress: "127.0.0.1:" + strconv.Itoa(port), + MaxBatchBytes: 1 << 20, + MaxBatchRows: 1, + MaxActiveInvocations: 1, + RequestTimeout: 30 * time.Second, + MaxTerminalEntries: 32, + MaxTerminalBytes: 1 << 20, + TerminalRecordTTL: time.Minute, + }) + require.NoError(t, err) + defer func() { + _ = gateway.Close() + stopRealWorker(worker) + }() + + readyContext, cancel := context.WithTimeout(context.Background(), 5*time.Second) + require.NoError(t, gateway.CheckLanguageReady(readyContext, udf.LanguagePython)) + cancel() + + input, mp := integrationInput(t, []int64{1}) + result := vector.NewFunctionResultWrapper(types.T_int64.ToType(), mp) + invocation := integrationInvocation(ModeScalar, source, input, protocol.FencingTuple{ + AccountID: 1, StatementID: "gateway-close", GroupID: "gateway-close-group", + GroupEpoch: 1, InvocationID: "gateway-close-invocation", LeaseEpoch: 1, + }) + done := make(chan error, 1) + go func() { + done <- gateway.Execute(context.Background(), invocation, result, mp) + }() + + require.Eventually(t, func() bool { + _, statErr := os.Stat(marker) + return statErr == nil + }, 5*time.Second, 10*time.Millisecond, "handler did not reach the cancellation barrier") + require.NoError(t, gateway.Close()) + select { + case err := <-done: + require.Error(t, err, "closing the Gateway must not report a successful in-flight invocation") + case <-time.After(5 * time.Second): + t.Fatal("Gateway.Close did not cancel the in-flight exchange") + } + pidBytes, err := os.ReadFile(marker) + require.NoError(t, err) + handlerPID, err := strconv.Atoi(string(pidBytes)) + require.NoError(t, err) + if runtime.GOOS != "windows" { + require.Eventually(t, func() bool { + return syscall.Kill(handlerPID, 0) != nil + }, 5*time.Second, 10*time.Millisecond, "handler process survived Gateway.Close") + } + // The transport error is only half of the shutdown contract. The owner + // cleanup must also have removed the active admission, released K, and + // retained exactly one terminal fence for the accepted Open. Inspect these + // after Execute has returned so the assertion is about the real Flight path, + // rather than a helper's cleanup callback. + gateway.admissionMu.Lock() + require.Empty(t, gateway.admittedGroups) + require.Empty(t, gateway.active) + closedEpoch := gateway.closedGroups[scopedGroupKey(invocation.Tuple.AccountID, invocation.Tuple.GroupID)] + gateway.admissionMu.Unlock() + require.Equal(t, uint64(1), closedEpoch) + entries, _ := gateway.ledger.Counts() + require.Equal(t, 1, entries, "accepted Open retains one terminal tombstone") + + input.Free(mp) + result.Free() + mpool.DeleteMPool(mp) +} + +// BenchmarkGatewayRealPythonWorkerBurst measures the real Flight path with a +// fixed two-row batch. The first sub-benchmark performs eight independent +// one-batch invocations; the second performs one invocation containing eight +// batches. The handler records module loads in a test-owned file, which makes +// the child/import count observable instead of inferring reuse from elapsed +// time. This is a W=1 comparison: it measures bounded burst reuse and does not +// claim a W>1 pipeline benefit. +func BenchmarkGatewayRealPythonWorkerBurst(b *testing.B) { + python, err := exec.LookPath("python3") + if err != nil { + b.Skip("python3 is required for the real worker benchmark") + } + workerPath := realWorkerPath(b) + port := freeTCPPort(b) + worker := startRealWorker(b, python, workerPath, port) + defer stopRealWorker(worker) + + gateway, err := NewGateway(ClientConfig{ + Enabled: true, + AllowUnisolated: true, + ServerAddress: "127.0.0.1:" + strconv.Itoa(port), + MaxBatchBytes: 1 << 20, + MaxBatchRows: 2, + MaxActiveInvocations: 2, + MaxInvocationRows: 1024, + MaxInvocationResultBytes: 1 << 20, + RequestTimeout: 30 * time.Second, + MaxTerminalEntries: 1024, + MaxTerminalBytes: 1 << 20, + TerminalRecordTTL: time.Minute, + }) + if err != nil { + b.Fatal(err) + } + defer gateway.Close() + readyContext, cancel := context.WithTimeout(context.Background(), 5*time.Second) + if err := gateway.CheckLanguageReady(readyContext, udf.LanguagePython); err != nil { + cancel() + b.Fatal(err) + } + cancel() + + benchmark := func(b *testing.B, rows, calls int, label string) { + marker := filepath.Join(b.TempDir(), label+"-module-loads") + runID := realWorkerBenchmarkRun.Add(1) + source := fmt.Sprintf(`from pathlib import Path +with Path(%q).open("a", encoding="utf-8") as marker: + marker.write("loaded\n") + +def add(ctx, value): + return value + 1 +`, marker) + input, mp := integrationInput(b, make([]int64, rows)) + for index := range make([]int64, rows) { + vector.MustFixedColNoTypeCheck[int64](input)[index] = int64(index) + } + result := vector.NewFunctionResultWrapper(types.T_int64.ToType(), mp) + defer func() { + input.Free(mp) + result.Free() + mpool.DeleteMPool(mp) + }() + + b.ReportAllocs() + b.ResetTimer() + for iteration := 0; iteration < b.N; iteration++ { + for call := 0; call < calls; call++ { + invocation := integrationInvocation( + ModeScalar, source, input, + protocol.FencingTuple{ + AccountID: 1, + StatementID: fmt.Sprintf("benchmark-%s-%d-%d-%d", label, runID, iteration, call), + GroupID: fmt.Sprintf("benchmark-%s-group-%d-%d-%d", label, runID, iteration, call), + GroupEpoch: 1, + InvocationID: fmt.Sprintf("benchmark-%s-invocation-%d-%d-%d", label, runID, iteration, call), + LeaseEpoch: 1, + }, + ) + if err := gateway.Execute(context.Background(), invocation, result, mp); err != nil { + b.Fatal(err) + } + } + } + b.StopTimer() + loads, err := os.ReadFile(marker) + if err != nil { + b.Fatal(err) + } + actualLoads := strings.Count(string(loads), "loaded\n") + if actualLoads == 0 { + b.Fatal("the handler did not record a module load") + } + b.ReportMetric(float64(rows*calls*b.N)/float64(b.Elapsed().Nanoseconds())*1e9, "rows/s") + b.Logf("batches/invocation=%d module_loads=%d", rows/2, actualLoads) + } + + b.Run("eight_independent_one_batch_invocations", func(b *testing.B) { + benchmark(b, 2, 8, "independent") + }) + b.Run("one_eight_batch_invocation", func(b *testing.B) { + benchmark(b, 16, 1, "burst") + }) +} + +// BenchmarkGatewayRealPythonWorkerLargeBatch compares the two handler modes +// on one 8,192-row batch. The small-batch burst benchmark above is dominated +// by process startup and Flight control traffic; this benchmark makes the +// scalar conversion cost visible while keeping the complete Gateway/Flight/ +// worker/materialization path intact. +func BenchmarkGatewayRealPythonWorkerLargeBatch(b *testing.B) { + python, err := exec.LookPath("python3") + if err != nil { + b.Skip("python3 is required for the real worker benchmark") + } + workerPath := realWorkerPath(b) + port := freeTCPPort(b) + worker := startRealWorker(b, python, workerPath, port) + defer stopRealWorker(worker) + + gateway, err := NewGateway(ClientConfig{ + Enabled: true, + AllowUnisolated: true, + ServerAddress: "127.0.0.1:" + strconv.Itoa(port), + MaxBatchBytes: 1 << 20, + MaxBatchRows: 8192, + MaxActiveInvocations: 2, + MaxInvocationRows: 1 << 20, + MaxInvocationResultBytes: 1 << 20, + RequestTimeout: 30 * time.Second, + MaxTerminalEntries: 1024, + MaxTerminalBytes: 1 << 20, + TerminalRecordTTL: time.Minute, + }) + if err != nil { + b.Fatal(err) + } + defer gateway.Close() + readyContext, cancel := context.WithTimeout(context.Background(), 5*time.Second) + if err := gateway.CheckLanguageReady(readyContext, udf.LanguagePython); err != nil { + cancel() + b.Fatal(err) + } + cancel() + + const rows = 8192 + run := func(b *testing.B, mode, source, label string) { + input, mp := integrationInput(b, make([]int64, rows)) + defer func() { + input.Free(mp) + mpool.DeleteMPool(mp) + }() + result := vector.NewFunctionResultWrapper(types.T_int64.ToType(), mp) + defer result.Free() + b.ReportAllocs() + b.SetBytes(int64(rows * 8)) + b.ResetTimer() + for iteration := 0; iteration < b.N; iteration++ { + runID := realWorkerBenchmarkRun.Add(1) + invocation := integrationInvocationForArgs( + mode, "add", source, []types.Type{types.T_int64.ToType()}, + []*vector.Vector{input}, rows, + protocol.FencingTuple{ + AccountID: 1, StatementID: fmt.Sprintf("large-%s-%d-%d", label, runID, iteration), + GroupID: fmt.Sprintf("large-%s-group-%d-%d", label, runID, iteration), GroupEpoch: 1, + InvocationID: fmt.Sprintf("large-%s-invocation-%d-%d", label, runID, iteration), LeaseEpoch: 1, + }, + ) + if err := gateway.Execute(context.Background(), invocation, result, mp); err != nil { + b.Fatal(err) + } + } + b.StopTimer() + b.ReportMetric(float64(rows*b.N)/float64(b.Elapsed().Nanoseconds())*1e9, "rows/s") + } + + b.Run("scalar", func(b *testing.B) { + run(b, ModeScalar, "def add(ctx, value): return value + 1", "scalar") + }) + b.Run("vector", func(b *testing.B) { + run(b, ModeVector, "import pyarrow.compute as pc\ndef add(ctx, values): return pc.add(values, 1)", "vector") + }) +} + +func realWorkerPath(t testing.TB) string { + t.Helper() + _, sourceFile, _, ok := runtime.Caller(0) + require.True(t, ok) + path := filepath.Join(filepath.Dir(sourceFile), "worker", "worker.py") + _, err := os.Stat(path) + require.NoError(t, err) + return path +} + +func freeTCPPort(t testing.TB) int { + t.Helper() + listener, err := net.Listen("tcp", "127.0.0.1:0") + require.NoError(t, err) + defer listener.Close() + return listener.Addr().(*net.TCPAddr).Port +} + +func waitForWorkerPort(t testing.TB, port int) { + t.Helper() + deadline := time.Now().Add(5 * time.Second) + ticker := time.NewTicker(10 * time.Millisecond) + defer ticker.Stop() + for { + connection, err := net.DialTimeout("tcp", "127.0.0.1:"+strconv.Itoa(port), 100*time.Millisecond) + if err == nil { + _ = connection.Close() + return + } + if time.Now().After(deadline) { + require.NoError(t, err, "Python worker did not listen before the startup deadline") + } + <-ticker.C + } +} + +func startRealWorker(t testing.TB, python, workerPath string, port int) *exec.Cmd { + t.Helper() + cmd := exec.Command(python, workerPath, "--address=grpc+tcp://127.0.0.1:"+strconv.Itoa(port)) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Env = append(os.Environ(), "PYTHONUNBUFFERED=1") + if runtime.GOOS != "windows" { + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} + } + require.NoError(t, cmd.Start()) + // Own cleanup before readiness can fail; Fatal also runs test cleanups. + t.Cleanup(func() { stopRealWorker(cmd) }) + waitForWorkerPort(t, port) + return cmd +} + +func stopRealWorker(cmd *exec.Cmd) { + if cmd == nil || cmd.Process == nil || cmd.ProcessState != nil { + return + } + if runtime.GOOS != "windows" { + _ = syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL) + } else { + _ = cmd.Process.Kill() + } + _ = cmd.Wait() +} + +func integrationInput(t testing.TB, values []int64) (*vector.Vector, *mpool.MPool) { + t.Helper() + mp := mpool.MustNewZeroNoFixed() + input := vector.NewVec(types.T_int64.ToType()) + for _, value := range values { + require.NoError(t, vector.AppendFixed(input, value, false, mp)) + } + return input, mp +} + +func integrationInvocation(mode, source string, input *vector.Vector, tuple protocol.FencingTuple) *udf.Invocation { + return integrationInvocationForArgs( + mode, "add", source, + []types.Type{types.T_int64.ToType()}, []*vector.Vector{input}, input.Length(), tuple, + ) +} + +func integrationZeroArgVectorInvocation(source string, length int, tuple protocol.FencingTuple) *udf.Invocation { + return integrationInvocationForArgs(ModeVector, "add", source, nil, nil, length, tuple) +} + +func integrationInvocationForArgs( + mode, handler, source string, + args []types.Type, + inputs []*vector.Vector, + length int, + tuple protocol.FencingTuple, +) *udf.Invocation { + environmentDigest := func() string { + digest, _ := udf.PythonEnvironmentDigest() + return digest + }() + argumentDescriptors := make([]TypeDescriptor, len(args)) + for index, typ := range args { + argumentDescriptors[index], _ = NewTypeDescriptor(typ) + } + returnDescriptor, _ := NewTypeDescriptor(types.T_int64.ToType()) + statementValues := map[string]string{ + "statement_id": tuple.StatementID, + "statement_timestamp_utc": "1704067200123456", + "session_timezone_kind": "FIXED_OFFSET", + "session_timezone_offset_minutes": "+480", + "sql_mode": "[\"ANSI\",\"STRICT_TRANS_TABLES\"]", + "current_database": "udf_integration", + "current_user": "root", + "current_role": "writer", + "connection_collation": "utf8mb4_bin", + } + statementContext, _ := udf.StatementContextFromMap(statementValues) + return &udf.Invocation{ + FunctionRef: udf.FunctionRef{ + AccountID: tuple.AccountID, DatabaseID: 2, FunctionID: 3, Revision: 1, NamespaceVersion: 1, + }, + Language: udf.LanguagePython, + Handler: handler, + Source: source, + Args: args, + ReturnType: types.T_int64.ToType(), + Inputs: inputs, + Length: length, + Mode: mode, + NullPolicy: NullCallHandler, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + SDKVersion: udf.PythonSDKVersion, + DefinitionSchemaVersion: udf.PythonDefinitionSchemaVersion, + ArtifactDigest: udf.PythonInlineArtifactDigest(handler, source), + EnvironmentDigest: environmentDigest, + DefinitionFingerprint: func() string { + fingerprint, _ := DefinitionFingerprint( + udf.PythonDefinitionSchemaVersion, + handler, mode, NullCallHandler, + udf.PythonABIContract, udf.PythonAdapterVersion, + udf.PythonInlineArtifactDigest(handler, source), environmentDigest, + udf.PythonSDKVersion, argumentDescriptors, returnDescriptor, + ) + return fingerprint + }(), + CallsiteID: "python/integration", + MayError: true, + SecurityMode: "INVOKER", + StatementContext: statementContext, + SecurityFrame: &udf.SecurityFrame{ + ContractVersion: udf.SecurityFrameContractVersion, + Mode: "INVOKER", + }, + Context: statementValues, + Tuple: tuple, + } +} + +func routineDefinitionForIntegration(invocation *udf.Invocation) *udf.RoutineDefinition { + return &udf.RoutineDefinition{ + Language: udf.LanguagePython, + AccountID: invocation.FunctionRef.AccountID, + Handler: invocation.Handler, + Args: append([]types.Type(nil), invocation.Args...), + ReturnType: invocation.ReturnType, + Mode: invocation.Mode, + NullPolicy: invocation.NullPolicy, + ABIContract: invocation.ABIContract, + AdapterVersion: invocation.AdapterVersion, + SDKVersion: invocation.SDKVersion, + DefinitionSchemaVersion: invocation.DefinitionSchemaVersion, + ArtifactDigest: invocation.ArtifactDigest, + EnvironmentDigest: invocation.EnvironmentDigest, + DefinitionFingerprint: invocation.DefinitionFingerprint, + } +} + +func TestRealWorkerStopRecordsCompletion(t *testing.T) { + python, err := exec.LookPath("python3") + require.NoError(t, err) + cmd := startRealWorker(t, python, realWorkerPath(t), freeTCPPort(t)) + stopRealWorker(cmd) + // Process.Wait alone does not publish this state on Cmd, so delayed cleanup + // could send a second signal to a process group whose ID has been reused. + require.NotNil(t, cmd.ProcessState) + completed := cmd.ProcessState + stopRealWorker(cmd) + require.Same(t, completed, cmd.ProcessState) +} diff --git a/pkg/udf/python/gateway_test.go b/pkg/udf/python/gateway_test.go new file mode 100644 index 0000000000000..cd2961e876bce --- /dev/null +++ b/pkg/udf/python/gateway_test.go @@ -0,0 +1,1447 @@ +// Copyright 2026 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 python + +import ( + "context" + "encoding/json" + "errors" + "io" + "strings" + "sync" + "testing" + "time" + + "github.com/apache/arrow-go/v18/arrow" + "github.com/apache/arrow-go/v18/arrow/array" + "github.com/apache/arrow-go/v18/arrow/flight/gen/flight" + "github.com/apache/arrow-go/v18/arrow/memory" + "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/udf" + "github.com/matrixorigin/matrixone/pkg/udf/protocol" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" +) + +type gatewayResultStream struct { + grpc.ClientStream + results []*flight.FlightData + index int +} + +type scriptedGatewayResultStream struct { + grpc.ClientStream + results []*flight.FlightData + errors []error + index int +} + +func (s *scriptedGatewayResultStream) Recv() (*flight.FlightData, error) { + index := s.index + s.index++ + if index < len(s.results) { + return s.results[index], nil + } + if index < len(s.errors) { + return nil, s.errors[index] + } + return nil, io.EOF +} + +func (s *scriptedGatewayResultStream) Send(*flight.FlightData) error { + return nil +} + +type gatedGatewayResultStream struct { + grpc.ClientStream + results []*flight.FlightData + index int + release <-chan struct{} + waiting chan<- struct{} + waitOnce sync.Once +} + +type finishAckActionStream struct { + grpc.ClientStream + result *flight.Result + err error + read bool +} + +func (s *finishAckActionStream) Recv() (*flight.Result, error) { + if !s.read { + s.read = true + if s.err != nil { + return nil, s.err + } + return s.result, nil + } + return nil, io.EOF +} + +type finishAckFlightClient struct { + flight.FlightServiceClient + calls int + actions []*flight.Action +} + +type resultAckFlightClient struct { + flight.FlightServiceClient + response []byte + err error +} + +func (c *resultAckFlightClient) DoAction(context.Context, *flight.Action, ...grpc.CallOption) (flight.FlightService_DoActionClient, error) { + return &finishAckActionStream{result: &flight.Result{Body: c.response}, err: c.err}, nil +} + +type capabilityActionClient struct { + flight.FlightServiceClient + response []byte + err error +} + +func (c *capabilityActionClient) DoAction( + _ context.Context, + action *flight.Action, + _ ...grpc.CallOption, +) (flight.FlightService_DoActionClient, error) { + if c.err != nil { + return nil, c.err + } + if action.Type != "GetPythonCapabilities" { + return nil, errors.New("unexpected capability action") + } + return &finishAckActionStream{result: &flight.Result{Body: c.response}}, nil +} + +type scriptedCapabilityActionStream struct { + grpc.ClientStream + results []*flight.Result + errors []error + index int +} + +func (s *scriptedCapabilityActionStream) Recv() (*flight.Result, error) { + index := s.index + s.index++ + if index < len(s.results) { + return s.results[index], nil + } + if index < len(s.errors) { + return nil, s.errors[index] + } + return nil, io.EOF +} + +type scriptedCapabilityFlightClient struct { + flight.FlightServiceClient + actionErr error + stream *scriptedCapabilityActionStream + actions []*flight.Action +} + +func (c *scriptedCapabilityFlightClient) DoAction( + _ context.Context, + action *flight.Action, + _ ...grpc.CallOption, +) (flight.FlightService_DoActionClient, error) { + c.actions = append(c.actions, action) + if c.actionErr != nil { + return nil, c.actionErr + } + return c.stream, nil +} + +type recordingArtifactResolver struct { + source string + calls int + account uint64 + handler string + digest string +} + +type blockingArtifactResolver struct{} + +func (blockingArtifactResolver) Resolve(ctx context.Context, _ uint64, _, _ string) (string, error) { + <-ctx.Done() + return "", ctx.Err() +} + +type closeBlockingArtifactResolver struct { + started chan struct{} +} + +func (r *closeBlockingArtifactResolver) Resolve(ctx context.Context, _ uint64, _, _ string) (string, error) { + close(r.started) + <-ctx.Done() + return "", ctx.Err() +} + +func (r *recordingArtifactResolver) Resolve(_ context.Context, accountID uint64, handler, digest string) (string, error) { + r.calls++ + r.account = accountID + r.handler = handler + r.digest = digest + return r.source, nil +} + +func TestValidateDefinitionBoundsArtifactResolution(t *testing.T) { + invocation := validInvocation() + gateway, err := NewGatewayWithArtifactStore(ClientConfig{ + Enabled: true, + AllowUnisolated: true, + ServerAddress: "127.0.0.1:1", + RequestTimeout: 20 * time.Millisecond, + }, blockingArtifactResolver{}) + require.NoError(t, err) + defer gateway.Close() + + definition := &udf.RoutineDefinition{ + Language: udf.LanguagePython, + AccountID: invocation.FunctionRef.AccountID, + Handler: invocation.Handler, + Args: append([]types.Type(nil), invocation.Args...), + ReturnType: invocation.ReturnType, + Mode: invocation.Mode, + NullPolicy: invocation.NullPolicy, + ABIContract: invocation.ABIContract, + AdapterVersion: invocation.AdapterVersion, + SDKVersion: invocation.SDKVersion, + DefinitionSchemaVersion: invocation.DefinitionSchemaVersion, + ArtifactDigest: invocation.ArtifactDigest, + EnvironmentDigest: invocation.EnvironmentDigest, + DefinitionFingerprint: invocation.DefinitionFingerprint, + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + done := make(chan error, 1) + go func() { done <- gateway.ValidateDefinition(ctx, definition) }() + select { + case err := <-done: + require.ErrorIs(t, err, context.DeadlineExceeded) + case <-time.After(500 * time.Millisecond): + cancel() + require.FailNow(t, "artifact resolution was not bounded by the gateway request timeout") + } +} + +func TestGatewayCloseCancelsDefinitionResolution(t *testing.T) { + invocation := validInvocation() + resolver := &closeBlockingArtifactResolver{started: make(chan struct{})} + gateway, err := NewGatewayWithArtifactStore(ClientConfig{ + Enabled: true, + AllowUnisolated: true, + ServerAddress: "127.0.0.1:1", + RequestTimeout: 30 * time.Second, + }, resolver) + require.NoError(t, err) + + definition := &udf.RoutineDefinition{ + Language: udf.LanguagePython, + AccountID: invocation.FunctionRef.AccountID, + Handler: invocation.Handler, + Args: append([]types.Type(nil), invocation.Args...), + ReturnType: invocation.ReturnType, + Mode: invocation.Mode, + NullPolicy: invocation.NullPolicy, + ABIContract: invocation.ABIContract, + AdapterVersion: invocation.AdapterVersion, + SDKVersion: invocation.SDKVersion, + DefinitionSchemaVersion: invocation.DefinitionSchemaVersion, + ArtifactDigest: invocation.ArtifactDigest, + EnvironmentDigest: invocation.EnvironmentDigest, + DefinitionFingerprint: invocation.DefinitionFingerprint, + } + done := make(chan error, 1) + go func() { done <- gateway.ValidateDefinition(context.Background(), definition) }() + select { + case <-resolver.started: + case <-time.After(time.Second): + require.FailNow(t, "artifact resolution did not start") + } + require.NoError(t, gateway.Close()) + select { + case err := <-done: + require.ErrorIs(t, err, context.Canceled) + case <-time.After(time.Second): + require.FailNow(t, "Gateway.Close did not cancel artifact resolution") + } +} + +func (c *finishAckFlightClient) DoAction( + ctx context.Context, + action *flight.Action, + opts ...grpc.CallOption, +) (flight.FlightService_DoActionClient, error) { + c.calls++ + c.actions = append(c.actions, action) + if c.calls == 1 { + return &finishAckActionStream{err: errors.New("injected ACK response loss")}, nil + } + tuple := validInvocation().Tuple + ack, err := protocol.MarshalControl(protocol.Control{ + Kind: "Ack", Tuple: tuple, Status: statusOK, FinishID: "finish-1", + }) + if err != nil { + return nil, err + } + return &finishAckActionStream{result: &flight.Result{Body: ack}}, nil +} + +func (s *gatewayResultStream) Recv() (*flight.FlightData, error) { + if s.index == len(s.results) { + return nil, io.EOF + } + result := s.results[s.index] + s.index++ + return result, nil +} + +func (s *gatewayResultStream) Send(*flight.FlightData) error { + return nil +} + +func (s *gatedGatewayResultStream) Recv() (*flight.FlightData, error) { + if s.index < len(s.results) { + result := s.results[s.index] + s.index++ + return result, nil + } + s.waitOnce.Do(func() { close(s.waiting) }) + <-s.release + return nil, io.EOF +} + +func (s *gatedGatewayResultStream) Send(*flight.FlightData) error { + return nil +} + +func gatewayControl(t *testing.T, kind string, tuple protocol.FencingTuple, fields ...func(*protocol.Control)) *flight.FlightData { + t.Helper() + control := protocol.Control{Kind: kind, Tuple: tuple} + for _, field := range fields { + field(&control) + } + encoded, err := protocol.MarshalControl(control) + require.NoError(t, err) + return &flight.FlightData{AppMetadata: encoded} +} + +func validInvocation() *udf.Invocation { + return &udf.Invocation{ + FunctionRef: udf.FunctionRef{ + AccountID: 1, DatabaseID: 2, FunctionID: 3, Revision: 1, NamespaceVersion: 1, + }, + Language: udf.LanguagePython, + Handler: "add", + Source: "def add(ctx, value): return value", + Args: []types.Type{types.T_int64.ToType()}, + ReturnType: types.T_int64.ToType(), + Length: 0, + Inputs: []*vector.Vector{nil}, + Mode: ModeScalar, + NullPolicy: NullCallHandler, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + SDKVersion: udf.PythonSDKVersion, + DefinitionSchemaVersion: udf.PythonDefinitionSchemaVersion, + ArtifactDigest: udf.PythonInlineArtifactDigest("add", "def add(ctx, value): return value"), + EnvironmentDigest: func() string { digest, _ := udf.PythonEnvironmentDigest(); return digest }(), + DefinitionFingerprint: func() string { + argument, _ := NewTypeDescriptor(types.T_int64.ToType()) + fingerprint, _ := DefinitionFingerprint( + udf.PythonDefinitionSchemaVersion, + "add", ModeScalar, NullCallHandler, + udf.PythonABIContract, udf.PythonAdapterVersion, + udf.PythonInlineArtifactDigest("add", "def add(ctx, value): return value"), + func() string { digest, _ := udf.PythonEnvironmentDigest(); return digest }(), + udf.PythonSDKVersion, []TypeDescriptor{argument}, argument, + ) + return fingerprint + }(), + CallsiteID: "python/test", + MayError: true, + SecurityMode: "INVOKER", + StatementContext: &udf.StatementContext{ + ContractVersion: udf.StatementContextContractVersion, + StatementTimestampUTC: 1704067200123456, + TimezoneKind: "FIXED_OFFSET", + TimezoneOffsetMinutes: 480, + SQLMode: []string{"ANSI", "STRICT_TRANS_TABLES"}, + CurrentDatabase: "udf", + CurrentUser: "root", + CurrentRole: "writer", + ConnectionCollation: "utf8mb4_bin", + }, + SecurityFrame: &udf.SecurityFrame{ + ContractVersion: udf.SecurityFrameContractVersion, + Mode: "INVOKER", + }, + Tuple: protocol.FencingTuple{ + AccountID: 1, StatementID: "statement", GroupID: "group", + GroupEpoch: 1, InvocationID: "invocation", LeaseEpoch: 1, + }, + } +} + +func TestValidateInvocationHeaderRejectsUnfrozenContracts(t *testing.T) { + require.NoError(t, validateInvocationHeader(validInvocation())) + + cases := []struct { + name string + mutate func(*udf.Invocation) + }{ + {"nil invocation", nil}, + {"language", func(i *udf.Invocation) { i.Language = "PYTHON" }}, + {"empty handler", func(i *udf.Invocation) { i.Handler = "" }}, + {"external handler", func(i *udf.Invocation) { i.Handler = "package:handler" }}, + {"negative length", func(i *udf.Invocation) { i.Length = -1 }}, + {"argument input count", func(i *udf.Invocation) { i.Inputs = nil }}, + {"unsupported mode", func(i *udf.Invocation) { i.Mode = "BATCH" }}, + {"empty callsite", func(i *udf.Invocation) { i.CallsiteID = "" }}, + {"oversized callsite", func(i *udf.Invocation) { i.CallsiteID = strings.Repeat("x", 257) }}, + {"control character callsite", func(i *udf.Invocation) { i.CallsiteID = "bad\nsite" }}, + {"must be allowed to error", func(i *udf.Invocation) { i.MayError = false }}, + {"unsupported security mode", func(i *udf.Invocation) { i.SecurityMode = "DEFINER" }}, + {"leakproof", func(i *udf.Invocation) { i.Leakproof = true }}, + {"missing statement context", func(i *udf.Invocation) { i.StatementContext = nil }}, + {"invalid statement context", func(i *udf.Invocation) { i.StatementContext.TimezoneKind = "UNKNOWN" }}, + {"missing security frame", func(i *udf.Invocation) { i.SecurityFrame = nil }}, + {"changed security principal", func(i *udf.Invocation) { i.SecurityFrame.EffectiveUserID = 8 }}, + {"security mode mismatch", func(i *udf.Invocation) { i.SecurityFrame.Mode = "DEFINER" }}, + {"unsupported null policy", func(i *udf.Invocation) { i.NullPolicy = "STRICT" }}, + {"unsupported ABI", func(i *udf.Invocation) { i.ABIContract = "PYTHON_NATIVE" }}, + {"unsupported adapter", func(i *udf.Invocation) { i.AdapterVersion = "future" }}, + {"unsupported SDK", func(i *udf.Invocation) { i.SDKVersion = "future" }}, + {"unsupported schema", func(i *udf.Invocation) { i.DefinitionSchemaVersion++ }}, + {"malformed artifact digest", func(i *udf.Invocation) { i.ArtifactDigest = "bad" }}, + {"environment digest mismatch", func(i *udf.Invocation) { i.EnvironmentDigest = strings.Repeat("d", 64) }}, + {"malformed definition fingerprint", func(i *udf.Invocation) { i.DefinitionFingerprint = "bad" }}, + {"unsupported argument type", func(i *udf.Invocation) { i.Args[0] = types.T_any.ToType() }}, + {"unsupported return type", func(i *udf.Invocation) { i.ReturnType = types.T_any.ToType() }}, + {"invalid function identity", func(i *udf.Invocation) { i.FunctionRef.FunctionID = 0 }}, + {"fencing account mismatch", func(i *udf.Invocation) { i.Tuple.AccountID++ }}, + {"invalid fencing tuple", func(i *udf.Invocation) { i.Tuple.StatementID = "" }}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + invocation := validInvocation() + if tc.mutate == nil { + require.Error(t, validateInvocationHeader(nil)) + return + } + tc.mutate(invocation) + require.Error(t, validateInvocationHeader(invocation)) + }) + } +} + +func TestGatewayStatusSnapshotReportsAdmissionAndWorkerContract(t *testing.T) { + response, err := json.Marshal(currentTestCapabilities()) + require.NoError(t, err) + for _, tc := range []struct { + name string + language string + config ClientConfig + client *capabilityActionClient + closeGateway bool + directConfig bool + wantReady bool + wantClass string + wantReason string + wantProtocol int32 + wantLease uint64 + }{ + { + name: "unsupported language", + language: "sql", + wantClass: udf.RuntimeStatusInvalid, + wantReason: udf.RuntimeStatusReasonInvalidLanguage, + }, + { + name: "disabled", + language: udf.LanguagePython, + wantClass: udf.RuntimeStatusDisabled, + wantReason: udf.RuntimeStatusReasonRuntimeDisabled, + }, + { + name: "unisolated execution not admitted", + language: udf.LanguagePython, + config: ClientConfig{ + Enabled: true, + }, + directConfig: true, + wantClass: udf.RuntimeStatusNotAllowed, + wantReason: udf.RuntimeStatusReasonUnisolatedNotAllowed, + }, + { + name: "worker transport failure", + language: udf.LanguagePython, + config: ClientConfig{ + Enabled: true, AllowUnisolated: true, ServerAddress: "127.0.0.1:1", RequestTimeout: time.Second, + }, + client: &capabilityActionClient{err: errors.New("connection refused")}, + wantClass: udf.RuntimeStatusUnavailable, + wantReason: udf.RuntimeStatusReasonWorkerUnavailable, + }, + { + name: "capability contract mismatch", + language: udf.LanguagePython, + config: ClientConfig{ + Enabled: true, AllowUnisolated: true, ServerAddress: "127.0.0.1:1", RequestTimeout: time.Second, + }, + client: func() *capabilityActionClient { + mismatch := currentTestCapabilities() + mismatch.ProtocolVersion++ + body, marshalErr := json.Marshal(mismatch) + require.NoError(t, marshalErr) + return &capabilityActionClient{response: body} + }(), + wantClass: udf.RuntimeStatusContractMismatch, + wantReason: udf.RuntimeStatusReasonCapabilityMismatch, + }, + { + name: "ready worker", + language: udf.LanguagePython, + config: ClientConfig{ + Enabled: true, AllowUnisolated: true, ServerAddress: "127.0.0.1:1", RequestTimeout: time.Second, + }, + client: &capabilityActionClient{response: response}, + wantReady: true, + wantClass: "", + wantReason: udf.RuntimeStatusReasonReady, + wantProtocol: int32(protocol.Version), + wantLease: 42, + }, + { + name: "closed gateway", + language: udf.LanguagePython, + config: ClientConfig{Enabled: true, AllowUnisolated: true, ServerAddress: "127.0.0.1:1"}, + closeGateway: true, + wantClass: udf.RuntimeStatusClosed, + wantReason: udf.RuntimeStatusReasonRuntimeClosed, + }, + } { + t.Run(tc.name, func(t *testing.T) { + cfg := tc.config + if cfg.ServerAddress == "" && cfg.Enabled { + cfg.ServerAddress = "127.0.0.1:1" + } + if cfg.Enabled && cfg.AllowUnisolated && cfg.RequestTimeout == 0 { + cfg.RequestTimeout = time.Second + } + var gateway *Gateway + var err error + if tc.directConfig { + // NewGateway correctly rejects this production configuration. A + // direct value exercises the status fail-closed branch itself. + gateway = &Gateway{cfg: cfg} + } else { + gateway, err = NewGateway(cfg) + require.NoError(t, err) + } + if tc.client != nil { + gateway.flight = tc.client + } + if tc.closeGateway { + require.NoError(t, gateway.Close()) + } else { + defer gateway.Close() + } + + snapshot := gateway.StatusSnapshot(nil, tc.language) + require.Equal(t, tc.language, snapshot.Language) + require.Equal(t, tc.wantReady, snapshot.Ready) + require.Equal(t, tc.wantClass, snapshot.ErrorClass) + require.Equal(t, tc.wantReason, snapshot.Reason) + if tc.wantReady { + require.Equal(t, tc.wantProtocol, snapshot.ProtocolVersion) + require.Equal(t, tc.wantLease, snapshot.LeaseEpoch) + require.Equal(t, []string{ModeScalar, ModeVector}, snapshot.Modes) + require.Equal(t, []string{NullCallHandler, NullReturnNull}, snapshot.NullPolicies) + require.Equal(t, udf.PythonABIContract, snapshot.ABIContract) + } + }) + } +} + +func TestReadCapabilitiesRequiresOneStrictCurrentResponse(t *testing.T) { + validBody, err := json.Marshal(currentTestCapabilities()) + require.NoError(t, err) + unknownFieldBody := append(append([]byte(nil), validBody[:len(validBody)-1]...), []byte(`,"future_contract":true}`)...) + + for _, tc := range []struct { + name string + actionErr error + stream *scriptedCapabilityActionStream + wantError string + wantResult bool + }{ + { + name: "one current response followed by EOF", + stream: &scriptedCapabilityActionStream{ + results: []*flight.Result{{Body: validBody}}, + }, + wantResult: true, + }, + { + name: "action RPC failure", + actionErr: errors.New("injected action failure"), + wantError: "capability handshake", + }, + { + name: "first response transport failure", + stream: &scriptedCapabilityActionStream{ + errors: []error{errors.New("injected response failure")}, + }, + wantError: "capability handshake response", + }, + { + name: "empty response", + stream: &scriptedCapabilityActionStream{results: []*flight.Result{nil}}, + wantError: "empty capability handshake response", + }, + { + name: "malformed JSON", + stream: &scriptedCapabilityActionStream{ + results: []*flight.Result{{Body: []byte("{")}}, + }, + wantError: "decode capability handshake", + }, + { + name: "unknown contract field", + stream: &scriptedCapabilityActionStream{ + results: []*flight.Result{{Body: unknownFieldBody}}, + }, + wantError: "decode capability handshake", + }, + { + name: "trailing JSON value", + stream: &scriptedCapabilityActionStream{ + results: []*flight.Result{{Body: append(append([]byte(nil), validBody...), []byte(" {}")...)}}, + }, + wantError: "trailing JSON", + }, + { + name: "unsupported current contract", + stream: func() *scriptedCapabilityActionStream { + mismatch := currentTestCapabilities() + mismatch.ProtocolVersion++ + body, marshalErr := json.Marshal(mismatch) + require.NoError(t, marshalErr) + return &scriptedCapabilityActionStream{results: []*flight.Result{{Body: body}}} + }(), + wantError: "contract does not match", + }, + { + name: "multiple responses", + stream: &scriptedCapabilityActionStream{ + results: []*flight.Result{{Body: validBody}, {Body: validBody}}, + }, + wantError: "multiple results", + }, + { + name: "stream failure after response", + stream: &scriptedCapabilityActionStream{ + results: []*flight.Result{{Body: validBody}}, + errors: []error{nil, errors.New("injected trailing stream failure")}, + }, + wantError: "capability handshake stream", + }, + } { + t.Run(tc.name, func(t *testing.T) { + client := &scriptedCapabilityFlightClient{actionErr: tc.actionErr, stream: tc.stream} + got, err := readCapabilities(context.Background(), client) + if tc.wantError != "" { + require.ErrorContains(t, err, tc.wantError) + require.Nil(t, got) + } else { + require.NoError(t, err) + require.Equal(t, tc.wantResult, got != nil) + require.Equal(t, protocol.Version, got.ProtocolVersion) + } + require.Len(t, client.actions, 1) + require.Equal(t, "GetPythonCapabilities", client.actions[0].Type) + var request capabilityRequest + require.NoError(t, json.Unmarshal(client.actions[0].Body, &request)) + require.Equal(t, protocol.Version, request.ProtocolVersion) + }) + } +} + +func TestValidateDefinitionRejectsMalformedCurrentContractsBeforeRPC(t *testing.T) { + valid := func() *udf.RoutineDefinition { + invocation := validInvocation() + return &udf.RoutineDefinition{ + Language: invocation.Language, + AccountID: invocation.FunctionRef.AccountID, + Handler: invocation.Handler, + Source: invocation.Source, + Args: append([]types.Type(nil), invocation.Args...), + ReturnType: invocation.ReturnType, + Mode: invocation.Mode, + NullPolicy: invocation.NullPolicy, + ABIContract: invocation.ABIContract, + AdapterVersion: invocation.AdapterVersion, + SDKVersion: invocation.SDKVersion, + DefinitionSchemaVersion: invocation.DefinitionSchemaVersion, + ArtifactDigest: invocation.ArtifactDigest, + EnvironmentDigest: invocation.EnvironmentDigest, + DefinitionFingerprint: invocation.DefinitionFingerprint, + } + } + for _, tc := range []struct { + name string + mutate func(*udf.RoutineDefinition) + }{ + {"unsupported language", func(d *udf.RoutineDefinition) { d.Language = "sql" }}, + {"empty handler", func(d *udf.RoutineDefinition) { d.Handler = " " }}, + {"external handler", func(d *udf.RoutineDefinition) { d.Handler = "module:handler" }}, + {"unsupported schema", func(d *udf.RoutineDefinition) { d.DefinitionSchemaVersion++ }}, + {"unsupported ABI", func(d *udf.RoutineDefinition) { d.ABIContract = "future" }}, + {"unsupported adapter", func(d *udf.RoutineDefinition) { d.AdapterVersion = "future" }}, + {"unsupported SDK", func(d *udf.RoutineDefinition) { d.SDKVersion = "future" }}, + {"unsupported mode", func(d *udf.RoutineDefinition) { d.Mode = "BATCH" }}, + {"unsupported NULL policy", func(d *udf.RoutineDefinition) { d.NullPolicy = "STRICT" }}, + {"invalid artifact digest", func(d *udf.RoutineDefinition) { d.ArtifactDigest = "invalid" }}, + {"invalid environment digest", func(d *udf.RoutineDefinition) { d.EnvironmentDigest = "invalid" }}, + {"environment digest mismatch", func(d *udf.RoutineDefinition) { d.EnvironmentDigest = strings.Repeat("a", 64) }}, + {"invalid fingerprint", func(d *udf.RoutineDefinition) { d.DefinitionFingerprint = "invalid" }}, + {"unsupported argument descriptor", func(d *udf.RoutineDefinition) { d.Args[0] = types.T_any.ToType() }}, + {"unsupported return descriptor", func(d *udf.RoutineDefinition) { d.ReturnType = types.T_any.ToType() }}, + {"fingerprint does not bind definition", func(d *udf.RoutineDefinition) { d.Mode = ModeVector }}, + } { + t.Run(tc.name, func(t *testing.T) { + gateway, err := NewGateway(ClientConfig{ + Enabled: true, AllowUnisolated: true, ServerAddress: "127.0.0.1:1", RequestTimeout: time.Second, + }) + require.NoError(t, err) + defer gateway.Close() + definition := valid() + tc.mutate(definition) + err = gateway.ValidateDefinition(context.Background(), definition) + require.Error(t, err) + require.Contains(t, err.Error(), "UNSUPPORTED_ROUTINE_VERSION") + gateway.mu.Lock() + defer gateway.mu.Unlock() + require.Nil(t, gateway.conn, "invalid definitions must be rejected before opening a Flight connection") + }) + } + t.Run("nil definition", func(t *testing.T) { + gateway, err := NewGateway(ClientConfig{Enabled: true, AllowUnisolated: true, ServerAddress: "127.0.0.1:1"}) + require.NoError(t, err) + defer gateway.Close() + require.ErrorContains(t, gateway.ValidateDefinition(context.Background(), nil), "nil Python routine definition") + }) + t.Run("disabled runtime", func(t *testing.T) { + gateway, err := NewGateway(ClientConfig{}) + require.NoError(t, err) + defer gateway.Close() + require.ErrorContains(t, gateway.ValidateDefinition(context.Background(), valid()), "runtime is disabled") + }) + t.Run("unisolated opt in is required", func(t *testing.T) { + gateway := &Gateway{cfg: ClientConfig{Enabled: true, ServerAddress: "127.0.0.1:1"}} + require.ErrorContains(t, gateway.ValidateDefinition(context.Background(), valid()), "explicit unisolated opt-in") + }) +} + +func TestValidateInvocationInputsChecksZeroRowVectorTypes(t *testing.T) { + mp := mpool.MustNewZeroNoFixed() + input := vector.NewVec(types.T_int32.ToType()) + defer func() { + input.Free(mp) + mpool.DeleteMPool(mp) + }() + + descriptor, err := NewTypeDescriptor(types.T_int64.ToType()) + require.NoError(t, err) + err = validateInvocationInputs(&udf.Invocation{ + Length: 0, + Args: []types.Type{types.T_int64.ToType()}, + Inputs: []*vector.Vector{input}, + }, []TypeDescriptor{descriptor}) + require.ErrorContains(t, err, "does not match the frozen argument type") +} + +func TestValidateInvocationRequiresFrozenContract(t *testing.T) { + base := validInvocation() + require.NoError(t, validateInvocation(base)) + + cases := []struct { + name string + mutate func(*udf.Invocation) + }{ + {name: "language", mutate: func(invocation *udf.Invocation) { invocation.Language = "" }}, + {name: "mode", mutate: func(invocation *udf.Invocation) { invocation.Mode = "" }}, + {name: "external handler", mutate: func(invocation *udf.Invocation) { invocation.Handler = "module:add" }}, + {name: "null policy", mutate: func(invocation *udf.Invocation) { invocation.NullPolicy = "" }}, + {name: "ABI", mutate: func(invocation *udf.Invocation) { invocation.ABIContract = "" }}, + {name: "adapter", mutate: func(invocation *udf.Invocation) { invocation.AdapterVersion = "" }}, + {name: "SDK", mutate: func(invocation *udf.Invocation) { invocation.SDKVersion = "" }}, + {name: "definition schema", mutate: func(invocation *udf.Invocation) { invocation.DefinitionSchemaVersion = 0 }}, + {name: "artifact digest", mutate: func(invocation *udf.Invocation) { invocation.ArtifactDigest = "" }}, + {name: "environment digest", mutate: func(invocation *udf.Invocation) { invocation.EnvironmentDigest = "" }}, + {name: "definition fingerprint", mutate: func(invocation *udf.Invocation) { invocation.DefinitionFingerprint = "" }}, + {name: "definition fingerprint contents", mutate: func(invocation *udf.Invocation) { + invocation.DefinitionFingerprint = strings.Repeat("b", 64) + }}, + } + for _, test := range cases { + t.Run(test.name, func(t *testing.T) { + invocation := validInvocation() + test.mutate(invocation) + require.Error(t, validateInvocation(invocation)) + }) + } +} + +func TestValidateInvocationBoundsResolvedArtifact(t *testing.T) { + oversized := validInvocation() + oversized.Source = strings.Repeat("x", int(DefaultMaxArtifactBytes)+1) + require.ErrorContains( + t, + validateInvocation(oversized), + "Python artifact exceeds", + ) + + invalidUTF8 := validInvocation() + invalidUTF8.Source = string([]byte{0xff}) + require.ErrorContains( + t, + validateInvocation(invalidUTF8), + "source is not valid UTF-8", + ) +} + +func TestGatewayValidatesIdentityBeforeResolvingArtifact(t *testing.T) { + resolver := &recordingArtifactResolver{source: validInvocation().Source} + gateway, err := NewGatewayWithArtifactStore(ClientConfig{ + Enabled: true, + AllowUnisolated: true, + ServerAddress: "127.0.0.1:50051", + }, resolver) + require.NoError(t, err) + + invocation := validInvocation() + invocation.Source = "" + invocation.FunctionRef.FunctionID = 0 + resultMP := mpool.MustNewZeroNoFixed() + defer mpool.DeleteMPool(resultMP) + result := vector.NewFunctionResultWrapper(types.T_int64.ToType(), resultMP) + defer result.Free() + + err = gateway.Execute(context.Background(), invocation, result, resultMP) + require.ErrorContains(t, err, "incomplete UDF FunctionRef") + require.Zero(t, resolver.calls, "a malformed typed plan must not probe an account-scoped artifact") +} + +func TestGatewayResolvesArtifactOnlyAfterHeaderValidation(t *testing.T) { + base := validInvocation() + resolver := &recordingArtifactResolver{source: base.Source} + gateway, err := NewGatewayWithArtifactStore(ClientConfig{ + Enabled: true, + AllowUnisolated: true, + ServerAddress: "127.0.0.1:50051", + }, resolver) + require.NoError(t, err) + + invocation := *base + invocation.Source = "" + resultMP := mpool.MustNewZeroNoFixed() + defer mpool.DeleteMPool(resultMP) + result := vector.NewFunctionResultWrapper(types.T_int64.ToType(), resultMP) + defer result.Free() + + require.NoError(t, gateway.Execute(context.Background(), &invocation, result, resultMP)) + require.Equal(t, 1, resolver.calls) + require.Equal(t, uint64(1), resolver.account) + require.Equal(t, "add", resolver.handler) + require.Equal(t, base.ArtifactDigest, resolver.digest) +} + +func TestValidateInvocationRejectsMismatchedInputBacking(t *testing.T) { + cases := []struct { + name string + make func(*mpool.MPool) *vector.Vector + want string + }{ + { + name: "nil backing", + make: func(*mpool.MPool) *vector.Vector { return nil }, + want: "has no backing vector", + }, + { + name: "wrong type", + make: func(mp *mpool.MPool) *vector.Vector { + input := vector.NewVec(types.T_float64.ToType()) + require.NoError(t, vector.AppendFixed(input, float64(1), false, mp)) + return input + }, + want: "does not match", + }, + { + name: "short flat vector", + make: func(mp *mpool.MPool) *vector.Vector { + input := vector.NewVec(types.T_int64.ToType()) + require.NoError(t, vector.AppendFixed(input, int64(1), false, mp)) + return input + }, + want: "expected at least 2", + }, + } + for _, test := range cases { + t.Run(test.name, func(t *testing.T) { + mp := mpool.MustNewZeroNoFixed() + t.Cleanup(func() { mpool.DeleteMPool(mp) }) + input := test.make(mp) + if input != nil { + t.Cleanup(func() { input.Free(mp) }) + } + invocation := validInvocation() + invocation.Length = 2 + invocation.Inputs = []*vector.Vector{input} + require.ErrorContains(t, validateInvocation(invocation), test.want) + }) + } +} + +func TestValidateInvocationAcceptsConstInputWithFrozenType(t *testing.T) { + mp := mpool.MustNewZeroNoFixed() + t.Cleanup(func() { mpool.DeleteMPool(mp) }) + input, err := vector.NewConstFixed(types.T_int64.ToType(), int64(7), 2, mp) + require.NoError(t, err) + t.Cleanup(func() { input.Free(mp) }) + + invocation := validInvocation() + invocation.Length = 2 + invocation.Inputs = []*vector.Vector{input} + require.NoError(t, validateInvocation(invocation)) +} + +func TestValidateInvocationBudgetRejectsBeforeOpen(t *testing.T) { + require.NoError(t, validateInvocationBudget(executionBudget{ + rows: 2, maxRows: 2, returnType: types.T_int64.ToType(), maxResultBytes: 32, + })) + require.ErrorContains(t, validateInvocationBudget(executionBudget{ + rows: 3, maxRows: 2, returnType: types.T_int64.ToType(), maxResultBytes: 32, + }), "invocation has 3 rows") + // Two int64 values plus the validity bitmap need more than sixteen bytes; + // this is rejected before OpenInvocation rather than after user code runs. + require.ErrorContains(t, validateInvocationBudget(executionBudget{ + rows: 2, maxRows: 2, returnType: types.T_int64.ToType(), maxResultBytes: 16, + }), "result reservation") +} + +func TestGatewayFeatureGateRejectsDisabledRuntime(t *testing.T) { + gateway, err := NewGateway(ClientConfig{}) + require.NoError(t, err) + + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + require.ErrorContains(t, gateway.CheckLanguageReady(ctx, udf.LanguagePython), "runtime is disabled") + require.ErrorContains(t, gateway.Execute(ctx, validInvocation(), nil, nil), "runtime is disabled") +} + +func TestValidateCapabilitiesRequiresWorkerInstanceLease(t *testing.T) { + response := capabilityResponse{ + ProtocolVersion: protocol.Version, + ABIContract: udf.PythonABIContract, + AdapterVersion: udf.PythonAdapterVersion, + SDKVersion: udf.PythonSDKVersion, + DefinitionSchemaVersion: udf.PythonDefinitionSchemaVersion, + PlanContractVersion: udf.PythonPlanContractVersion, + TypeDescriptorContract: udf.PythonTypeDescriptorContract, + TimezoneDatabaseVersion: currentTimezoneDatabaseVersion(), + Modes: []string{ModeScalar, ModeVector}, + NullPolicies: []string{NullCallHandler, NullReturnNull}, + WindowBatches: 1, + MaxExecutionFrameBytes: 1 << 30, + MaxHandlerProcesses: DefaultWorkerMaxHandlerProcesses, + MaxAccountHandlerProcesses: DefaultWorkerMaxAccountHandlers, + MaxOwnerHandlerProcesses: DefaultWorkerMaxOwnerHandlers, + } + require.ErrorContains(t, validateCapabilities(response), "contract does not match") + response.LeaseEpoch = 17 + require.NoError(t, validateCapabilities(response)) + response.MaxOwnerHandlerProcesses++ + require.ErrorContains(t, validateCapabilities(response), "contract does not match") +} + +func TestValidateActionAckCorrelatesTheRequestedFence(t *testing.T) { + request := protocol.Control{ + Kind: "AcknowledgeResults", + Tuple: validInvocation().Tuple, + AckSequence: 3, + } + ack := protocol.Control{Kind: "Ack", Tuple: request.Tuple, Status: statusOK, AckSequence: 3} + require.NoError(t, validateActionAck(request.Kind, request, ack)) + ack.AckSequence = 2 + require.ErrorContains(t, validateActionAck(request.Kind, request, ack), "ACK sequence") + + finish := protocol.Control{Kind: "AcknowledgeFinish", Tuple: request.Tuple, FinishID: "finish-1"} + finishAck := protocol.Control{Kind: "Ack", Tuple: request.Tuple, Status: statusOK, FinishID: "finish-1"} + require.NoError(t, validateActionAck(finish.Kind, finish, finishAck)) + finishAck.FinishID = "finish-2" + require.ErrorContains(t, validateActionAck(finish.Kind, finish, finishAck), "finish ID") +} + +func TestAcknowledgeFinishRetriesTheSameIdempotentRequest(t *testing.T) { + request := protocol.Control{ + Kind: "AcknowledgeFinish", + Tuple: validInvocation().Tuple, + FinishID: "finish-1", + } + client := &finishAckFlightClient{} + gateway := &Gateway{cfg: ClientConfig{RequestTimeout: time.Second}} + + require.NoError(t, gateway.acknowledgeFinish(context.Background(), client, request.Kind, request)) + require.Equal(t, 2, client.calls) + require.Len(t, client.actions, 2) + require.Equal(t, client.actions[0].Type, client.actions[1].Type) + require.Equal(t, client.actions[0].Body, client.actions[1].Body) +} + +func TestGatewayCloseIsTerminal(t *testing.T) { + gateway, err := NewGateway(ClientConfig{}) + require.NoError(t, err) + require.NoError(t, gateway.Close()) + require.ErrorIs(t, gateway.connect(), errGatewayClosed) + require.NoError(t, gateway.Close()) +} + +func TestGatewayFinishRejectsLateHalfStreamControls(t *testing.T) { + tuple := validInvocation().Tuple + for _, kind := range []string{"InputConsumed", "ResultSchema"} { + t.Run(kind, func(t *testing.T) { + sequence := protocol.Sequence{} + require.NoError(t, sequence.AcceptInput(1)) + require.NoError(t, sequence.EndInput(1)) + require.NoError(t, sequence.AcceptResult(1)) + require.NoError(t, sequence.AcknowledgeResults(1)) + stream := &gatewayResultStream{results: []*flight.FlightData{ + gatewayControl(t, kind, tuple, func(control *protocol.Control) { + if kind == "InputConsumed" { + control.Sequence = 1 + control.ReleasedBytes = 1 + control.ReleasedBatches = 1 + } + }), + }} + gateway := &Gateway{cfg: ClientConfig{RequestTimeout: time.Second}} + err := gateway.receiveFinish(context.Background(), nil, stream, tuple, 1, 1, &sequence) + require.ErrorContains(t, err, "arrived after result stream was drained") + }) + } +} + +func TestGatewayFinishWaitsForExchangeEOF(t *testing.T) { + tuple := validInvocation().Tuple + sequence := protocol.Sequence{} + require.NoError(t, sequence.AcceptInput(1)) + require.NoError(t, sequence.EndInput(1)) + require.NoError(t, sequence.AcceptResult(1)) + require.NoError(t, sequence.AcknowledgeResults(1)) + finish := gatewayControl(t, "Finish", tuple, func(value *protocol.Control) { + value.Status = statusOK + value.FinishID = "finish-1" + value.LastSequence = 1 + value.LastResultSequence = 1 + }) + release := make(chan struct{}) + waiting := make(chan struct{}) + stream := &gatedGatewayResultStream{ + results: []*flight.FlightData{finish}, + release: release, + waiting: waiting, + } + gateway := &Gateway{cfg: ClientConfig{RequestTimeout: time.Second}} + done := make(chan error, 1) + go func() { + done <- gateway.receiveFinish(context.Background(), &finishAckFlightClient{}, stream, tuple, 1, 1, &sequence) + }() + + <-waiting + select { + case err := <-done: + require.Failf(t, "Finish returned before the exchange reached EOF", "%v", err) + default: + } + close(release) + require.NoError(t, <-done) +} + +func TestGatewayRejectsArrowBodyOnControlFrame(t *testing.T) { + tuple := validInvocation().Tuple + sequence := protocol.Sequence{} + require.NoError(t, sequence.AcceptInput(1)) + require.NoError(t, sequence.EndInput(1)) + require.NoError(t, sequence.AcceptResult(1)) + require.NoError(t, sequence.AcknowledgeResults(1)) + control := gatewayControl(t, "Finish", tuple, func(value *protocol.Control) { + value.Status = statusOK + value.FinishID = "finish-1" + value.LastSequence = 1 + value.LastResultSequence = 1 + }) + control.DataBody = []byte("hidden Arrow payload") + gateway := &Gateway{cfg: ClientConfig{RequestTimeout: time.Second}} + err := gateway.receiveFinish( + context.Background(), nil, + &gatewayResultStream{results: []*flight.FlightData{control}}, + tuple, 1, 1, &sequence, + ) + require.ErrorContains(t, err, "unexpected Arrow data") +} + +func TestReceiveResultBatchRejectsMalformedProtocolProgress(t *testing.T) { + tuple := validInvocation().Tuple + resultBatch := func(controlTuple protocol.FencingTuple) *flight.FlightData { + return &flight.FlightData{ + DataHeader: []byte("record"), + AppMetadata: func() []byte { + encoded, err := protocol.MarshalControl(protocol.Control{ + Kind: "ResultBatch", Tuple: controlTuple, Sequence: 1, + }) + require.NoError(t, err) + return encoded + }(), + } + } + inputConsumed := func(sequence uint64, releasedBytes int64, releasedBatches uint64) *flight.FlightData { + return gatewayControl(t, "InputConsumed", tuple, func(control *protocol.Control) { + control.Sequence = sequence + control.ReleasedBytes = releasedBytes + control.ReleasedBatches = releasedBatches + }) + } + for _, tc := range []struct { + name string + results []*flight.FlightData + recvErrors []error + initialSchema bool + schemaReady bool + want string + }{ + {name: "EOF before result", want: "ended before result sequence"}, + {name: "receive failure", recvErrors: []error{errors.New("injected receive failure")}, want: "receive result"}, + {name: "nil FlightData", results: []*flight.FlightData{nil}, want: "empty Flight result"}, + {name: "empty FlightData", results: []*flight.FlightData{{}}, want: "empty Flight result"}, + { + name: "control frame with Arrow body", + results: []*flight.FlightData{func() *flight.FlightData { + data := inputConsumed(1, 1, 1) + data.DataBody = []byte("unexpected") + return data + }()}, + want: "control frame contains an Arrow body", + }, + {name: "invalid control metadata", results: []*flight.FlightData{{AppMetadata: []byte("not-json")}}, want: "invalid character"}, + { + name: "changed tuple", + results: []*flight.FlightData{gatewayControl(t, "InputConsumed", protocol.FencingTuple{ + AccountID: tuple.AccountID + 1, StatementID: tuple.StatementID, GroupID: tuple.GroupID, + GroupEpoch: tuple.GroupEpoch, InvocationID: tuple.InvocationID, LeaseEpoch: tuple.LeaseEpoch, + }, func(control *protocol.Control) { + control.Sequence = 1 + control.ReleasedBytes = 1 + control.ReleasedBatches = 1 + })}, + want: "result tuple changed", + }, + {name: "result schema control before schema", results: []*flight.FlightData{gatewayControl(t, "ResultSchema", tuple)}, want: "invalid result schema metadata"}, + { + name: "input sequence mismatch", + results: []*flight.FlightData{inputConsumed(2, 1, 1)}, + want: "was consumed while waiting for result", + }, + { + name: "invalid released credits", + results: []*flight.FlightData{inputConsumed(1, 2048, 1)}, + want: "released invalid bytes/batches", + }, + {name: "worker error control", results: []*flight.FlightData{gatewayControl(t, "Error", tuple, func(control *protocol.Control) { + control.Status = "ERROR" + control.Reason = "handler failed" + })}, want: "worker error: handler failed"}, + {name: "Finish before result", results: []*flight.FlightData{gatewayControl(t, "Finish", tuple, func(control *protocol.Control) { + control.FinishID = "finish-1" + control.Status = statusOK + control.LastSequence = 1 + control.LastResultSequence = 0 + })}, want: "Finish arrived before result"}, + {name: "unknown control", results: []*flight.FlightData{{AppMetadata: []byte(`{"version":1,"kind":"Unknown","tuple":{"statement_id":"stmt","group_id":"group","group_epoch":1,"invocation_id":"invocation","lease_epoch":1}}`)}}, want: "unsupported control kind"}, + { + name: "schema frame contains a body", + results: []*flight.FlightData{{DataHeader: []byte("schema"), DataBody: []byte("body")}}, + want: "result schema contains a body", + }, + { + name: "schema metadata has wrong tuple", + results: []*flight.FlightData{func() *flight.FlightData { + data := gatewayControl(t, "ResultSchema", tuple) + data.DataHeader = []byte("schema") + otherTuple := tuple + otherTuple.AccountID++ + data.AppMetadata, _ = protocol.MarshalControl(protocol.Control{Kind: "ResultSchema", Tuple: otherTuple}) + return data + }()}, + want: "invalid result schema metadata", + }, + { + name: "record omitted schema metadata", + results: []*flight.FlightData{ + {DataHeader: []byte("schema")}, + resultBatch(tuple), + }, + want: "result schema metadata was not received", + }, + { + name: "result before input consumed", + initialSchema: true, + schemaReady: true, + results: []*flight.FlightData{resultBatch(tuple)}, + want: "arrived before InputConsumed", + }, + { + name: "duplicate input consumed", + results: []*flight.FlightData{ + inputConsumed(1, 1, 1), + inputConsumed(1, 1, 1), + }, + want: "was consumed more than once", + }, + } { + t.Run(tc.name, func(t *testing.T) { + mp := mpool.MustNewZeroNoFixed() + defer mpool.DeleteMPool(mp) + result := vector.NewFunctionResultWrapper(types.T_int64.ToType(), mp) + defer result.Free() + returnDescriptor, err := NewTypeDescriptor(types.T_int64.ToType()) + require.NoError(t, err) + sequence := protocol.Sequence{} + require.NoError(t, sequence.AcceptInput(1)) + var schemaFrame *ArrowFrame + if tc.initialSchema { + schemaFrame = &ArrowFrame{Header: []byte("schema")} + } + schemaReady := tc.schemaReady + gateway := &Gateway{cfg: ClientConfig{MaxBatchBytes: 1024}} + _, err = gateway.receiveResultBatch( + context.Background(), nil, + &scriptedGatewayResultStream{results: tc.results, errors: tc.recvErrors}, + tuple, 1, 1, &schemaFrame, &schemaReady, returnDescriptor, result, mp, &sequence, + ) + require.ErrorContains(t, err, tc.want) + }) + } +} + +func TestReceiveResultBatchValidatesArrowPayloadAndResultAck(t *testing.T) { + type encodedResult struct { + frames []ArrowFrame + descriptor TypeDescriptor + } + encodeResult := func(t *testing.T, fieldName string) encodedResult { + t.Helper() + descriptor, err := NewTypeDescriptor(types.T_int64.ToType()) + require.NoError(t, err) + field, err := descriptor.Field(fieldName) + require.NoError(t, err) + builder := array.NewInt64Builder(memory.NewGoAllocator()) + builder.AppendValues([]int64{17}, nil) + values := builder.NewInt64Array() + defer values.Release() + record := array.NewRecordBatch(arrow.NewSchema([]arrow.Field{field}, nil), []arrow.Array{values}, 1) + defer record.Release() + frames, err := EncodeRecordBatch(record, DefaultMaxBatchBytes) + require.NoError(t, err) + return encodedResult{frames: frames, descriptor: descriptor} + } + + tuple := validInvocation().Tuple + encoded := encodeResult(t, "result") + wrongName := encodeResult(t, "other") + validAck, err := protocol.MarshalControl(protocol.Control{ + Kind: "Ack", Tuple: tuple, AckSequence: 1, Status: statusOK, + }) + require.NoError(t, err) + wrongAck, err := protocol.MarshalControl(protocol.Control{ + Kind: "Ack", Tuple: tuple, AckSequence: 2, Status: statusOK, + }) + require.NoError(t, err) + resultMetadata, err := protocol.MarshalControl(protocol.Control{ + Kind: "ResultBatch", Tuple: tuple, Sequence: 1, + }) + require.NoError(t, err) + schemaMetadata, err := protocol.MarshalControl(protocol.Control{ + Kind: "ResultSchema", Tuple: tuple, + }) + require.NoError(t, err) + inputConsumedMetadata, err := protocol.MarshalControl(protocol.Control{ + Kind: "InputConsumed", Tuple: tuple, Sequence: 1, ReleasedBytes: 1, ReleasedBatches: 1, + }) + require.NoError(t, err) + + for _, tc := range []struct { + name string + frames []ArrowFrame + descriptor TypeDescriptor + expectedRows int64 + maxBatchBytes int64 + maxResultBytes int64 + resultMetadata []byte + ackResponse []byte + ackError error + resultAlreadySeen bool + wantError string + }{ + {name: "valid one-row result is appended and acknowledged", frames: encoded.frames, descriptor: encoded.descriptor, expectedRows: 1, maxBatchBytes: DefaultMaxBatchBytes, resultMetadata: resultMetadata, ackResponse: validAck}, + {name: "malformed result metadata", frames: encoded.frames, descriptor: encoded.descriptor, expectedRows: 1, maxBatchBytes: DefaultMaxBatchBytes, resultMetadata: []byte("not-json"), wantError: "invalid character"}, + {name: "result sequence does not match input", frames: encoded.frames, descriptor: encoded.descriptor, expectedRows: 1, maxBatchBytes: DefaultMaxBatchBytes, resultMetadata: func() []byte { + metadata, marshalErr := protocol.MarshalControl(protocol.Control{Kind: "ResultBatch", Tuple: tuple, Sequence: 2}) + require.NoError(t, marshalErr) + return metadata + }(), wantError: "unexpected result sequence"}, + {name: "duplicate result sequence", frames: encoded.frames, descriptor: encoded.descriptor, expectedRows: 1, maxBatchBytes: DefaultMaxBatchBytes, resultMetadata: resultMetadata, resultAlreadySeen: true, wantError: "sequence violation"}, + {name: "corrupt Arrow record body", frames: func() []ArrowFrame { + frames := append([]ArrowFrame(nil), encoded.frames...) + frames[1].Body = []byte("not an Arrow body") + return frames + }(), descriptor: encoded.descriptor, expectedRows: 1, maxBatchBytes: DefaultMaxBatchBytes, resultMetadata: resultMetadata, wantError: "decode result"}, + {name: "unexpected row count", frames: encoded.frames, descriptor: encoded.descriptor, expectedRows: 2, maxBatchBytes: DefaultMaxBatchBytes, resultMetadata: resultMetadata, wantError: "result batch row count"}, + {name: "unexpected field name", frames: wrongName.frames, descriptor: wrongName.descriptor, expectedRows: 1, maxBatchBytes: DefaultMaxBatchBytes, resultMetadata: resultMetadata, wantError: "field has unexpected name"}, + {name: "descriptor mismatch", frames: encoded.frames, descriptor: func() TypeDescriptor { + descriptor, descriptorErr := NewTypeDescriptor(types.T_int32.ToType()) + require.NoError(t, descriptorErr) + return descriptor + }(), expectedRows: 1, maxBatchBytes: DefaultMaxBatchBytes, resultMetadata: resultMetadata, wantError: "Arrow type int64 does not match int32"}, + {name: "complete IPC payload exceeds limit", frames: encoded.frames, descriptor: encoded.descriptor, expectedRows: 1, maxBatchBytes: 1, resultMetadata: resultMetadata, wantError: "exceeds"}, + {name: "materialized result exceeds invocation budget", frames: encoded.frames, descriptor: encoded.descriptor, expectedRows: 1, maxBatchBytes: DefaultMaxBatchBytes, maxResultBytes: 1, resultMetadata: resultMetadata, wantError: "invocation result exceeds"}, + {name: "result ACK response lost", frames: encoded.frames, descriptor: encoded.descriptor, expectedRows: 1, maxBatchBytes: DefaultMaxBatchBytes, resultMetadata: resultMetadata, ackError: errors.New("injected ACK response loss"), wantError: "injected ACK response loss"}, + {name: "result ACK sequence mismatch", frames: encoded.frames, descriptor: encoded.descriptor, expectedRows: 1, maxBatchBytes: DefaultMaxBatchBytes, resultMetadata: resultMetadata, ackResponse: wrongAck, wantError: "ACK sequence 2, expected 1"}, + } { + t.Run(tc.name, func(t *testing.T) { + mp := mpool.MustNewZeroNoFixed() + defer mpool.DeleteMPool(mp) + result := vector.NewFunctionResultWrapper(types.T_int64.ToType(), mp) + defer result.Free() + require.NoError(t, result.PreExtendAndReset(int(tc.expectedRows))) + sequence := protocol.Sequence{} + require.NoError(t, sequence.AcceptInput(1)) + require.NoError(t, sequence.EndInput(1)) + if tc.resultAlreadySeen { + require.NoError(t, sequence.AcceptResult(1)) + } + schema := &flight.FlightData{DataHeader: tc.frames[0].Header, AppMetadata: schemaMetadata} + consumed := &flight.FlightData{AppMetadata: inputConsumedMetadata} + record := &flight.FlightData{ + DataHeader: tc.frames[1].Header, DataBody: tc.frames[1].Body, + AppMetadata: tc.resultMetadata, + } + stream := &gatewayResultStream{results: []*flight.FlightData{schema, consumed, record}} + client := &resultAckFlightClient{response: tc.ackResponse, err: tc.ackError} + gateway := &Gateway{cfg: ClientConfig{ + MaxBatchBytes: tc.maxBatchBytes, MaxInvocationResultBytes: tc.maxResultBytes, + }} + schemaFrame := (*ArrowFrame)(nil) + schemaReady := false + rows, callErr := gateway.receiveResultBatch( + context.Background(), client, stream, tuple, 1, tc.expectedRows, + &schemaFrame, &schemaReady, tc.descriptor, result, mp, &sequence, + ) + if tc.wantError != "" { + require.ErrorContains(t, callErr, tc.wantError) + return + } + require.NoError(t, callErr) + require.Equal(t, 1, rows) + require.Equal(t, []int64{17}, vector.MustFixedColNoTypeCheck[int64](result.GetResultVector())) + lastInput, lastResult, ackedResult, inputEnded := sequence.State() + require.Equal(t, uint64(1), lastInput) + require.Equal(t, uint64(1), lastResult) + require.Equal(t, uint64(1), ackedResult) + require.True(t, inputEnded) + }) + } +} + +func TestFreezeResultFramesFreezesBothPartsAndChargesTotal(t *testing.T) { + header := []byte("record-header") + body := []byte("record-body") + headerSnapshot, bodySnapshot, err := freezeResultFrames(header, body, int64(len(header)+len(body))) + require.NoError(t, err) + require.NoError(t, headerSnapshot.Validate(len(header), headerSnapshot.Digest())) + require.NoError(t, bodySnapshot.Validate(len(body), bodySnapshot.Digest())) + + header[0] = 'X' + body[0] = 'Y' + require.Equal(t, "record-header", string(headerSnapshot.TrustedBytes())) + require.Equal(t, "record-body", string(bodySnapshot.TrustedBytes())) + + _, _, err = freezeResultFrames(header, body, int64(len(header)+len(body)-1)) + require.ErrorContains(t, err, "exceeds") +} + +func TestChooseInputBatchBoundsEncodingAttemptsAndPropagatesErrors(t *testing.T) { + frame := ArrowFrame{Header: []byte("schema"), Body: []byte("record")} + t.Run("full candidate avoids a search when it fits", func(t *testing.T) { + var attempts []int64 + got, err := chooseInputBatchWithFullCandidate(8, 64, func(rows int64) ([]ArrowFrame, error) { + attempts = append(attempts, rows) + return []ArrowFrame{frame}, nil + }, true) + require.NoError(t, err) + require.Equal(t, int64(8), got.Rows) + require.Equal(t, []ArrowFrame{frame}, got.Frames) + require.Equal(t, []int64{8}, attempts) + }) + + t.Run("size limit uses bounded exponential and binary search", func(t *testing.T) { + var attempts []int64 + got, err := chooseInputBatchWithFullCandidate(10, 64, func(rows int64) ([]ArrowFrame, error) { + attempts = append(attempts, rows) + if rows > 5 { + return nil, errArrowBatchTooLarge + } + return []ArrowFrame{frame}, nil + }, true) + require.NoError(t, err) + require.Equal(t, int64(5), got.Rows) + require.Equal(t, []int64{10, 1, 2, 4, 8, 6, 5}, attempts) + }) + + t.Run("non-size errors do not trigger retries", func(t *testing.T) { + wantErr := errors.New("injected Arrow encoder failure") + attempts := 0 + _, err := chooseInputBatchWithFullCandidate(4, 64, func(int64) ([]ArrowFrame, error) { + attempts++ + return nil, wantErr + }, true) + require.ErrorIs(t, err, wantErr) + require.Equal(t, 1, attempts) + }) + + t.Run("one row larger than the byte limit is rejected", func(t *testing.T) { + got, err := chooseInputBatch(4, 1, func(int64) ([]ArrowFrame, error) { + return nil, errArrowBatchTooLarge + }) + require.ErrorIs(t, err, errArrowBatchTooLarge) + require.Zero(t, got.Rows) + }) +} diff --git a/pkg/udf/python/supervisor.go b/pkg/udf/python/supervisor.go new file mode 100644 index 0000000000000..b8b143c7610f3 --- /dev/null +++ b/pkg/udf/python/supervisor.go @@ -0,0 +1,164 @@ +// Copyright 2026 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 python + +import ( + "errors" + "os" + "os/exec" + "path/filepath" + "sync" + + "github.com/matrixorigin/matrixone/pkg/udf/udferr" + "github.com/matrixorigin/matrixone/pkg/util/errutil" + + "github.com/matrixorigin/matrixone/pkg/logutil" +) + +var errSupervisorClosing = udferr.New("python udf worker is shutting down") + +type Supervisor struct { + cfg Config + mu sync.Mutex + cmd *exec.Cmd + done chan struct{} + lastErr error + closing bool +} + +func NewSupervisor(cfg Config) (*Supervisor, error) { + if err := cfg.Validate(); err != nil { + return nil, err + } + return &Supervisor{cfg: cfg}, nil +} + +func (s *Supervisor) Start() error { + s.mu.Lock() + defer s.mu.Unlock() + if s.closing { + return errSupervisorClosing + } + if s.cmd != nil { + return nil + } + workerPath := s.cfg.Path + if !filepath.IsAbs(workerPath) { + cwd, err := os.Getwd() + if err != nil { + return err + } + workerPath = filepath.Join(cwd, workerPath) + } + workerPath = filepath.Join(workerPath, "worker.py") + if _, err := os.Stat(workerPath); err != nil { + return err + } + executable := s.cfg.Python + if executable == "" { + executable = "python" + } + cmd := exec.Command(executable, "-u", workerPath, "--address="+s.cfg.Address) + prepareSupervisorCommand(cmd) + // The MatrixOne service owns process logging. Inheriting stderr keeps + // worker diagnostics in the service log and avoids an unbounded, per-start + // file beside the binary. + cmd.Stdout, cmd.Stderr = os.Stderr, os.Stderr + if err := cmd.Start(); err != nil { + return err + } + done := make(chan struct{}) + // Keep the notification channel after Wait clears cmd. A very short-lived + // worker can exit between cmd.Start and the caller's Done call; dropping the + // channel in that window would make the service role miss an unexpected + // worker exit entirely. The next successful Start replaces it with a fresh + // channel. + s.cmd, s.done = cmd, done + s.lastErr = nil + go s.wait(cmd, done) + logutil.Infof("started Python UDF worker: %s", cmd.String()) + return nil +} + +func (s *Supervisor) wait(cmd *exec.Cmd, done chan struct{}) { + err := cmd.Wait() + unplanned := false + s.mu.Lock() + if s.cmd == cmd { + // Keep the terminal state transition and Done close under the same lock. + // Otherwise Start can observe cmd == nil in the small interval after + // Wait clears it but before the old Done channel is closed, and launch a + // replacement while a concurrent Close is still waiting for the old + // worker. + s.cmd = nil + s.lastErr = err + // Close marks the supervisor as closing before killing the process + // group. Keep the exit error available through Err(), but do not report + // an intentional SIGKILL as an unexpected worker failure. + unplanned = !s.closing + } + close(done) + s.mu.Unlock() + if err != nil && unplanned { + logutil.Errorf("Python UDF worker exited: %v", err) + } +} + +// Done returns the exit notification for the currently running worker. The +// channel is captured after Start and is closed exactly once by wait. A caller +// that owns the service role can therefore observe an unexpected worker exit +// independently of the normal shutdown context. +func (s *Supervisor) Done() <-chan struct{} { + s.mu.Lock() + defer s.mu.Unlock() + return s.done +} + +// Err returns the exit error for the most recently completed worker. It must +// be read after the channel returned by Done has closed. A nil error means the +// process exited with status zero; the service layer still treats that as an +// unexpected exit while the role is running. +func (s *Supervisor) Err() error { + s.mu.Lock() + defer s.mu.Unlock() + return s.lastErr +} + +func (s *Supervisor) Close() error { + s.mu.Lock() + cmd, done := s.cmd, s.done + if cmd != nil || done != nil { + s.closing = true + } + s.mu.Unlock() + var closeErr error + if cmd != nil { + if err := killSupervisorProcess(cmd); err != nil && !errors.Is(err, os.ErrProcessDone) { + closeErr = errutil.Wrapf(err, "stop Python UDF worker") + } + } + if done != nil { + <-done + } + // Keep Start fenced until the worker observed by this Close has published + // its terminal notification. This also clears the fence when Close is + // called after an unexpected exit, where cmd is already nil. + s.mu.Lock() + if s.cmd == nil && s.done == done { + s.closing = false + } + s.mu.Unlock() + return closeErr +} diff --git a/pkg/udf/pythonservice/types.go b/pkg/udf/python/supervisor_process_other.go similarity index 57% rename from pkg/udf/pythonservice/types.go rename to pkg/udf/python/supervisor_process_other.go index 541418c2b0616..bd72579d202c6 100644 --- a/pkg/udf/pythonservice/types.go +++ b/pkg/udf/python/supervisor_process_other.go @@ -1,10 +1,10 @@ -// Copyright 2023 Matrix Origin +// Copyright 2026 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 +// 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, @@ -12,9 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -package pythonservice +//go:build !(aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris) -type PythonUdfServer interface { - Start() error - Close() error +package python + +import "os/exec" + +func prepareSupervisorCommand(*exec.Cmd) {} + +func killSupervisorProcess(cmd *exec.Cmd) error { + if cmd == nil || cmd.Process == nil { + return nil + } + return cmd.Process.Kill() } diff --git a/pkg/udf/python/supervisor_process_unix.go b/pkg/udf/python/supervisor_process_unix.go new file mode 100644 index 0000000000000..c0930ebcd7026 --- /dev/null +++ b/pkg/udf/python/supervisor_process_unix.go @@ -0,0 +1,40 @@ +// Copyright 2026 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. + +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris + +package python + +import ( + "errors" + "os/exec" + "syscall" +) + +func prepareSupervisorCommand(cmd *exec.Cmd) { + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} +} + +func killSupervisorProcess(cmd *exec.Cmd) error { + if cmd == nil || cmd.Process == nil { + return nil + } + if err := syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL); err != nil { + if errors.Is(err, syscall.ESRCH) { + return cmd.Process.Kill() + } + return err + } + return nil +} diff --git a/pkg/udf/python/supervisor_test.go b/pkg/udf/python/supervisor_test.go new file mode 100644 index 0000000000000..21fe77e45d69e --- /dev/null +++ b/pkg/udf/python/supervisor_test.go @@ -0,0 +1,112 @@ +// Copyright 2026 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 python + +import ( + "os" + "path/filepath" + "runtime" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestSupervisorCloseStopsTheCurrentWorkerBeforeReturning(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("worker supervisor test uses a POSIX executable script") + } + dir := t.TempDir() + workerPath := filepath.Join(dir, "worker.py") + require.NoError(t, os.WriteFile(workerPath, []byte("#!/bin/sh\nwhile :; do sleep 1; done\n"), 0o755)) + + supervisor, err := NewSupervisor(Config{Address: "127.0.0.1:0", Path: dir, Python: "/bin/sh"}) + require.NoError(t, err) + require.NoError(t, supervisor.Start()) + require.Eventually(t, func() bool { + supervisor.mu.Lock() + defer supervisor.mu.Unlock() + return supervisor.cmd != nil + }, time.Second, time.Millisecond) + require.NoError(t, supervisor.Close()) + require.Eventually(t, func() bool { + supervisor.mu.Lock() + defer supervisor.mu.Unlock() + return supervisor.cmd == nil && supervisor.done != nil + }, time.Second, time.Millisecond) + select { + case <-supervisor.Done(): + default: + t.Fatal("closed worker did not publish a completed notification") + } + + // A second start is only safe after the first wait has completed. This + // catches a Close implementation that clears cmd and returns before Wait. + require.NoError(t, supervisor.Start()) + require.NoError(t, supervisor.Close()) +} + +func TestSupervisorPublishesUnexpectedWorkerExit(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("worker supervisor test uses a POSIX executable script") + } + dir := t.TempDir() + workerPath := filepath.Join(dir, "worker.py") + require.NoError(t, os.WriteFile(workerPath, []byte("#!/bin/sh\nexit 17\n"), 0o755)) + + supervisor, err := NewSupervisor(Config{Address: "127.0.0.1:0", Path: dir, Python: "/bin/sh"}) + require.NoError(t, err) + require.NoError(t, supervisor.Start()) + done := supervisor.Done() + require.NotNil(t, done) + select { + case <-done: + case <-time.After(time.Second): + t.Fatal("worker exit was not published") + } + require.EqualError(t, supervisor.Err(), "exit status 17") + require.NoError(t, supervisor.Close()) +} + +func TestSupervisorKeepsImmediateExitObservable(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("worker supervisor test uses a POSIX executable script") + } + dir := t.TempDir() + workerDir := filepath.Join(dir, "worker") + require.NoError(t, os.Mkdir(workerDir, 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(workerDir, "worker.py"), []byte(""), 0o644)) + + script := filepath.Join(dir, "python") + require.NoError(t, os.WriteFile(script, []byte("#!/bin/sh\nexit 17\n"), 0o755)) + s, err := NewSupervisor(Config{ + Path: workerDir, + Python: script, + Address: "127.0.0.1:0", + }) + require.NoError(t, err) + require.NoError(t, s.Start()) + done := s.Done() + require.NotNil(t, done, "Start must publish an observable exit channel even for an immediate failure") + // Close must wait even when Wait has already cleared cmd but has not yet + // published the terminal notification. + require.NoError(t, s.Close()) + select { + case <-done: + case <-time.After(time.Second): + t.Fatal("immediate worker exit was not published") + } + require.Error(t, s.Err(), "a close that races an immediate worker exit must still publish the terminal process result") +} diff --git a/pkg/udf/python/testdata/type_descriptors.json b/pkg/udf/python/testdata/type_descriptors.json new file mode 100644 index 0000000000000..fcc281fc6ea61 --- /dev/null +++ b/pkg/udf/python/testdata/type_descriptors.json @@ -0,0 +1,29 @@ +[ + {"name":"bool","descriptor":{"type_id":10,"offset_width":32},"fingerprint":"7843e5e6f50016ce5cded0cf2c3c9d72134b84e33ef06680dfa1a249bb4c6595"}, + {"name":"int8","descriptor":{"type_id":20,"offset_width":32},"fingerprint":"43302f179a9dc14fc9ad45f5c2c785d7defb402c5e6da00d7f4735b4761b9cea"}, + {"name":"int16","descriptor":{"type_id":21,"offset_width":32},"fingerprint":"f346acef35ead4474900db739a1083b75d76439f4ac1e5ced6d4f2dd1bdcb748"}, + {"name":"int32","descriptor":{"type_id":22,"offset_width":32},"fingerprint":"069fd1e0859fa6d348313e71c9052087b867a486dae7b205906c85fb9b731a00"}, + {"name":"int64","descriptor":{"type_id":23,"offset_width":32},"fingerprint":"482d3c55b8a9d662c2b41326b3ca55cbae65153e662c47c4919ba020d006262b"}, + {"name":"uint8","descriptor":{"type_id":25,"offset_width":32},"fingerprint":"bfb8e804f99c17fda55421b073fecde0b8bb90fc857f21a43abe67de5a6b4e25"}, + {"name":"uint16","descriptor":{"type_id":26,"offset_width":32},"fingerprint":"373eace0b3ab82f3a5380113a75fecb56d4db68775e2e6aa70e0dc9779b918f7"}, + {"name":"uint32","descriptor":{"type_id":27,"offset_width":32},"fingerprint":"be2c02da94fda7b5ab40012b8d8b2f5a76312e1bdf7b93db26b067bd406f3dfc"}, + {"name":"uint64","descriptor":{"type_id":28,"offset_width":32},"fingerprint":"09088571e78bcb6fe65965e09a45886a9f15b58f6000a26de2214842ee9abaf8"}, + {"name":"float32","descriptor":{"type_id":30,"offset_width":32},"fingerprint":"8ade0ed866ef188cbe1dbfeadac487b54edf3e933e811637138db817222a3150"}, + {"name":"float64","descriptor":{"type_id":31,"offset_width":32},"fingerprint":"0121acc964077e1ada1525d4abca8011c297586bd8bb0c20614a8f8e21288b67"}, + {"name":"decimal64","descriptor":{"type_id":32,"width":18,"scale":6,"offset_width":32},"fingerprint":"0ee43811e24e92d89b801a19dbc4e2b4256e0688a08040b0995fde6f18ee6a20"}, + {"name":"decimal128","descriptor":{"type_id":33,"width":38,"scale":10,"offset_width":32},"fingerprint":"3690a03c5e39c40b2d53156c79ee2b9ccb4bea2d7ccb611a5ee8004bada46178"}, + {"name":"date","descriptor":{"type_id":50,"temporal_encoding":"sql_zero_struct","offset_width":32},"fingerprint":"8c401bde992eb173ca8aedca97dbd9f47453b7a860fae199ae0439307e858b4b"}, + {"name":"time","descriptor":{"type_id":51,"scale":6,"offset_width":32},"fingerprint":"8da0f51443fd6822c406d856627054978cef335020a4ba908d0ba41f5438dc93"}, + {"name":"datetime","descriptor":{"type_id":52,"scale":6,"temporal_encoding":"sql_zero_struct","offset_width":32},"fingerprint":"bc5e43e10dbd23c35fe3dea194d8f9a2c294f5ed3eb882e4f9fabd1768a6a618"}, + {"name":"timestamp","descriptor":{"type_id":53,"scale":6,"temporal_encoding":"sql_zero_struct","offset_width":32},"fingerprint":"c1e750fc23cb99b128f673299fa74580a1b8cf896ae64f2a8f7c73c01843f89b"}, + {"name":"char","descriptor":{"type_id":60,"width":16,"charset":3,"offset_width":32},"fingerprint":"1d158d5de44d8579a38f1267d8323ac5f787e83a9ce8a162d97ee744a44e5d60"}, + {"name":"varchar","descriptor":{"type_id":61,"width":64,"charset":3,"offset_width":32},"fingerprint":"eac25e693910d4a54f43e574304d8963c7ea0984c47a2ee1687f0fc4a6fac61f"}, + {"name":"text","descriptor":{"type_id":71,"offset_width":32},"fingerprint":"4d9f162421867c37eb20b22da43637a04e00c18d18a2d73d8018f7b3c2b56169"}, + {"name":"json","descriptor":{"type_id":62,"json_encoding":"canonical_text","offset_width":32},"fingerprint":"b156af5241a070ff80a287da19c46d1593dabee4fb5429f964452e711cd275eb"}, + {"name":"binary","descriptor":{"type_id":64,"width":8,"charset":1,"offset_width":32},"fingerprint":"18b158eee03eb5ea1e481c77fbb31a0201de6c68a27524cd208b0cb4ba09bbf3"}, + {"name":"varbinary","descriptor":{"type_id":65,"width":8,"charset":1,"offset_width":32},"fingerprint":"64406870de1c10859088bb512897cce6e80db525844780113bd9ffb5c3878f1e"}, + {"name":"blob","descriptor":{"type_id":70,"charset":1,"offset_width":32},"fingerprint":"d93ae4faac1d4c092a3fa35e7b8faf596eef890351aef5a7e9020c8fe0d2dd5d"}, + {"name":"uuid","descriptor":{"type_id":63,"offset_width":0},"fingerprint":"370e2939c178acee55aaae27a7bcf92937a203e2788e9e0140d84884be042780"}, + {"name":"vecf32","descriptor":{"type_id":224,"width":3,"offset_width":0},"fingerprint":"9134065bb458a203dae86dc150ec07d814e640ed3a39b04b474f7c9396e64ee9"}, + {"name":"vecf64","descriptor":{"type_id":225,"width":3,"offset_width":0},"fingerprint":"746241d9a35175c5d9fe14a61a9d951e1a97c371dba535c0fc1012f32412ec3c"} +] diff --git a/pkg/udf/python/worker/Dockerfile b/pkg/udf/python/worker/Dockerfile new file mode 100644 index 0000000000000..31d3a145d283d --- /dev/null +++ b/pkg/udf/python/worker/Dockerfile @@ -0,0 +1,52 @@ +# run from root path for debug: +# docker build -t mo-python-udf-worker -f ./pkg/udf/python/worker/Dockerfile ./pkg/udf/python/worker/ +# docker run -d --network host mo-python-udf-worker + +# Keep the worker's IANA database identical to the MatrixOne runtime image. +# The Python and Go base images are allowed to differ in language/runtime +# versions, but an IANA version mismatch would make the capability handshake +# reject the worker or, worse, let an IANA timezone resolve differently on +# the two sides of the boundary. +FROM matrixorigin/ubuntu:22.04 AS matrixone-tzdata + +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends tzdata \ + && rm -rf /var/lib/apt/lists/* + +FROM python:3.12-slim-bookworm + +RUN apt-get update \ + && apt-get install -y --no-install-recommends tini \ + && rm -rf /var/lib/apt/lists/* /usr/share/zoneinfo + +# Replace the complete database: Debian's posix symlinks cannot be overlaid +# safely with Ubuntu's directory layout, nor may stale zones be retained. +COPY --from=matrixone-tzdata /usr/share/zoneinfo/ /usr/share/zoneinfo/ + +RUN useradd -m -s /bin/bash mo + +WORKDIR /home/mo + +# only for debug +#RUN cp /etc/apt/sources.list.d/debian.sources /etc/apt/sources.list.d/ali.sources \ +# && sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list.d/ali.sources \ +# && apt-get update \ +# && apt-get install -y vim + +COPY requirements.txt worker.py watchdog.py healthcheck.py ./ + +RUN pip install --no-cache-dir -r requirements.txt + +# Fail the image build if the shared tzdata source was not copied into the +# worker image. The Go side performs the same version check at capability +# admission; this makes a broken worker image fail at build time as well. +RUN python -c 'from pathlib import Path; import worker; version = Path("/usr/share/zoneinfo/tzdata.zi").read_text(encoding="utf-8").splitlines()[0].removeprefix("# version ").strip(); assert version and version == worker.TIMEZONE_DATABASE_VERSION, (version, worker.TIMEZONE_DATABASE_VERSION)' + +USER mo + +EXPOSE 50051 + +# The worker waits for its direct children; init owns orphaned descendants +# after a handler leader exits. Keep that owner outside Python/Popen. +ENTRYPOINT [ "/usr/bin/tini", "--" ] +CMD [ "python", "-u", "worker.py", "--address=grpc://0.0.0.0:50051" ] diff --git a/pkg/udf/python/worker/healthcheck.py b/pkg/udf/python/worker/healthcheck.py new file mode 100644 index 0000000000000..05cfaab270bae --- /dev/null +++ b/pkg/udf/python/worker/healthcheck.py @@ -0,0 +1,33 @@ +"""Capability health check used by the container orchestrator.""" + +import json + +import pyarrow.flight as flight + + +PROTOCOL_VERSION = 1 +CAPABILITY_ACTION = "GetPythonCapabilities" + + +def check_capabilities( + address="grpc://127.0.0.1:50051", client_factory=flight.FlightClient +): + client = client_factory(address) + reader = client.do_action( + flight.Action(CAPABILITY_ACTION, b'{"protocol_version":1}') + ) + result = next(iter(reader), None) + if result is None: + raise RuntimeError("empty capability response") + capabilities = json.loads(bytes(result.body)) + if capabilities.get("protocol_version") != PROTOCOL_VERSION: + raise RuntimeError("unsupported capability protocol version") + return capabilities + + +def main(): + check_capabilities() + + +if __name__ == "__main__": + main() diff --git a/pkg/udf/python/worker/requirements.txt b/pkg/udf/python/worker/requirements.txt new file mode 100644 index 0000000000000..9a2bd0abbb48a --- /dev/null +++ b/pkg/udf/python/worker/requirements.txt @@ -0,0 +1,3 @@ +# Dependencies for the unisolated external worker adapter. This lock does +# not provide a sandbox or tenant isolation. +pyarrow==24.0.0 diff --git a/pkg/udf/python/worker/test_healthcheck.py b/pkg/udf/python/worker/test_healthcheck.py new file mode 100644 index 0000000000000..4cd0fa1dc843e --- /dev/null +++ b/pkg/udf/python/worker/test_healthcheck.py @@ -0,0 +1,64 @@ +import unittest + +import healthcheck + + +class _Result: + def __init__(self, body): + self.body = body + + +class _Reader: + def __init__(self, results): + self.results = iter(results) + + def __iter__(self): + return self + + def __next__(self): + return next(self.results) + + +class _Client: + def __init__(self, address, results): + self.address = address + self.results = results + self.action = None + + def do_action(self, action): + self.action = action + return _Reader(self.results) + + +class HealthcheckTest(unittest.TestCase): + def test_accepts_current_capability_protocol(self): + clients = [] + + def factory(address): + client = _Client( + address, [_Result(b'{"protocol_version":1}')] + ) + clients.append(client) + return client + + capabilities = healthcheck.check_capabilities( + "grpc://worker:50051", client_factory=factory + ) + + self.assertEqual(capabilities["protocol_version"], 1) + self.assertEqual(clients[0].address, "grpc://worker:50051") + self.assertEqual(clients[0].action.type, "GetPythonCapabilities") + self.assertEqual(clients[0].action.body, b'{"protocol_version":1}') + + def test_rejects_empty_or_unknown_protocol(self): + for response in (None, b'{"protocol_version":2}'): + def factory(address, response=response): + results = [] if response is None else [_Result(response)] + return _Client(address, results) + + with self.assertRaises(RuntimeError): + healthcheck.check_capabilities(client_factory=factory) + + +if __name__ == "__main__": + unittest.main() diff --git a/pkg/udf/python/worker/test_watchdog.py b/pkg/udf/python/worker/test_watchdog.py new file mode 100644 index 0000000000000..56d31f77a5cf7 --- /dev/null +++ b/pkg/udf/python/worker/test_watchdog.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +import importlib.util +import pathlib +import unittest +from unittest import mock + + +WATCHDOG_PATH = pathlib.Path(__file__).with_name("watchdog.py") +spec = importlib.util.spec_from_file_location("matrixone_python_watchdog", WATCHDOG_PATH) +watchdog = importlib.util.module_from_spec(spec) +spec.loader.exec_module(watchdog) + + +class WatchdogTest(unittest.TestCase): + @unittest.skipUnless(watchdog.os.name == "posix", "process-group watchdog") + def test_parent_watch_read_error_kills_process_group(self): + with ( + mock.patch.object(watchdog.os, "read", side_effect=OSError("closed")), + mock.patch.object(watchdog.os, "killpg") as killpg, + mock.patch.object(watchdog.os, "close"), + ): + watchdog._watch(17, 23) + + killpg.assert_called_once_with(23, watchdog.signal.SIGKILL) + + +if __name__ == "__main__": + unittest.main() diff --git a/pkg/udf/python/worker/test_worker.py b/pkg/udf/python/worker/test_worker.py new file mode 100644 index 0000000000000..3df7f07549055 --- /dev/null +++ b/pkg/udf/python/worker/test_worker.py @@ -0,0 +1,4273 @@ +#!/usr/bin/env python3 + +import datetime +import decimal +import errno +import io +import importlib.util +import json +import os +import pathlib +import pickle +import signal +import struct +import subprocess +import sys +import tempfile +import threading +import time +import types +import unittest +import uuid +from unittest import mock + +import pyarrow as pa +import pyarrow.flight as flight + + +WORKER_PATH = pathlib.Path(__file__).with_name("worker.py") +spec = importlib.util.spec_from_file_location("matrixone_python_worker", WORKER_PATH) +worker = importlib.util.module_from_spec(spec) +sys.modules[spec.name] = worker +spec.loader.exec_module(worker) + + +def complete_open_payload(payload): + """Build a current-contract Open payload for direct Flight tests.""" + payload = dict(payload) + payload.update( + { + "definition_schema_version": worker.DEFINITION_SCHEMA_VERSION, + "artifact_digest": worker._inline_artifact_digest( + payload["handler"], payload["source"] + ), + "environment_digest": worker._environment_digest(), + "max_invocation_rows": 1 << 20, + "max_invocation_result_bytes": 256 << 20, + } + ) + payload.setdefault("callsite_id", "python/test") + payload.setdefault("may_error", True) + payload.setdefault("security_mode", "INVOKER") + payload.setdefault("leakproof", False) + payload.setdefault( + "statement_context", + { + "contract_version": 1, + "statement_timestamp_utc": 1704067200123456, + "timezone_kind": "FIXED_OFFSET", + "timezone_offset_minutes": 480, + "sql_mode": ["ANSI", "STRICT_TRANS_TABLES"], + "current_database": "test", + "current_user": "root", + "current_role": "writer", + "connection_collation": "utf8mb4_bin", + }, + ) + payload.setdefault( + "security_frame", + { + "contract_version": 1, + "mode": "INVOKER", + "invoker_user_id": 0, + "invoker_role_id": 0, + "effective_user_id": 0, + "effective_role_id": 0, + }, + ) + try: + payload["definition_fingerprint"] = worker._definition_fingerprint(payload) + except ValueError: + # Some tests intentionally carry an invalid Arrow descriptor and must + # reach that validation branch before fingerprint computation. + payload["definition_fingerprint"] = "a" * 64 + return payload + + +def complete_definition_validation_payload(source="def f(ctx, value): return value", handler="f"): + descriptor = {"type_id": worker.INT64, "offset_width": 32} + payload = { + "account_id": 1, + "handler": handler, + "source": source, + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "abi_contract": worker.ABI_CONTRACT, + "adapter_version": worker.ADAPTER_VERSION, + "sdk_version": worker.SDK_VERSION, + "definition_schema_version": worker.DEFINITION_SCHEMA_VERSION, + "artifact_digest": worker._inline_artifact_digest(handler, source), + "environment_digest": worker._environment_digest(), + "definition_fingerprint": "", + "args": [descriptor], + "return": descriptor, + } + payload["definition_fingerprint"] = worker._definition_fingerprint(payload) + return payload + + +class WorkerContractTest(unittest.TestCase): + def test_definition_validation_compiles_without_executing_module_code(self): + with tempfile.TemporaryDirectory(prefix="mo-udf-definition-") as directory: + marker = pathlib.Path(directory) / "executed" + source = ( + "from pathlib import Path\n" + f"Path({str(marker)!r}).write_text('executed')\n" + "def f(ctx, value): return value\n" + ) + payload = complete_definition_validation_payload(source) + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + try: + results = list( + server.do_action( + None, + flight.Action( + "ValidatePythonDefinition", + json.dumps(payload, separators=(",", ":")).encode(), + ), + ) + ) + self.assertEqual(1, len(results)) + self.assertEqual("OK", json.loads(bytes(results[0].body))["status"]) + self.assertFalse(marker.exists(), "definition validation executed module code") + self.assertEqual({}, server._active) + self.assertEqual({}, server._terminal) + finally: + server.shutdown() + + def test_definition_validation_rejects_syntax_before_catalog_state(self): + payload = complete_definition_validation_payload("def f(ctx, value) return value") + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + try: + results = list( + server.do_action( + None, + flight.Action( + "ValidatePythonDefinition", + json.dumps(payload, separators=(",", ":")).encode(), + ), + ) + ) + response = json.loads(bytes(results[0].body)) + self.assertEqual("ERROR", response["status"]) + self.assertRegex(response["reason"], r"USER_CODE: Python syntax error at line 1, column") + self.assertEqual({}, server._active) + self.assertEqual({}, server._terminal) + finally: + server.shutdown() + + def test_definition_validation_rejects_missing_handler_before_catalog_state(self): + payload = complete_definition_validation_payload( + "def other(ctx, value): return value" + ) + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + try: + results = list( + server.do_action( + None, + flight.Action( + "ValidatePythonDefinition", + json.dumps(payload, separators=(",", ":")).encode(), + ), + ) + ) + response = json.loads(bytes(results[0].body)) + self.assertEqual("ERROR", response["status"]) + self.assertIn("not a module-level function", response["reason"]) + self.assertEqual({}, server._active) + self.assertEqual({}, server._terminal) + finally: + server.shutdown() + + def test_definition_validation_rejects_async_handler_before_catalog_state(self): + payload = complete_definition_validation_payload( + "async def f(ctx, value): return value" + ) + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + try: + results = list( + server.do_action( + None, + flight.Action( + "ValidatePythonDefinition", + json.dumps(payload, separators=(",", ":")).encode(), + ), + ) + ) + response = json.loads(bytes(results[0].body)) + self.assertEqual("ERROR", response["status"]) + self.assertIn("must be synchronous", response["reason"]) + self.assertEqual({}, server._active) + self.assertEqual({}, server._terminal) + finally: + server.shutdown() + + def test_definition_validation_rejects_boolean_schema_version(self): + payload = complete_definition_validation_payload() + payload["definition_schema_version"] = True + # A malformed sender could otherwise recompute its own malformed + # fingerprint and pass the later integrity check. The version domain + # must be rejected before that comparison. + payload["definition_fingerprint"] = worker._definition_fingerprint(payload) + with self.assertRaisesRegex(ValueError, "unsupported Python definition schema"): + worker._decode_definition_validation( + json.dumps(payload, separators=(",", ":")).encode() + ) + + def test_definition_validation_rejects_handler_rebound_after_definition(self): + payload = complete_definition_validation_payload( + "def f(ctx, value): return value\n" + "f = 1\n" + ) + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + try: + results = list( + server.do_action( + None, + flight.Action( + "ValidatePythonDefinition", + json.dumps(payload, separators=(",", ":")).encode(), + ), + ) + ) + response = json.loads(bytes(results[0].body)) + self.assertEqual("ERROR", response["status"]) + self.assertIn("not a module-level function", response["reason"]) + self.assertEqual({}, server._active) + self.assertEqual({}, server._terminal) + finally: + server.shutdown() + + def test_definition_validation_rejects_handler_rebound_in_module_control_flow(self): + sources = ( + "def f(ctx, value): return value\n" + "if True:\n" + " f = 1\n", + "def f(ctx, value): return value\n" + "for f in (1,):\n" + " pass\n", + "def f(ctx, value): return value\n" + "from math import pi as f\n", + "def f(ctx, value): return value\n" + "match {\"value\": 1, \"other\": 2}:\n" + " case {\"value\": value, **f}:\n" + " pass\n", + ) + for source in sources: + with self.subTest(source=source): + with self.assertRaisesRegex(ValueError, "not a module-level function"): + worker._validate_definition_syntax( + complete_definition_validation_payload(source) + ) + + # A same-named local in a nested function does not rebind the module + # handler and must remain valid. + worker._validate_definition_syntax( + complete_definition_validation_payload( + "def f(ctx, value):\n" + " def inner():\n" + " f = 1\n" + " return value\n" + ) + ) + + def test_definition_validation_accepts_bare_except(self): + worker._validate_definition_syntax( + complete_definition_validation_payload( + "def f(ctx, value): return value\n" + "try:\n" + " pass\n" + "except:\n" + " pass\n" + ) + ) + + def test_capability_advertises_worker_instance_lease(self): + encoded = worker._encode_capabilities( + {"protocol_version": worker.PROTOCOL_VERSION}, lease_epoch=17 + ) + value = json.loads(encoded) + self.assertEqual(17, value["lease_epoch"]) + self.assertEqual(worker.MAX_HANDLER_PROCESSES, value["max_handler_processes"]) + self.assertEqual( + worker.MAX_ACCOUNT_HANDLER_PROCESSES, + value["max_account_handler_processes"], + ) + self.assertEqual( + worker.MAX_OWNER_HANDLER_PROCESSES, + value["max_owner_handler_processes"], + ) + with self.assertRaisesRegex(ValueError, "invalid worker lease epoch"): + worker._encode_capabilities( + {"protocol_version": worker.PROTOCOL_VERSION}, lease_epoch=0 + ) + + def test_cleanup_reaper_can_be_stopped_independently(self): + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + try: + with server._pending_cleanup_condition: + server._ensure_pending_cleanup_thread_locked() + thread = server._pending_cleanup_thread + server._stop_pending_cleanup_reaper() + self.assertTrue(server._pending_cleanup_stopping) + self.assertIsNotNone(thread) + self.assertFalse(thread.is_alive()) + finally: + server.shutdown() + + def test_typed_statement_context_matches_canonical_handler_context(self): + typed = { + "contract_version": 1, + "statement_timestamp_utc": 1704067200123456, + "timezone_kind": "FIXED_OFFSET", + "timezone_offset_minutes": 510, + "sql_mode": ["ANSI", "STRICT_TRANS_TABLES"], + "current_database": "app", + "current_user": "alice", + "current_role": "writer", + "connection_collation": "utf8mb4_bin", + } + values = worker._typed_statement_context(typed) + statement = worker._statement_context(values) + self.assertEqual("alice", statement.current_user) + self.assertEqual(510, statement.session_timezone.offset_minutes) + self.assertEqual(("ANSI", "STRICT_TRANS_TABLES"), statement.sql_mode) + + def test_typed_statement_context_accepts_unix_epoch(self): + typed = { + "contract_version": 1, + "statement_timestamp_utc": 0, + "timezone_kind": "FIXED_OFFSET", + "timezone_offset_minutes": 0, + "sql_mode": [], + "current_user": "alice", + "connection_collation": "utf8mb4_bin", + } + values = worker._typed_statement_context(typed) + statement = worker._statement_context(values) + self.assertEqual( + datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc), + statement.statement_timestamp_utc, + ) + + def test_statement_timezone_kind_requires_canonical_spelling(self): + typed = { + "contract_version": 1, + "statement_timestamp_utc": 0, + "timezone_kind": "fixed_offset", + "timezone_offset_minutes": 0, + "sql_mode": [], + "current_user": "alice", + "connection_collation": "utf8mb4_bin", + } + with self.assertRaisesRegex(ValueError, "unsupported typed statement timezone"): + worker._typed_statement_context(typed) + + with self.assertRaisesRegex(ValueError, "unsupported timezone kind"): + worker._statement_context( + { + "statement_timestamp_utc": "0", + "session_timezone_kind": "fixed_offset", + "session_timezone_offset_minutes": "0", + "sql_mode": "[]", + "current_user": "alice", + "connection_collation": "utf8mb4_bin", + } + ) + + def test_typed_statement_context_rejects_timestamp_outside_int64(self): + typed = { + "contract_version": 1, + "statement_timestamp_utc": worker.MAX_INT64 + 1, + "timezone_kind": "FIXED_OFFSET", + "timezone_offset_minutes": 0, + "sql_mode": [], + "current_user": "alice", + "connection_collation": "utf8mb4_bin", + } + with self.assertRaisesRegex(ValueError, "invalid typed statement timestamp"): + worker._typed_statement_context(typed) + + with self.assertRaisesRegex(ValueError, "invalid statement_timestamp_utc"): + worker._statement_context( + { + "statement_timestamp_utc": str(worker.MIN_INT64 - 1), + "session_timezone_kind": "FIXED_OFFSET", + "session_timezone_offset_minutes": "0", + "sql_mode": "[]", + "current_user": "alice", + "connection_collation": "utf8mb4_bin", + } + ) + + def test_statement_context_matches_python_datetime_range(self): + for timestamp in ( + worker.MIN_STATEMENT_TIMESTAMP_UTC - 1, + worker.MAX_STATEMENT_TIMESTAMP_UTC + 1, + ): + typed = { + "contract_version": 1, + "statement_timestamp_utc": timestamp, + "timezone_kind": "FIXED_OFFSET", + "timezone_offset_minutes": 0, + "sql_mode": [], + "current_user": "alice", + "connection_collation": "utf8mb4_bin", + } + with self.assertRaisesRegex(ValueError, "invalid typed statement timestamp"): + worker._typed_statement_context(typed) + with self.assertRaisesRegex(ValueError, "invalid statement_timestamp_utc"): + worker._statement_context( + { + "statement_timestamp_utc": str(timestamp), + "session_timezone_kind": "FIXED_OFFSET", + "session_timezone_offset_minutes": "0", + "sql_mode": "[]", + "current_user": "alice", + "connection_collation": "utf8mb4_bin", + } + ) + + def test_typed_contract_versions_require_integer_wire_values(self): + typed_context = { + "contract_version": True, + "statement_timestamp_utc": 0, + "timezone_kind": "FIXED_OFFSET", + "timezone_offset_minutes": 0, + "sql_mode": [], + "current_user": "alice", + "connection_collation": "utf8mb4_bin", + } + with self.assertRaisesRegex(ValueError, "unsupported statement context contract"): + worker._typed_statement_context(typed_context) + + payload = { + "callsite_id": "python/1", + "may_error": True, + "security_mode": "INVOKER", + "leakproof": False, + "security_frame": { + "contract_version": True, + "mode": "INVOKER", + "invoker_user_id": 7, + "invoker_role_id": 8, + "effective_user_id": 7, + "effective_role_id": 8, + }, + } + with self.assertRaisesRegex(ValueError, "unsupported Python security frame"): + worker._validate_typed_call_contract(payload) + + def test_typed_routine_semantics_reject_partial_or_definer_contract(self): + payload = { + "callsite_id": "python/1", + "may_error": True, + "security_mode": "INVOKER", + "leakproof": False, + "security_frame": { + "contract_version": 1, + "mode": "INVOKER", + "invoker_user_id": 7, + "invoker_role_id": 8, + "effective_user_id": 7, + "effective_role_id": 8, + }, + } + worker._validate_typed_call_contract(payload) + payload["security_mode"] = "DEFINER" + with self.assertRaisesRegex(ValueError, "semantic contract"): + worker._validate_typed_call_contract(payload) + payload.pop("security_mode") + with self.assertRaisesRegex(ValueError, "incomplete typed routine semantic contract"): + worker._validate_typed_call_contract(payload) + + def test_typed_routine_semantics_rejects_non_uint32_principal(self): + payload = { + "callsite_id": "python/1", + "may_error": True, + "security_mode": "INVOKER", + "leakproof": False, + "security_frame": { + "contract_version": 1, + "mode": "INVOKER", + "invoker_user_id": worker.MAX_SECURITY_PRINCIPAL_ID + 1, + "invoker_role_id": 8, + "effective_user_id": worker.MAX_SECURITY_PRINCIPAL_ID + 1, + "effective_role_id": 8, + }, + } + with self.assertRaisesRegex(ValueError, "invalid Python security frame"): + worker._validate_typed_call_contract(payload) + + def test_handler_quota_uses_typed_effective_principal(self): + payload = complete_open_payload( + { + "function_ref": { + "account_id": 1, + "database_id": 2, + "function_id": 3, + "revision": 1, + "namespace_version": 1, + }, + "source": "def f(ctx, value): return value", + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "abi_contract": worker.ABI_CONTRACT, + "adapter_version": worker.ADAPTER_VERSION, + "sdk_version": worker.SDK_VERSION, + "args": [{"type_id": worker.INT64, "offset_width": 32}], + "return": {"type_id": worker.INT64, "offset_width": 32}, + "max_batch_bytes": 1 << 20, + "max_batch_rows": 1, + "handler_timeout_seconds": 1.0, + } + ) + payload["security_frame"].update( + { + "invoker_user_id": 23, + "invoker_role_id": 7, + "effective_user_id": 23, + "effective_role_id": 7, + } + ) + self.assertEqual("user:23/role:7", worker._handler_quota_owner(payload)) + payload["statement_context"]["current_user"] = "same-name-different-principal" + self.assertEqual("user:23/role:7", worker._handler_quota_owner(payload)) + + def test_exchange_rejects_old_demo_open_before_user_code(self): + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + fence = { + "account_id": 1, + "statement_id": "legacy-demo", + "group_id": "legacy-group", + "group_epoch": 1, + "invocation_id": "legacy-invocation", + "lease_epoch": 1, + } + descriptor = {"type_id": worker.INT64, "offset_width": 32} + payload = complete_open_payload( + { + "function_ref": { + "account_id": 1, + "database_id": 2, + "function_id": 3, + "revision": 1, + "namespace_version": 1, + }, + "source": "def f(ctx, x): return x", + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "abi_contract": worker.ABI_CONTRACT, + "adapter_version": worker.ADAPTER_VERSION, + "sdk_version": worker.SDK_VERSION, + "args": [descriptor], + "return": descriptor, + "max_batch_bytes": 1 << 20, + "max_batch_rows": 8, + "handler_timeout_seconds": 2, + } + ) + payload.pop("statement_context") + command = worker._encode_control( + {"kind": "OpenInvocation", "tuple": fence, "payload": payload} + ) + reader = types.SimpleNamespace(schema=None, read_chunk=lambda: None) + writer = types.SimpleNamespace( + begin=lambda schema: None, + write_metadata=lambda data: None, + write_with_metadata=lambda record, data: None, + ) + try: + with self.assertRaisesRegex(ValueError, "invocation payload is missing a required field"): + server.do_exchange( + types.SimpleNamespace(is_cancelled=lambda: False), + types.SimpleNamespace(command=command), + reader, + writer, + ) + self.assertFalse(server._active) + self.assertFalse(server._terminal) + finally: + server.shutdown() + + def test_exchange_rejects_missing_typed_statement_context_before_user_code(self): + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + fence = { + "account_id": 1, + "statement_id": "missing-context", + "group_id": "missing-context-group", + "group_epoch": 1, + "invocation_id": "missing-context-invocation", + "lease_epoch": 1, + } + descriptor = {"type_id": worker.INT64, "offset_width": 32} + payload = complete_open_payload( + { + "function_ref": { + "account_id": 1, + "database_id": 2, + "function_id": 3, + "revision": 1, + "namespace_version": 1, + }, + "source": "def f(ctx, x): return x", + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "abi_contract": worker.ABI_CONTRACT, + "adapter_version": worker.ADAPTER_VERSION, + "sdk_version": worker.SDK_VERSION, + "args": [descriptor], + "return": descriptor, + "max_batch_bytes": 1 << 20, + "max_batch_rows": 8, + "handler_timeout_seconds": 2, + } + ) + payload["statement_context"] = None + command = worker._encode_control( + {"kind": "OpenInvocation", "tuple": fence, "payload": payload} + ) + reader = types.SimpleNamespace(schema=None, read_chunk=lambda: None) + writer = types.SimpleNamespace( + begin=lambda schema: None, + write_metadata=lambda data: None, + write_with_metadata=lambda record, data: None, + ) + try: + with self.assertRaisesRegex(ValueError, "missing typed statement context"): + server.do_exchange( + types.SimpleNamespace(is_cancelled=lambda: False), + types.SimpleNamespace(command=command), + reader, + writer, + ) + self.assertFalse(server._active) + self.assertFalse(server._terminal) + finally: + server.shutdown() + + def test_worker_rejects_a_tuple_from_another_instance(self): + server = worker.RoutineFlightServer("grpc://127.0.0.1:0", lease_epoch=17) + with self.assertRaisesRegex(ValueError, "STALE_LEASE_EPOCH"): + server._require_current_lease((1, "statement", "group", 1, "invocation", 16)) + with self.assertRaisesRegex(ValueError, "invalid worker lease epoch"): + worker.RoutineFlightServer("grpc://127.0.0.1:0", lease_epoch=0) + + @unittest.skipUnless(os.name == "posix", "Flight shutdown reader lifetime test") + def test_flight_shutdown_does_not_race_native_input_reader(self): + """A native Flight reader must finish before its RPC is destroyed. + + FlightServerBase.shutdown waits for active callbacks; it does not + cancel a client that still owns the input direction. Close that + direction first, then shut down the server and verify the exchange + has no leftover native reader or ledger owner. The real client-side + cancellation path is covered by the Gateway integration test. + """ + entered = threading.Event() + reader_closed = threading.Event() + adapters = [] + original_reader = worker._ExchangeInputReader + + class NotifyingReader(original_reader): + def __init__(self, reader): + entered.set() + super().__init__(reader) + adapters.append(self) + + def close(self): + try: + return super().close() + finally: + reader_closed.set() + + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + client = flight.FlightClient(("127.0.0.1", server.port)) + server_thread = threading.Thread(target=server.serve, daemon=True) + server_thread.start() + writer = None + shutdown_error = [] + descriptor = {"type_id": worker.INT64, "offset_width": 32} + payload = complete_open_payload( + { + "function_ref": { + "account_id": 1, + "database_id": 2, + "function_id": 3, + "revision": 1, + "namespace_version": 1, + }, + "source": "def f(ctx, x): return x", + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "abi_contract": worker.ABI_CONTRACT, + "adapter_version": worker.ADAPTER_VERSION, + "sdk_version": worker.SDK_VERSION, + "args": [descriptor], + "return": descriptor, + "max_batch_bytes": 1 << 20, + "max_batch_rows": 8, + "handler_timeout_seconds": 60, + } + ) + fence = { + "account_id": 1, + "statement_id": "shutdown", + "group_id": "shutdown-group", + "group_epoch": 1, + "invocation_id": "shutdown-invocation", + "lease_epoch": 1, + } + + def control(kind, **fields): + return worker._encode_control({"kind": kind, "tuple": fence, **fields}) + + try: + with mock.patch.object(worker, "_ExchangeInputReader", NotifyingReader): + writer, reader = client.do_exchange( + flight.FlightDescriptor.for_command( + control("OpenInvocation", payload=payload) + ), + options=flight.FlightCallOptions(timeout=5), + ) + self.assertTrue(entered.wait(2), "exchange did not reach its input reader") + self.assertEqual(1, len(adapters)) + self.assertIsNone( + adapters[0]._thread, + "native Flight reader must stay on the RPC callback thread", + ) + # FlightServerBase.shutdown does not cancel an active client + # RPC. Close the client channel first; this is the same + # transport cancellation used by Gateway.Close and lets the + # native reader finish on its owning callback thread. + try: + writer.close() + except Exception: + # EndInput is intentionally omitted here; the worker may + # report the protocol error while closing the stream. + pass + client.close() + self.assertTrue( + reader_closed.wait(2), + "client cancellation did not finish the native reader", + ) + + def shutdown(): + try: + server.shutdown() + except Exception as exc: + shutdown_error.append(exc) + + shutdown_thread = threading.Thread(target=shutdown) + shutdown_thread.start() + shutdown_thread.join(5) + self.assertFalse( + shutdown_thread.is_alive(), + "server shutdown waited for an active exchange", + ) + self.assertEqual([], shutdown_error) + self.assertFalse(server._active) + with server._pending_cleanup_condition: + self.assertFalse(server._pending_cleanups) + finally: + if writer is not None: + try: + writer.close() + except Exception: + pass + client.close() + if server_thread.is_alive(): + server_thread.join(2) + + def test_inline_contract_rejects_external_handler_import(self): + with self.assertRaisesRegex(ValueError, "immutable artifact catalog"): + worker._load_handler("def add(ctx, value): return value", "module:add") + + def test_handler_load_revalidates_static_binding_before_exec(self): + with tempfile.TemporaryDirectory(prefix="mo-udf-handler-load-") as directory: + marker = pathlib.Path(directory) / "executed" + source = ( + "from pathlib import Path\n" + f"Path({str(marker)!r}).write_text('executed')\n" + "def f(ctx, value): return value\n" + "f = 1\n" + ) + with self.assertRaisesRegex(ValueError, "not a module-level function"): + worker._load_handler(source, "f") + self.assertFalse( + marker.exists(), + "execution must reject invalid handler binding before running module code", + ) + + def test_go_python_type_descriptor_fixtures(self): + fixture_path = WORKER_PATH.parent.parent / "testdata" / "type_descriptors.json" + fixtures = json.loads(fixture_path.read_text()) + self.assertGreaterEqual(len(fixtures), 20) + for fixture in fixtures: + descriptor = fixture["descriptor"] + field = worker._field("value", descriptor) + self.assertEqual( + fixture["fingerprint"], + worker._fingerprint(descriptor), + fixture["name"], + ) + self.assertEqual( + fixture["fingerprint"], + field.metadata[worker.TypeFingerprintKey].decode("ascii"), + fixture["name"], + ) + + def test_all_type_fixtures_round_trip_scalar_values_and_nulls(self): + fixture_path = WORKER_PATH.parent.parent / "testdata" / "type_descriptors.json" + fixtures = json.loads(fixture_path.read_text()) + values = { + "bool": False, + "int8": 1, + "int16": 1, + "int32": 1, + "int64": 1, + "uint8": 1, + "uint16": 1, + "uint32": 1, + "uint64": 1, + "float32": 1.25, + "float64": 1.25, + "decimal64": decimal.Decimal("0.123456"), + "decimal128": decimal.Decimal("0.0000000001"), + "date": worker.SqlDate(False, datetime.date(2024, 1, 2)), + "time": datetime.timedelta(microseconds=123456), + "datetime": worker.SqlDatetime( + False, datetime.datetime(2024, 1, 2, 3, 4, 5, 123456) + ), + "timestamp": worker.SqlTimestamp( + False, + datetime.datetime( + 2024, 1, 2, 3, 4, 5, 123456, tzinfo=datetime.timezone.utc + ), + ), + "char": "中", + "varchar": "中", + "text": "matrixone", + "json": '{"a":1,"b":[true,null]}', + "binary": b"\\x01\\x02", + "varbinary": b"\\x01\\x02", + "blob": b"\\x01\\x02", + "uuid": uuid.UUID("123e4567-e89b-12d3-a456-426614174000"), + "vecf32": memoryview(struct.pack("Q", 4) + b"\x01abc") + self.assertEqual( + (worker._HANDLER_RESPONSE_OK, b"abc"), session._take_response() + ) + self.assertEqual(bytearray(), session._response_buffer) + session._response_buffer = bytearray(struct.pack(">Q", 0)) + with self.assertRaisesRegex(ValueError, "empty response"): + session._take_response() + + def test_handler_response_frame_obeys_batch_byte_limit(self): + session = object.__new__(worker._HandlerProcessSession) + session._response_buffer = bytearray(struct.pack(">Q", 5) + b"\x01abcd") + with self.assertRaisesRegex(ValueError, "execution response is too large"): + session._take_response(4) + + def test_handler_response_frame_parts_keep_one_wire_frame(self): + stream = io.BytesIO() + worker._write_execution_frame_parts( + stream, (b"\x01", memoryview(b"abc")) + ) + self.assertEqual(struct.pack(">Q", 4) + b"\x01abc", stream.getvalue()) + + def test_handler_response_frame_parts_handle_short_writes(self): + class ShortWriter: + def __init__(self): + self.data = bytearray() + + def write(self, value): + value = bytes(value) + count = max(1, len(value) // 2) + self.data.extend(value[:count]) + return count + + def flush(self): + return None + + stream = ShortWriter() + worker._write_execution_frame_parts(stream, (b"\x01", b"abcdef")) + self.assertEqual( + struct.pack(">Q", 7) + b"\x01abcdef", bytes(stream.data) + ) + + def test_handler_process_accepts_schema_free_record_batch_messages(self): + descriptor = {"type_id": worker.INT64, "offset_width": 32} + schema = worker._schema_from_descriptors([descriptor], "arg") + result_schema = pa.schema([worker._field("result", descriptor)]) + batch = pa.RecordBatch.from_arrays( + [pa.array([1, 2], type=pa.int64())], schema=schema + ) + request = { + "source": "def f(ctx, x): return x + 1", + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "sdk_version": worker.SDK_VERSION, + "context": None, + "args": [descriptor], + "return": descriptor, + "max_batch_bytes": 1 << 20, + "arrow_encoding": worker.HANDLER_ARROW_RECORD_BATCH, + "input": worker._serialize_record_batch_message(batch), + } + output_wire = worker._run_handler_process(None, request, 3) + output = worker._deserialize_record_batch_message(output_wire, result_schema) + self.assertEqual([2, 3], output.column(0).to_pylist()) + + @unittest.skipUnless(os.name == "posix", "process-group cleanup race") + def test_handler_error_after_leader_exit_releases_quota(self): + """A normal handler error must not strand H while its leader exits.""" + descriptor = {"type_id": worker.INT64, "offset_width": 32} + batch = pa.RecordBatch.from_arrays( + [pa.array([1], type=pa.int64())], ["arg_0"] + ) + request = { + "source": "def f(ctx, x): return 1 / 0", + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "sdk_version": worker.SDK_VERSION, + "context": None, + "args": [descriptor], + "return": descriptor, + "max_batch_bytes": 1 << 20, + "input": worker._serialize_record_batch(batch), + } + quota = worker._HandlerQuota() + slots = threading.BoundedSemaphore(worker.MAX_HANDLER_PROCESSES) + for _ in range(worker.MAX_OWNER_HANDLER_PROCESSES * 3): + session = worker._HandlerProcessSession( + slots, + handler_quota=quota, + account_id=1, + owner_id="user:2/role:3", + ) + try: + with self.assertRaisesRegex( + ValueError, "USER_CODE: handler or runtime failed" + ): + session.run(None, request, 3) + # The response is sent before the handler child exits. Wait + # for that exact lifecycle edge instead of using a timing + # sleep, then exercise close() with an already exited leader. + session._process.wait(timeout=2) + finally: + session.close() + self.assertEqual(({}, {}), quota.counts()) + self.assertEqual(worker.MAX_HANDLER_PROCESSES, slots._value) + + def test_handler_burst_has_explicit_rollover_budget(self): + descriptor = {"type_id": worker.INT64, "offset_width": 32} + batch = pa.RecordBatch.from_arrays([pa.array([1], type=pa.int64())], ["arg_0"]) + request = { + "source": "def f(ctx, x): return x", + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "sdk_version": worker.SDK_VERSION, + "context": None, + "args": [descriptor], + "return": descriptor, + "max_batch_bytes": 1 << 20, + "input": worker._serialize_record_batch(batch), + } + old_batches = worker.DEFAULT_BURST_BATCHES + worker.DEFAULT_BURST_BATCHES = 1 + session = None + try: + session = worker._HandlerProcessSession() + output = worker._deserialize_record_batch(session.run(None, request, 3)) + self.assertEqual([1], output.column(0).to_pylist()) + self.assertTrue(session.should_rollover) + self.assertGreater(worker.DEFAULT_BURST_BYTES, 0) + self.assertGreater(worker.DEFAULT_BURST_SECONDS, 0) + finally: + if session is not None: + session.close() + worker.DEFAULT_BURST_BATCHES = old_batches + + def test_handler_slot_rejection_does_not_create_a_hidden_queue(self): + descriptor = {"type_id": worker.INT64, "offset_width": 32} + batch = pa.RecordBatch.from_arrays( + [pa.array([1], type=pa.int64())], ["arg_0"] + ) + request = { + "source": "def f(ctx, x): return x", + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "sdk_version": worker.SDK_VERSION, + "context": None, + "args": [descriptor], + "return": descriptor, + "max_batch_bytes": 1 << 20, + "input": worker._serialize_record_batch(batch), + } + slots = threading.BoundedSemaphore(1) + self.assertTrue(slots.acquire(blocking=False)) + try: + with self.assertRaisesRegex(ValueError, "handler execution slots are full"): + worker._run_handler_process(None, request, 1, slots) + finally: + slots.release() + + def test_handler_quota_is_scoped_by_account_and_owner(self): + quota = worker._HandlerQuota(max_account_handlers=2, max_owner_handlers=1) + first = quota.acquire(1, "alice") + with self.assertRaisesRegex(ValueError, "owner handler budget is full"): + quota.acquire(1, "alice") + + # The account still has capacity for a different owner. + second = quota.acquire(1, "bob") + with self.assertRaisesRegex(ValueError, "account handler budget is full"): + quota.acquire(1, "carol") + + # The same principal name in a different account has an independent + # budget; tenant identity is part of the owner key. + third = quota.acquire(2, "alice") + first.release() + first.release() + second.release() + third.release() + self.assertEqual(({}, {}), quota.counts()) + + def test_handler_quota_release_can_retry_after_counter_failure(self): + quota = worker._HandlerQuota(max_account_handlers=1, max_owner_handlers=1) + lease = quota.acquire(1, "alice") + real_release = quota._release + attempts = 0 + + def fail_once(account_id, owner_id): + nonlocal attempts + attempts += 1 + if attempts == 1: + raise RuntimeError("injected release failure") + return real_release(account_id, owner_id) + + with mock.patch.object(quota, "_release", side_effect=fail_once): + with self.assertRaisesRegex(RuntimeError, "injected release failure"): + lease.release() + lease.release() + self.assertEqual(({}, {}), quota.counts()) + + def test_handler_initialization_closes_partial_pipe_ownership(self): + real_pipe = os.pipe + for failure in ("second_pipe", "watchdog_dup"): + with self.subTest(failure=failure): + opened = [] + slots = threading.BoundedSemaphore(1) + quota = worker._HandlerQuota(max_account_handlers=1, max_owner_handlers=1) + + def allocate_pipe(): + if failure == "second_pipe" and opened: + raise OSError("injected pipe exhaustion") + pair = real_pipe() + opened.extend(pair) + return pair + + try: + with mock.patch.object(worker.os, "pipe", side_effect=allocate_pipe), mock.patch.object( + worker.os, "dup", side_effect=OSError("injected dup exhaustion") + ), mock.patch.object(worker.subprocess, "Popen") as popen: + with self.assertRaisesRegex(OSError, "injected"): + worker._HandlerProcessSession(slots, handler_quota=quota, account_id=1, owner_id="owner") + popen.assert_not_called() + self.assertEqual(({}, {}), quota.counts()) + self.assertTrue(slots.acquire(blocking=False)) + slots.release() + for fd in opened: + with self.assertRaises(OSError, msg=f"descriptor {fd} leaked after {failure}"): + os.fstat(fd) + finally: + for fd in opened: + try: + os.close(fd) + except OSError: + pass + + def test_handler_session_releases_account_owner_quota_idempotently(self): + quota = worker._HandlerQuota(max_account_handlers=2, max_owner_handlers=1) + session = worker._HandlerProcessSession( + threading.BoundedSemaphore(1), + handler_quota=quota, + account_id=9, + owner_id="alice", + ) + with self.assertRaisesRegex(ValueError, "owner handler budget is full"): + quota.acquire(9, "alice") + session.close() + session.close() + lease = quota.acquire(9, "alice") + lease.release() + + def test_handler_close_retries_failed_process_cleanup_without_losing_ownership(self): + slots = threading.BoundedSemaphore(1) + self.assertTrue(slots.acquire(blocking=False)) + session = object.__new__(worker._HandlerProcessSession) + session._slots = slots + session._slot_acquired = True + session._process = mock.Mock(stdin=mock.Mock()) + session._watchdog_process = mock.Mock() + session._selector = mock.Mock() + session._response_read_fd = -1 + session._parent_watch_write_fd = -1 + session._closed = False + session._close_lock = threading.Lock() + process = session._process + watchdog_process = session._watchdog_process + + try: + with mock.patch.object( + worker, + "_kill_execution_process", + side_effect=[RuntimeError("kill failed"), None], + ) as kill: + session.close() + self.assertIsNone(session._process) + self.assertIsNone(session._watchdog_process) + self.assertIsNone(session._selector) + self.assertFalse(session._slot_acquired) + self.assertEqual(2, kill.call_count) + self.assertTrue(slots.acquire(blocking=False)) + slots.release() + process.stdin.close.assert_called_once_with() + watchdog_process.wait.assert_called_once_with(timeout=0.1) + finally: + if session._slot_acquired: + slots.release() + + @unittest.skipUnless(os.name == "posix", "process-group cleanup fallback") + def test_process_cleanup_falls_back_to_owned_leader_on_group_permission_error(self): + process = mock.Mock(pid=1234) + process.poll.return_value = None + process.wait.return_value = 0 + + with mock.patch.object(worker.os, "killpg", side_effect=PermissionError): + worker._kill_execution_process(process) + + process.kill.assert_called_once_with() + process.wait.assert_called_once_with(timeout=1.0) + + @unittest.skipUnless(os.name == "posix", "process-group cleanup after leader exit") + def test_process_cleanup_kills_group_before_reaping_exited_leader(self): + process = mock.Mock(pid=1234) + process.poll.return_value = 7 + process.wait.return_value = 7 + + with mock.patch.object(worker.os, "killpg", side_effect=[None, None]) as killpg: + worker._kill_execution_process(process) + + self.assertEqual( + [mock.call(1234, 0), mock.call(1234, worker.signal.SIGKILL)], + killpg.call_args_list, + ) + process.kill.assert_not_called() + process.wait.assert_called_once_with(timeout=1.0) + + def test_handler_close_retains_process_for_a_later_cleanup_retry(self): + session = object.__new__(worker._HandlerProcessSession) + session._slots = threading.BoundedSemaphore(1) + session._slot_acquired = False + session._process = mock.Mock(stdin=None) + session._watchdog_process = None + session._selector = None + session._response_read_fd = -1 + session._parent_watch_write_fd = -1 + session._closed = False + session._close_lock = threading.Lock() + process = session._process + + with mock.patch.object( + worker, "_kill_execution_process", side_effect=RuntimeError("kill failed") + ) as kill: + with self.assertRaisesRegex(RuntimeError, "kill failed"): + session.close() + self.assertIs(process, session._process) + self.assertEqual(2, kill.call_count) + + with mock.patch.object(worker, "_kill_execution_process") as kill: + session.close() + kill.assert_called_once_with(process) + self.assertIsNone(session._process) + + def test_handler_close_keeps_h_slot_while_process_cleanup_is_pending(self): + slots = threading.BoundedSemaphore(1) + self.assertTrue(slots.acquire(blocking=False)) + session = object.__new__(worker._HandlerProcessSession) + session._slots = slots + session._slot_acquired = True + session._process = mock.Mock(stdin=mock.Mock()) + session._watchdog_process = None + session._selector = None + session._response_read_fd = -1 + session._parent_watch_write_fd = -1 + session._closed = False + session._close_lock = threading.Lock() + process = session._process + + try: + with mock.patch.object( + worker, "_kill_execution_process", side_effect=RuntimeError("kill failed") + ) as kill: + with self.assertRaisesRegex(RuntimeError, "kill failed"): + session.close() + self.assertEqual(2, kill.call_count) + # The pending reaper still owns the live child, so another + # invocation cannot acquire H merely because close() reported an + # error. + self.assertFalse(slots.acquire(blocking=False)) + self.assertTrue(session._slot_acquired) + self.assertIs(process, session._process) + + with mock.patch.object(worker, "_kill_execution_process") as kill: + session.close() + kill.assert_called_once_with(process) + self.assertFalse(session._slot_acquired) + self.assertIsNone(session._process) + self.assertTrue(slots.acquire(blocking=False)) + slots.release() + finally: + if session._slot_acquired: + slots.release() + + def test_exchange_construction_failure_retains_cleanup_owner(self): + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + self.addCleanup(server.shutdown) + slots = server._handler_slots = threading.BoundedSemaphore(1) + quota = server._handler_quota = worker._HandlerQuota(1, 1) + allow_kill = threading.Event() + process = mock.Mock(pid=1234, stdin=mock.Mock()) + watchdog = mock.Mock() + construction_error = OSError(errno.EMFILE, "selector exhausted") + descriptor = {"type_id": worker.INT64, "offset_width": 32} + payload = complete_open_payload({ + "function_ref": {"account_id": 1, "database_id": 2, "function_id": 3, + "revision": 1, "namespace_version": 1}, + "source": "def f(ctx, x): return x + 1", "handler": "f", + "mode": worker.MODE_SCALAR, "null_policy": worker.NULL_CALL, + "abi_contract": worker.ABI_CONTRACT, + "adapter_version": worker.ADAPTER_VERSION, "sdk_version": worker.SDK_VERSION, + "args": [descriptor], "return": descriptor, + "max_batch_bytes": 1 << 20, "max_batch_rows": 8, + "handler_timeout_seconds": 10, + }) + fence = {"account_id": 1, "statement_id": "construction", + "group_id": "construction", "group_epoch": 1, + "invocation_id": "failed", "lease_epoch": 1} + batch = pa.RecordBatch.from_arrays( + [pa.array([7], type=pa.int64())], + schema=pa.schema([worker._field("arg_0", descriptor)]), + ) + controls, results = [], [] + + def exchange(): + key = worker._tuple_key(fence) + + def control(kind, **fields): + return worker._encode_control({"kind": kind, "tuple": fence, **fields}) + + chunks = iter([ + types.SimpleNamespace(data=batch, app_metadata=control("InputBatch", sequence=1)), + types.SimpleNamespace(data=None, app_metadata=control("EndInput", last_sequence=1)), + ]) + + def metadata(data): + value = worker._decode_control(data) + controls.append(value) + if value["kind"] == "Finish": + server._active[key].ack_finish(value["finish_id"]) + + def output(record, data): + results.append(record.column(0).to_pylist()) + server._active[key].ack_result(worker._decode_control(data)["sequence"]) + + server.do_exchange( + None, types.SimpleNamespace(command=control("OpenInvocation", payload=payload)), + types.SimpleNamespace(schema=batch.schema, read_chunk=lambda: next(chunks)), + types.SimpleNamespace(begin=lambda schema: None, + write_metadata=metadata, write_with_metadata=output), + ) + + def kill(child): + self.assertIs(child, process) + if not allow_kill.is_set(): + raise OSError("kill blocked") + + key = worker._tuple_key(fence) + owner = worker._handler_quota_owner(payload) + with mock.patch.object(worker.subprocess, "Popen", side_effect=[process, watchdog]), \ + mock.patch.object(worker.selectors, "DefaultSelector", side_effect=construction_error), \ + mock.patch.object(worker, "_kill_execution_process", side_effect=kill), \ + mock.patch.object(slots, "release", wraps=slots.release) as release_slot, \ + mock.patch.object(quota, "_release", wraps=quota._release) as release_quota: + try: + with self.assertRaises(OSError) as raised: + exchange() + self.assertIs(construction_error, raised.exception) + self.assertEqual("Error", controls[-1]["kind"]) + self.assertEqual([], results) + with server._pending_cleanup_condition: + self.assertEqual([key], list(server._pending_cleanups)) + session = server._pending_cleanups[key].handler_session + self.assertIs(process, session._process) + self.assertIn(key, server._active) + self.assertNotIn(key, server._terminal) + self.assertFalse(slots.acquire(blocking=False)) + self.assertEqual(({1: 1}, {(1, owner): 1}), quota.counts()) + release_slot.assert_not_called() + release_quota.assert_not_called() + with self.assertRaisesRegex(ValueError, "account handler budget is full"): + quota.acquire(1, owner) + + allow_kill.set() + with server._pending_cleanup_condition: + self.assertTrue(server._pending_cleanup_condition.wait_for( + lambda: not server._pending_cleanups, timeout=3 + ), "pending cleanup did not complete") + self.assertNotIn(key, server._active) + self.assertIn(key, server._terminal) + self.assertEqual(({}, {}), quota.counts()) + session.close() + release_slot.assert_called_once_with() + release_quota.assert_called_once_with(1, owner) + process.stdin.close.assert_called_once_with() + self.assertTrue(slots.acquire(blocking=False)) + slots.release() + finally: + allow_kill.set() + # Drain while the process doubles and kill hook remain installed, + # including after an early assertion failure. + with server._pending_cleanup_condition: + self.assertTrue(server._pending_cleanup_condition.wait_for( + lambda: not server._pending_cleanups, timeout=3 + ), "test cleanup did not drain") + + # A later actual exchange can acquire the returned budgets and execute. + fence.update(group_epoch=2, invocation_id="next") + exchange() + self.assertEqual([[8]], results) + self.assertEqual("Finish", controls[-1]["kind"]) + self.assertFalse(server._active) + self.assertEqual(({}, {}), quota.counts()) + self.assertTrue(slots.acquire(blocking=False)) + slots.release() + + def test_helper_construction_failure_transfers_cleanup_owner(self): + slots = threading.BoundedSemaphore(1) + process = mock.Mock(pid=1234, stdin=mock.Mock()) + error = OSError(errno.EMFILE, "selector exhausted") + with mock.patch.object(worker.subprocess, "Popen", return_value=process), \ + mock.patch.object(worker.selectors, "DefaultSelector", side_effect=error), \ + mock.patch.object(worker, "_kill_execution_process", side_effect=OSError("kill blocked")) as kill: + with self.assertRaises(worker._HandlerCleanupPending) as raised: + worker._run_handler_process(None, {}, 1, slots) + pending = raised.exception + try: + self.assertIs(error, pending.error) + self.assertIs(error, pending.__cause__) + self.assertIs(process, pending.session._process) + self.assertFalse(slots.acquire(blocking=False)) + self.assertEqual(2, kill.call_count) + finally: + kill.side_effect = None + pending.session.close() + pending.session.close() + self.assertTrue(slots.acquire(blocking=False)) + slots.release() + process.stdin.close.assert_called_once_with() + + def test_handler_cleanup_does_not_mask_execution_error(self): + session = mock.Mock() + session.run.side_effect = ValueError("USER_CODE: handler failed") + session.close.side_effect = RuntimeError("close failed") + with mock.patch.object(worker, "_HandlerProcessSession", return_value=session): + with self.assertRaises(worker._HandlerCleanupPending) as raised: + worker._run_handler_process(None, {}, 1) + self.assertIs(session.run.side_effect, raised.exception.error) + self.assertIs(session.run.side_effect, raised.exception.__cause__) + self.assertIs(session, raised.exception.session) + session.close.assert_called_once_with() + + def test_helper_success_with_failed_cleanup_transfers_owner(self): + session = mock.Mock() + session.close.side_effect = OSError("kill blocked") + with mock.patch.object(worker, "_HandlerProcessSession", return_value=session): + with self.assertRaises(worker._HandlerCleanupPending) as raised: + worker._run_handler_process(None, {}, 1) + self.assertIs(session.close.side_effect, raised.exception.error) + self.assertIs(session, raised.exception.session) + session.close.assert_called_once_with() + + def test_real_flight_half_close_delivers_delayed_float_result_and_finish(self): + """Exercise the worker through a real Flight client and server. + + EndInput is sent before the client starts reading results. The + worker must treat that as a normal input half-close, preserve the + result direction, validate a FLOAT64 result, and only finish after + both result and Finish acknowledgements have been accepted. + """ + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + client = flight.FlightClient(("127.0.0.1", server.port)) + server_thread = threading.Thread(target=server.serve, daemon=True) + server_thread.start() + writer = None + try: + fence = { + "account_id": 1, + "statement_id": "flight-contract", + "group_id": "flight-group", + "group_epoch": 1, + "invocation_id": "delayed-float", + "lease_epoch": 1, + } + int_descriptor = {"type_id": worker.INT64, "offset_width": 32} + float_descriptor = {"type_id": worker.FLOAT64, "offset_width": 32} + payload = complete_open_payload({ + "function_ref": {"account_id": 1, "database_id": 2, "function_id": 3, "revision": 1, "namespace_version": 1}, + "source": "def f(ctx, x): return float(x)", + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "abi_contract": worker.ABI_CONTRACT, + "adapter_version": worker.ADAPTER_VERSION, + "sdk_version": worker.SDK_VERSION, + "args": [int_descriptor], + "return": float_descriptor, + "max_batch_bytes": 1 << 20, + "max_batch_rows": 8, + "handler_timeout_seconds": 2, + }) + + def control(kind, **fields): + return worker._encode_control( + {"kind": kind, "tuple": fence, **fields} + ) + + command = control("OpenInvocation", payload=payload) + writer, reader = client.do_exchange( + flight.FlightDescriptor.for_command(command), + options=flight.FlightCallOptions(timeout=5), + ) + schema = pa.schema([worker._field("arg_0", int_descriptor)]) + writer.begin(schema) + batch = pa.RecordBatch.from_arrays( + [pa.array([1, 2], type=pa.int64())], schema=schema + ) + writer.write_with_metadata( + batch, control("InputBatch", sequence=1) + ) + writer.write_metadata(control("EndInput", last_sequence=1)) + writer.done_writing() + + saw_result = False + saw_finish = False + for _ in range(8): + chunk = reader.read_chunk() + self.assertIsNotNone(chunk) + if chunk.data is not None and chunk.app_metadata: + metadata = worker._decode_control(chunk.app_metadata) + if metadata["kind"] != "ResultBatch": + continue + saw_result = True + self.assertEqual([1.0, 2.0], chunk.data.column(0).to_pylist()) + list( + client.do_action( + flight.Action( + "AcknowledgeResults", + control("AcknowledgeResults", ack_sequence=1), + ) + ) + ) + continue + if chunk.app_metadata: + metadata = worker._decode_control(chunk.app_metadata) + if metadata["kind"] != "Finish": + continue + saw_finish = True + self.assertTrue(saw_result) + list( + client.do_action( + flight.Action( + "AcknowledgeFinish", + control( + "AcknowledgeFinish", + finish_id=metadata["finish_id"], + ), + ) + ) + ) + break + self.assertTrue(saw_result) + self.assertTrue(saw_finish) + finally: + if writer is not None: + try: + writer.close() + except Exception: + pass + client.close() + server.shutdown() + server_thread.join(3) + + def test_real_flight_reuses_handler_within_one_burst(self): + """A bounded invocation burst compiles the handler only once.""" + with tempfile.TemporaryDirectory(prefix="mo-udf-burst-") as artifact: + marker = pathlib.Path(artifact) / "loaded" + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + client = flight.FlightClient(("127.0.0.1", server.port)) + server_thread = threading.Thread(target=server.serve, daemon=True) + server_thread.start() + writer = None + try: + fence = { + "account_id": 1, + "statement_id": "flight-burst", + "group_id": "burst-group", + "group_epoch": 1, + "invocation_id": "reuse-handler", + "lease_epoch": 1, + } + descriptor = {"type_id": worker.INT64, "offset_width": 32} + payload = complete_open_payload({ + "function_ref": {"account_id": 1, "database_id": 2, "function_id": 3, "revision": 1, "namespace_version": 1}, + "source": ( + "import pathlib\n" + f"pathlib.Path({str(marker)!r}).write_text('loaded')\n" + "def f(ctx, x): return x + 1\n" + ), + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "abi_contract": worker.ABI_CONTRACT, + "adapter_version": worker.ADAPTER_VERSION, + "sdk_version": worker.SDK_VERSION, + "args": [descriptor], + "return": descriptor, + "max_batch_bytes": 1 << 20, + "max_batch_rows": 8, + "handler_timeout_seconds": 2, + }) + + def control(kind, **fields): + return worker._encode_control({"kind": kind, "tuple": fence, **fields}) + + writer, reader = client.do_exchange( + flight.FlightDescriptor.for_command( + control("OpenInvocation", payload=payload) + ), + options=flight.FlightCallOptions(timeout=5), + ) + schema = pa.schema([worker._field("arg_0", descriptor)]) + writer.begin(schema) + + def read_result(sequence, expected): + while True: + chunk = reader.read_chunk() + self.assertIsNotNone(chunk) + if not chunk.app_metadata: + continue + metadata = worker._decode_control(chunk.app_metadata) + if metadata["kind"] != "ResultBatch": + continue + self.assertEqual(sequence, metadata["sequence"]) + self.assertEqual(expected, chunk.data.column(0).to_pylist()) + list( + client.do_action( + flight.Action( + "AcknowledgeResults", + control("AcknowledgeResults", ack_sequence=sequence), + ) + ) + ) + return + + batch = pa.RecordBatch.from_arrays([pa.array([1], type=pa.int64())], schema=schema) + writer.write_with_metadata(batch, control("InputBatch", sequence=1)) + read_result(1, [2]) + writer.write_with_metadata(batch, control("InputBatch", sequence=2)) + read_result(2, [2]) + writer.write_metadata(control("EndInput", last_sequence=2)) + writer.done_writing() + while True: + chunk = reader.read_chunk() + self.assertIsNotNone(chunk) + if not chunk.app_metadata: + continue + metadata = worker._decode_control(chunk.app_metadata) + if metadata["kind"] != "Finish": + continue + list( + client.do_action( + flight.Action( + "AcknowledgeFinish", + control("AcknowledgeFinish", finish_id=metadata["finish_id"]), + ) + ) + ) + break + self.assertEqual("loaded", marker.read_text()) + finally: + if writer is not None: + try: + writer.close() + except Exception: + pass + client.close() + server.shutdown() + server_thread.join(3) + + def test_real_flight_finish_ack_response_loss_is_idempotent(self): + """An accepted Finish ACK remains SUCCESS when its RPC response is lost.""" + + class DropFirstFinishAckServer(worker.RoutineFlightServer): + def __init__(self, location): + super().__init__(location) + self.drop_first_finish_ack = True + self.terminalized = threading.Event() + + def _finish_invocation(self, key, state): + super()._finish_invocation(key, state) + self.terminalized.set() + + def do_action(self, context, action): + if action.type == "AcknowledgeFinish" and self.drop_first_finish_ack: + self.drop_first_finish_ack = False + list(super().do_action(context, action)) + raise RuntimeError("injected Finish ACK response loss") + yield from super().do_action(context, action) + + server = DropFirstFinishAckServer("grpc://127.0.0.1:0") + client = flight.FlightClient(("127.0.0.1", server.port)) + server_thread = threading.Thread(target=server.serve, daemon=True) + server_thread.start() + writer = None + retry_client = None + try: + fence = { + "account_id": 1, + "statement_id": "finish-response-loss", + "group_id": "finish-group", + "group_epoch": 1, + "invocation_id": "response-loss", + "lease_epoch": 1, + } + int_descriptor = {"type_id": worker.INT64, "offset_width": 32} + float_descriptor = {"type_id": worker.FLOAT64, "offset_width": 32} + payload = complete_open_payload({ + "function_ref": {"account_id": 1, "database_id": 2, "function_id": 3, "revision": 1, "namespace_version": 1}, + "source": "def f(ctx, x): return float(x)", + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "abi_contract": worker.ABI_CONTRACT, + "adapter_version": worker.ADAPTER_VERSION, + "sdk_version": worker.SDK_VERSION, + "args": [int_descriptor], + "return": float_descriptor, + "max_batch_bytes": 1 << 20, + "max_batch_rows": 8, + "handler_timeout_seconds": 2, + }) + + def control(kind, **fields): + return worker._encode_control({"kind": kind, "tuple": fence, **fields}) + + writer, reader = client.do_exchange( + flight.FlightDescriptor.for_command( + control("OpenInvocation", payload=payload) + ), + options=flight.FlightCallOptions(timeout=5), + ) + schema = pa.schema([worker._field("arg_0", int_descriptor)]) + writer.begin(schema) + batch = pa.RecordBatch.from_arrays( + [pa.array([7], type=pa.int64())], schema=schema + ) + writer.write_with_metadata(batch, control("InputBatch", sequence=1)) + writer.write_metadata(control("EndInput", last_sequence=1)) + writer.done_writing() + + while True: + chunk = reader.read_chunk() + self.assertIsNotNone(chunk) + if not chunk.app_metadata: + continue + metadata = worker._decode_control(chunk.app_metadata) + if metadata["kind"] == "ResultBatch": + self.assertEqual([7.0], chunk.data.column(0).to_pylist()) + list( + client.do_action( + flight.Action( + "AcknowledgeResults", + control("AcknowledgeResults", ack_sequence=1), + ) + ) + ) + continue + if metadata["kind"] != "Finish": + continue + finish_id = metadata["finish_id"] + with self.assertRaises(Exception): + list( + client.do_action( + flight.Action( + "AcknowledgeFinish", + control("AcknowledgeFinish", finish_id=finish_id), + ) + ) + ) + retry_client = flight.FlightClient(("127.0.0.1", server.port)) + retry_ack = list( + retry_client.do_action( + flight.Action( + "AcknowledgeFinish", + control("AcknowledgeFinish", finish_id=finish_id), + ) + ) + ) + self.assertTrue(retry_ack) + break + + key = worker._tuple_key(fence) + self.assertTrue(server.terminalized.wait(2)) + self.assertEqual(worker._TERMINAL_SUCCESS, server._terminal[key].outcome) + finally: + if writer is not None: + try: + writer.close() + except Exception: + pass + if retry_client is not None: + retry_client.close() + client.close() + server.shutdown() + server_thread.join(3) + + @unittest.skipUnless(os.name == "posix", "parent-death process-group test") + def test_worker_death_reaps_handler_process_group(self): + with tempfile.TemporaryDirectory(prefix="mo-udf-parent-death-") as artifact: + marker = pathlib.Path(artifact) / "handler-and-descendant.json" + relay_source = f''' +import importlib.util, pathlib, pyarrow as pa, sys, time +worker_path = pathlib.Path({str(WORKER_PATH)!r}) +spec = importlib.util.spec_from_file_location("relay_worker", worker_path) +worker = importlib.util.module_from_spec(spec) +sys.modules[spec.name] = worker +spec.loader.exec_module(worker) +descriptor = {{"type_id": worker.INT64, "offset_width": 32}} +batch = pa.RecordBatch.from_arrays([pa.array([1], type=pa.int64())], ["arg_0"]) +request = {{ + "source": {( + "import json, os, pathlib, subprocess, sys, time\n" + "def f(ctx, x):\n" + f" child = subprocess.Popen([sys.executable, '-c', 'import time; time.sleep(60)'], stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)\n" + f" marker = pathlib.Path({str(marker)!r})\n" + " temporary = marker.with_suffix('.tmp')\n" + " temporary.write_text(json.dumps(dict(handler_pid=os.getpid(), child_pid=child.pid, pgid=os.getpgrp())))\n" + " os.replace(temporary, marker)\n" + " time.sleep(60)\n" + " return x\n" + )!r}, + "handler": "f", "mode": worker.MODE_SCALAR, "null_policy": worker.NULL_CALL, + "sdk_version": worker.SDK_VERSION, "context": None, "args": [descriptor], + "return": descriptor, "max_batch_bytes": 1 << 20, + "input": worker._serialize_record_batch(batch), +}} +worker._run_handler_process(None, request, 60) +''' + relay = subprocess.Popen( + [sys.executable, "-c", relay_source], + stdin=subprocess.DEVNULL, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + close_fds=True, + ) + observed = None + + def process_is_running(pid): + try: + os.kill(pid, 0) + except ProcessLookupError: + return False + try: + status = subprocess.check_output( + ["ps", "-o", "stat=", "-p", str(pid)], + text=True, + stderr=subprocess.DEVNULL, + ).strip() + except (OSError, subprocess.CalledProcessError): + return True + return not status.startswith("Z") + + try: + deadline = time.monotonic() + 3 + while time.monotonic() < deadline and not marker.exists(): + if relay.poll() is not None: + break + time.sleep(0.01) + self.assertTrue(marker.exists(), "handler did not reach the death-watch barrier") + observed = json.loads(marker.read_text()) + relay.kill() + relay.wait(timeout=2) + + deadline = time.monotonic() + 3 + while time.monotonic() < deadline and any( + process_is_running(observed[key]) + for key in ("handler_pid", "child_pid") + ): + time.sleep(0.01) + self.assertFalse(process_is_running(observed["handler_pid"])) + self.assertFalse(process_is_running(observed["child_pid"])) + finally: + if relay.poll() is None: + relay.kill() + relay.wait(timeout=2) + if observed is not None and any( + process_is_running(observed[key]) for key in ("handler_pid", "child_pid") + ): + try: + os.killpg(observed["pgid"], signal.SIGKILL) + except ProcessLookupError: + pass + + @unittest.skipUnless(os.name == "posix", "independent group watchdog test") + def test_worker_death_reaps_descendant_after_handler_leader_exits(self): + """The worker watchdog remains responsible after the leader is gone.""" + with tempfile.TemporaryDirectory(prefix="mo-udf-leader-exit-") as artifact: + marker = pathlib.Path(artifact) / "handler-and-watchdog.json" + relay_source = f''' +import importlib.util, json, os, pathlib, pyarrow as pa, sys, time +worker_path = pathlib.Path({str(WORKER_PATH)!r}) +spec = importlib.util.spec_from_file_location("relay_worker_leader_exit", worker_path) +worker = importlib.util.module_from_spec(spec) +sys.modules[spec.name] = worker +spec.loader.exec_module(worker) +descriptor = {{"type_id": worker.INT64, "offset_width": 32}} +batch = pa.RecordBatch.from_arrays([pa.array([1], type=pa.int64())], ["arg_0"]) +request = {{ + "source": {( + "import json, os, pathlib, subprocess, sys\n" + "def f(ctx, x):\n" + f" child = subprocess.Popen([sys.executable, '-c', 'import time; time.sleep(60)'])\n" + f" marker = pathlib.Path({str(marker)!r})\n" + " temporary = marker.with_suffix('.tmp')\n" + " temporary.write_text(json.dumps(dict(handler_pid=os.getpid(), child_pid=child.pid, pgid=os.getpgrp())))\n" + " os.replace(temporary, marker)\n" + " os._exit(7)\n" + )!r}, + "handler": "f", "mode": worker.MODE_SCALAR, "null_policy": worker.NULL_CALL, + "sdk_version": worker.SDK_VERSION, "context": None, "args": [descriptor], + "return": descriptor, "max_batch_bytes": 1 << 20, + "input": worker._serialize_record_batch(batch), +}} +session = worker._HandlerProcessSession() +try: + session.run(None, request, 60) +except Exception: + marker = pathlib.Path({str(marker)!r}) + payload = json.loads(marker.read_text()) + payload["watchdog_pid"] = session._watchdog_process.pid + temporary = marker.with_suffix('.watchdog.tmp') + temporary.write_text(json.dumps(payload)) + os.replace(temporary, marker) + time.sleep(60) +''' + relay = subprocess.Popen( + [sys.executable, "-c", relay_source], + stdin=subprocess.DEVNULL, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + close_fds=True, + ) + observed = None + + def process_is_running(pid): + try: + os.kill(pid, 0) + except ProcessLookupError: + return False + try: + status = subprocess.check_output( + ["ps", "-o", "stat=", "-p", str(pid)], + text=True, + stderr=subprocess.DEVNULL, + ).strip() + except (OSError, subprocess.CalledProcessError): + return True + return not status.startswith("Z") + + try: + deadline = time.monotonic() + 3 + while time.monotonic() < deadline and not marker.exists(): + if relay.poll() is not None: + break + time.sleep(0.01) + self.assertTrue(marker.exists(), "handler did not exit after creating its descendant") + observed = json.loads(marker.read_text()) + self.assertTrue(process_is_running(observed["child_pid"])) + relay.kill() + relay.wait(timeout=2) + + deadline = time.monotonic() + 3 + while time.monotonic() < deadline and "watchdog_pid" not in observed: + if marker.exists(): + observed = json.loads(marker.read_text()) + if "watchdog_pid" not in observed: + time.sleep(0.01) + self.assertIn("watchdog_pid", observed, "watchdog did not register before leader exit") + while time.monotonic() < deadline and any( + process_is_running(observed[key]) + for key in ("child_pid", "watchdog_pid") + ): + time.sleep(0.01) + self.assertFalse(process_is_running(observed["child_pid"])) + self.assertFalse(process_is_running(observed["watchdog_pid"])) + finally: + if relay.poll() is None: + relay.kill() + relay.wait(timeout=2) + if observed is not None and process_is_running(observed["child_pid"]): + try: + os.killpg(observed["pgid"], signal.SIGKILL) + except ProcessLookupError: + pass + + @unittest.skipUnless(os.name == "posix", "handler process-group cleanup") + def test_parent_watch_read_error_kills_own_group_before_handler_exit(self): + with ( + mock.patch.object(worker.os, "read", side_effect=OSError("closed")), + mock.patch.object(worker.os, "getpgrp", return_value=23), + mock.patch.object(worker.os, "killpg") as killpg, + mock.patch.object(worker.os, "_exit", side_effect=SystemExit(137)), + ): + with self.assertRaises(SystemExit): + worker._watch_parent_liveness(17) + + killpg.assert_called_once_with(23, worker.signal.SIGKILL) + + def test_handler_stdout_cannot_inject_parent_protocol(self): + descriptor = {"type_id": worker.INT64, "offset_width": 32} + batch = pa.RecordBatch.from_arrays([pa.array([1], type=pa.int64())], ["arg_0"]) + request = { + "source": "import os\ndef f(ctx, x): os.write(1, b'\\x00' * 8); return x", + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "sdk_version": worker.SDK_VERSION, + "context": None, + "args": [descriptor], + "return": descriptor, + "max_batch_bytes": 1 << 20, + "input": worker._serialize_record_batch(batch), + } + result = worker._deserialize_record_batch( + worker._run_handler_process(None, request, 3) + ) + self.assertEqual([1], result.column(0).to_pylist()) + + def test_handler_does_not_inherit_parent_environment(self): + descriptor = {"type_id": worker.BOOL, "offset_width": 32} + batch = pa.RecordBatch.from_arrays( + [pa.array([True], type=pa.bool_())], ["arg_0"] + ) + request = { + "source": "import os;\ndef f(ctx, x): return 'MATRIXONE_TEST_SECRET' in os.environ", + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "sdk_version": worker.SDK_VERSION, + "context": None, + "args": [descriptor], + "return": descriptor, + "max_batch_bytes": 1 << 20, + "input": worker._serialize_record_batch(batch), + } + with mock.patch.dict(os.environ, {"MATRIXONE_TEST_SECRET": "must-not-leak"}, clear=False): + result = worker._deserialize_record_batch( + worker._run_handler_process(None, request, 3) + ) + self.assertEqual([False], result.column(0).to_pylist()) + + def test_handler_preserves_runtime_pythonpath(self): + descriptor = {"type_id": worker.BOOL, "offset_width": 32} + batch = pa.RecordBatch.from_arrays( + [pa.array([True], type=pa.bool_())], ["arg_0"] + ) + request = { + "source": ( + "import os\n" + "def f(ctx, x):\n" + " return os.environ.get('PYTHONPATH', '').startswith('matrixone-test-pythonpath')" + ), + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "sdk_version": worker.SDK_VERSION, + "context": None, + "args": [descriptor], + "return": descriptor, + "max_batch_bytes": 1 << 20, + "input": worker._serialize_record_batch(batch), + } + inherited = os.environ.get("PYTHONPATH", "") + runtime_path = "matrixone-test-pythonpath" + if inherited: + runtime_path += os.pathsep + inherited + with mock.patch.dict(os.environ, {"PYTHONPATH": runtime_path}, clear=False): + result = worker._deserialize_record_batch( + worker._run_handler_process(None, request, 3) + ) + self.assertEqual([True], result.column(0).to_pylist()) + + def test_handler_cannot_forge_completion_on_stdout(self): + descriptor = {"type_id": worker.INT64, "offset_width": 32} + batch = pa.RecordBatch.from_arrays([pa.array([77], type=pa.int64())], ["arg_0"]) + result_batch = pa.RecordBatch.from_arrays( + [pa.array([77], type=pa.int64())], ["result"] + ) + frame = struct.pack(">Q", len(bytes([worker._HANDLER_RESPONSE_OK]) + worker._serialize_record_batch(result_batch))) + frame += bytes([worker._HANDLER_RESPONSE_OK]) + worker._serialize_record_batch(result_batch) + request = { + "source": ( + "import os,time\n" + f"def f(ctx, x):\n os.write(1, {frame!r})\n" + " time.sleep(5)\n" + " raise RuntimeError('handler never returned success')\n" + ), + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "sdk_version": worker.SDK_VERSION, + "context": None, + "args": [descriptor], + "return": descriptor, + "max_batch_bytes": 1 << 20, + "input": worker._serialize_record_batch(batch), + } + with self.assertRaisesRegex(TimeoutError, "handler execution timeout"): + worker._run_handler_process(None, request, 0.1) + + def test_end_input_rejects_late_batch_without_running_handler(self): + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + fence = { + "account_id": 1, + "statement_id": "review", + "group_id": "group", + "group_epoch": 1, + "invocation_id": "late-input", + "lease_epoch": 1, + } + key = worker._tuple_key(fence) + descriptor = {"type_id": worker.INT64, "offset_width": 32} + batch = pa.RecordBatch.from_arrays( + [pa.array([1], type=pa.int64())], + schema=pa.schema([worker._field("arg_0", descriptor)]), + ) + payload = complete_open_payload({ + "function_ref": {"account_id": 1, "database_id": 2, "function_id": 3, "revision": 1, "namespace_version": 1}, + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "abi_contract": worker.ABI_CONTRACT, + "adapter_version": worker.ADAPTER_VERSION, + "sdk_version": worker.SDK_VERSION, + "args": [descriptor], + "return": descriptor, + "source": "def f(ctx, x): return x", + "handler": "f", + "max_batch_bytes": 1 << 20, + "max_batch_rows": 1024, + "handler_timeout_seconds": 2, + }) + messages = [] + + def control(kind, **fields): + return worker._encode_control(dict(kind=kind, tuple=fence, **fields)) + + chunks = iter( + [ + types.SimpleNamespace( + data=None, + app_metadata=control("EndInput", last_sequence=0), + ), + types.SimpleNamespace( + data=batch, + app_metadata=control("InputBatch", sequence=1), + ), + ] + ) + reader = types.SimpleNamespace(schema=batch.schema, read_chunk=lambda: next(chunks)) + + class Writer: + def begin(self, schema): + pass + + def write_metadata(self, data): + messages.append(worker._decode_control(data)) + + def write_with_metadata(self, record, data): + messages.append(worker._decode_control(data)) + + handler = mock.Mock() + try: + with mock.patch.object(worker, "_run_handler_process", handler): + with self.assertRaisesRegex(ValueError, "after EndInput"): + server.do_exchange( + types.SimpleNamespace(is_cancelled=lambda: False), + types.SimpleNamespace( + command=control("OpenInvocation", payload=payload) + ), + reader, + Writer(), + ) + finally: + server.shutdown() + self.assertEqual(0, handler.call_count) + + def test_cancel_interrupts_a_blocked_flight_input_reader(self): + """Cancellation must release a native read before exchange cleanup.""" + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + descriptor = {"type_id": worker.INT64, "offset_width": 32} + fence = { + "account_id": 1, + "statement_id": "blocked-reader", + "group_id": "blocked-reader-group", + "group_epoch": 1, + "invocation_id": "blocked-reader-invocation", + "lease_epoch": 1, + } + payload = complete_open_payload( + { + "function_ref": { + "account_id": 1, + "database_id": 2, + "function_id": 3, + "revision": 1, + "namespace_version": 1, + }, + "source": "def f(ctx, x): return x", + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "abi_contract": worker.ABI_CONTRACT, + "adapter_version": worker.ADAPTER_VERSION, + "sdk_version": worker.SDK_VERSION, + "args": [descriptor], + "return": descriptor, + "max_batch_bytes": 1 << 20, + "max_batch_rows": 1024, + "handler_timeout_seconds": 2, + } + ) + + class BlockingReader: + schema = None + + def __init__(self): + self.started = threading.Event() + self.released = threading.Event() + self.cancelled = threading.Event() + + def read_chunk(self): + self.started.set() + self.released.wait() + raise StopIteration + + def cancel(self): + self.cancelled.set() + self.released.set() + + class Writer: + def begin(self, schema): + pass + + def write_metadata(self, data): + pass + + def write_with_metadata(self, record, data): + pass + + reader = BlockingReader() + cancelled = threading.Event() + context = types.SimpleNamespace(is_cancelled=cancelled.is_set) + command = worker._encode_control( + {"kind": "OpenInvocation", "tuple": fence, "payload": payload} + ) + result = [] + + def run_exchange(): + try: + server.do_exchange( + context, + types.SimpleNamespace(command=command), + reader, + Writer(), + ) + except Exception as exc: # cancellation is the assertion + result.append(exc) + + thread = threading.Thread(target=run_exchange) + thread.start() + try: + self.assertTrue(reader.started.wait(2), "native reader did not block") + cancelled.set() + thread.join(2) + self.assertFalse(thread.is_alive(), "cancelled exchange remained blocked") + self.assertTrue(reader.cancelled.is_set(), "reader cancellation was not requested") + self.assertEqual(1, len(result)) + self.assertIsInstance(result[0], TimeoutError) + key = worker._tuple_key(fence) + self.assertNotIn(key, server._active) + self.assertEqual(worker._TERMINAL_CANCELLED, server._terminal[key].outcome) + finally: + if thread.is_alive(): + cancelled.set() + reader.cancel() + thread.join(2) + server.shutdown() + + def test_cancelled_chunk_handoff_cannot_start_handler(self): + """A chunk dequeued after cancel is rejected before handler admission.""" + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + descriptor = {"type_id": worker.INT64, "offset_width": 32} + fence = { + "account_id": 1, + "statement_id": "cancelled-handoff", + "group_id": "cancelled-handoff-group", + "group_epoch": 1, + "invocation_id": "cancelled-handoff-invocation", + "lease_epoch": 1, + } + payload = complete_open_payload( + { + "function_ref": { + "account_id": 1, + "database_id": 2, + "function_id": 3, + "revision": 1, + "namespace_version": 1, + }, + "source": "def f(ctx, x): return x", + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "abi_contract": worker.ABI_CONTRACT, + "adapter_version": worker.ADAPTER_VERSION, + "sdk_version": worker.SDK_VERSION, + "args": [descriptor], + "return": descriptor, + "max_batch_bytes": 1 << 20, + "max_batch_rows": 1024, + "handler_timeout_seconds": 2, + } + ) + batch = pa.RecordBatch.from_arrays( + [pa.array([1], type=pa.int64())], + schema=pa.schema([worker._field("arg_0", descriptor)]), + ) + control = worker._encode_control( + {"kind": "InputBatch", "tuple": fence, "sequence": 1} + ) + command = worker._encode_control( + {"kind": "OpenInvocation", "tuple": fence, "payload": payload} + ) + cancelled = threading.Event() + next_started = threading.Event() + release = threading.Event() + handler = mock.Mock() + + class GatedInput: + schema = batch.schema + + def __init__(self, _reader): + pass + + def next(self, _context): + next_started.set() + self.assert_release() + return types.SimpleNamespace(data=batch, app_metadata=control) + + def assert_release(self): + if not release.wait(2): + raise AssertionError("test did not release the input handoff") + + def close(self): + release.set() + + class Writer: + def begin(self, schema): + pass + + def write_metadata(self, data): + pass + + def write_with_metadata(self, record, data): + pass + + result = [] + thread = None + + def run_exchange(): + try: + server.do_exchange( + types.SimpleNamespace(is_cancelled=cancelled.is_set), + types.SimpleNamespace(command=command), + object(), + Writer(), + ) + except Exception as exc: + result.append(exc) + + try: + with mock.patch.object(worker, "_ExchangeInputReader", GatedInput), mock.patch.object( + worker, "_HandlerProcessSession", handler + ): + thread = threading.Thread(target=run_exchange) + thread.start() + self.assertTrue(next_started.wait(2), "input handoff did not start") + cancelled.set() + release.set() + thread.join(2) + self.assertFalse(thread.is_alive(), "cancelled handoff remained blocked") + self.assertEqual(1, len(result)) + self.assertIsInstance(result[0], TimeoutError) + handler.assert_not_called() + finally: + release.set() + if thread is not None and thread.is_alive(): + cancelled.set() + thread.join(2) + server.shutdown() + + def test_exchange_rejects_duplicate_open_control(self): + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + fence = { + "account_id": 1, + "statement_id": "review", + "group_id": "group", + "group_epoch": 1, + "invocation_id": "duplicate-open", + "lease_epoch": 1, + } + descriptor = {"type_id": worker.INT64, "offset_width": 32} + payload = complete_open_payload({ + "function_ref": {"account_id": 1, "database_id": 2, "function_id": 3, "revision": 1, "namespace_version": 1}, + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "abi_contract": worker.ABI_CONTRACT, + "adapter_version": worker.ADAPTER_VERSION, + "sdk_version": worker.SDK_VERSION, + "args": [descriptor], + "return": descriptor, + "source": "def f(ctx, x): return x", + "handler": "f", + "max_batch_bytes": 1 << 20, + "max_batch_rows": 1024, + "handler_timeout_seconds": 2, + }) + + def control(kind, **fields): + return worker._encode_control(dict(kind=kind, tuple=fence, **fields)) + + duplicate = control("OpenInvocation", payload=payload) + chunks = iter( + [ + types.SimpleNamespace(data=None, app_metadata=duplicate), + types.SimpleNamespace( + data=None, app_metadata=control("EndInput", last_sequence=1) + ), + ] + ) + reader = types.SimpleNamespace( + schema=None, read_chunk=lambda: next(chunks) + ) + + class Writer: + def begin(self, schema): + pass + + def write_metadata(self, data): + pass + + def write_with_metadata(self, record, data): + pass + + try: + with self.assertRaisesRegex(ValueError, "duplicate OpenInvocation"): + server.do_exchange( + types.SimpleNamespace(is_cancelled=lambda: False), + types.SimpleNamespace(command=duplicate), + reader, + Writer(), + ) + finally: + server.shutdown() + + def test_invalid_open_does_not_consume_terminal_ledger(self): + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + fence = { + "account_id": 1, + "statement_id": "review", + "group_id": "group", + "group_epoch": 1, + "invocation_id": "invalid-open", + "lease_epoch": 1, + } + payload = complete_open_payload({ + "function_ref": {"account_id": 1, "database_id": 2, "function_id": 3, "revision": 1, "namespace_version": 1}, + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "abi_contract": worker.ABI_CONTRACT, + "adapter_version": worker.ADAPTER_VERSION, + "sdk_version": worker.SDK_VERSION, + "args": [{"type_id": worker.INT64, "offset_width": 32}], + "return": {"type_id": 999, "offset_width": 32}, + "source": "def f(ctx, x): return x", + "handler": "f", + "max_batch_bytes": 1 << 20, + "max_batch_rows": 1024, + "handler_timeout_seconds": 2, + }) + command = worker._encode_control( + {"kind": "OpenInvocation", "tuple": fence, "payload": payload} + ) + reader = types.SimpleNamespace(schema=None, read_chunk=lambda: (_ for _ in ()).throw(StopIteration)) + writer = types.SimpleNamespace( + begin=lambda schema: None, + write_metadata=lambda data: None, + write_with_metadata=lambda record, data: None, + ) + key = worker._tuple_key(fence) + try: + with self.assertRaisesRegex(ValueError, "unsupported type id"): + server.do_exchange( + types.SimpleNamespace(is_cancelled=lambda: False), + types.SimpleNamespace(command=command), + reader, + writer, + ) + self.assertNotIn(key, server._active) + self.assertNotIn(key, server._terminal) + finally: + server.shutdown() + + def test_exchange_rejects_empty_input_frame(self): + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + fence = { + "account_id": 1, + "statement_id": "review", + "group_id": "group", + "group_epoch": 1, + "invocation_id": "empty-frame", + "lease_epoch": 1, + } + descriptor = {"type_id": worker.INT64, "offset_width": 32} + payload = complete_open_payload({ + "function_ref": {"account_id": 1, "database_id": 2, "function_id": 3, "revision": 1, "namespace_version": 1}, + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "abi_contract": worker.ABI_CONTRACT, + "adapter_version": worker.ADAPTER_VERSION, + "sdk_version": worker.SDK_VERSION, + "args": [descriptor], + "return": descriptor, + "source": "def f(ctx, x): return x", + "handler": "f", + "max_batch_bytes": 1 << 20, + "max_batch_rows": 1024, + "handler_timeout_seconds": 2, + }) + + def control(kind, **fields): + return worker._encode_control(dict(kind=kind, tuple=fence, **fields)) + + chunks = iter( + [ + types.SimpleNamespace(data=None, app_metadata=b""), + types.SimpleNamespace( + data=None, app_metadata=control("EndInput", last_sequence=0) + ), + ] + ) + reader = types.SimpleNamespace(schema=None, read_chunk=lambda: next(chunks)) + writer = types.SimpleNamespace( + begin=lambda schema: None, + write_metadata=lambda data: None, + write_with_metadata=lambda record, data: None, + ) + command = control("OpenInvocation", payload=payload) + try: + with mock.patch.object(worker._InvocationState, "wait_finish_ack"): + with self.assertRaisesRegex(ValueError, "empty input frame"): + server.do_exchange( + types.SimpleNamespace(is_cancelled=lambda: False), + types.SimpleNamespace(command=command), + reader, + writer, + ) + finally: + server.shutdown() + + def test_exchange_rejects_invalid_input_values_before_handler(self): + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + fence = { + "account_id": 1, + "statement_id": "review", + "group_id": "group", + "group_epoch": 1, + "invocation_id": "invalid-input-values", + "lease_epoch": 1, + } + descriptor = {"type_id": worker.VECF32, "width": 2, "offset_width": 0} + child = pa.array([1.0, None], type=pa.float32()) + invalid_vector = pa.FixedSizeListArray.from_arrays(child, 2) + batch = pa.RecordBatch.from_arrays( + [invalid_vector], + schema=pa.schema([worker._field("arg_0", descriptor)]), + ) + payload = complete_open_payload({ + "function_ref": {"account_id": 1, "database_id": 2, "function_id": 3, "revision": 1, "namespace_version": 1}, + "mode": worker.MODE_VECTOR, + "null_policy": worker.NULL_CALL, + "abi_contract": worker.ABI_CONTRACT, + "adapter_version": worker.ADAPTER_VERSION, + "sdk_version": worker.SDK_VERSION, + "args": [descriptor], + "return": descriptor, + "source": "def f(ctx, x): return x", + "handler": "f", + "max_batch_bytes": 1 << 20, + "max_batch_rows": 1024, + "handler_timeout_seconds": 2, + }) + + def control(kind, **fields): + return worker._encode_control(dict(kind=kind, tuple=fence, **fields)) + + chunks = iter( + [ + types.SimpleNamespace( + data=batch, + app_metadata=control("InputBatch", sequence=1), + ), + ] + ) + reader = types.SimpleNamespace(schema=batch.schema, read_chunk=lambda: next(chunks)) + writer = types.SimpleNamespace( + begin=lambda schema: None, + write_metadata=lambda data: None, + write_with_metadata=lambda record, data: None, + ) + command = control("OpenInvocation", payload=payload) + try: + handler = mock.Mock() + with mock.patch.object(worker, "_run_handler_process", handler): + with self.assertRaisesRegex(ValueError, "child validity"): + server.do_exchange( + types.SimpleNamespace(is_cancelled=lambda: False), + types.SimpleNamespace(command=command), + reader, + writer, + ) + handler.assert_not_called() + finally: + server.shutdown() + + @unittest.skipUnless(os.name == "posix", "process-group test") + def test_descendant_is_killed_after_handler_leader_exits(self): + with tempfile.TemporaryDirectory(prefix="mo-udf-owned-child-") as artifact: + witness = pathlib.Path(artifact) / "owned-child.json" + descendant = "import os,time; time.sleep(0.15); os.close(1); time.sleep(10)" + source = ( + "import json,os,pathlib,subprocess,sys\n" + "def f(ctx,x):\n" + f" child=subprocess.Popen([sys.executable,'-c',{descendant!r}],stdin=subprocess.DEVNULL)\n" + f" pathlib.Path({str(witness)!r}).write_text(json.dumps(dict(pid=child.pid,pgid=os.getpgrp())))\n" + " os._exit(7)\n" + ) + descriptor = {"type_id": worker.INT64, "offset_width": 32} + batch = pa.RecordBatch.from_arrays([pa.array([1], type=pa.int64())], ["arg_0"]) + request = { + "source": source, + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "sdk_version": worker.SDK_VERSION, + "context": None, + "args": [descriptor], + "return": descriptor, + "max_batch_bytes": 1 << 20, + "input": worker._serialize_record_batch(batch), + } + try: + with self.assertRaisesRegex(ValueError, "handler process"): + worker._run_handler_process(None, request, 2) + observed = json.loads(witness.read_text()) + # SIGKILL is synchronous as a request, but orphan adoption + # and init's waitpid are asynchronous. Require disappearance + # of the owned identity, including zombies, within a bound. + deadline = time.monotonic() + 2 + while True: + try: + survived = os.getpgid(observed["pid"]) == observed["pgid"] + except ProcessLookupError: + survived = False + if not survived or time.monotonic() >= deadline: + break + time.sleep(0.005) + self.assertFalse(survived, "init did not reap the owned descendant") + finally: + if witness.exists(): + owned = json.loads(witness.read_text()) + try: + if os.getpgid(owned["pid"]) == owned["pgid"]: + os.kill(owned["pid"], signal.SIGKILL) + except ProcessLookupError: + pass + + @unittest.skipUnless(os.name == "posix", "non-blocking pipe test") + def test_request_write_observes_handler_deadline(self): + created = [] + entered = threading.Event() + real_popen = subprocess.Popen + + def no_reader(argv, **kwargs): + process = real_popen( + [sys.executable, "-c", "import time; time.sleep(10)"], **kwargs + ) + created.append(process) + entered.set() + return process + + descriptor = {"type_id": worker.INT64, "offset_width": 32} + batch = pa.RecordBatch.from_arrays([pa.array([1], type=pa.int64())], ["arg_0"]) + request = { + "source": "def f(ctx, x): return x", + "handler": "f", + "mode": worker.MODE_SCALAR, + "null_policy": worker.NULL_CALL, + "sdk_version": worker.SDK_VERSION, + "context": None, + "args": [descriptor], + "return": descriptor, + "max_batch_bytes": 1 << 20, + "input": worker._serialize_record_batch(batch), + "probe_padding": b"x" * (1 << 20), + } + outcome = [] + + def invoke(): + try: + worker._run_handler_process(None, request, 0.05) + except Exception as exc: + outcome.append(type(exc).__name__) + + thread = threading.Thread(target=invoke, daemon=True) + try: + with mock.patch.object(worker.subprocess, "Popen", side_effect=no_reader): + thread.start() + self.assertTrue(entered.wait(1)) + thread.join(0.5) + self.assertFalse(thread.is_alive()) + self.assertEqual(["TimeoutError"], outcome) + finally: + for process in created: + if process.poll() is None: + os.killpg(process.pid, signal.SIGKILL) + thread.join(2) + for process in created: + process.wait(timeout=1) + if process.stdin: + process.stdin.close() + + @unittest.skipUnless(os.name == "posix", "handler deadline test") + def test_handler_deadline_includes_request_serialization(self): + # The session owns one monotonic timestamp for the whole request. A + # deterministic clock jump after request encoding proves that serialization + # cannot consume time outside the handler budget. + clock = iter((0.0, 0.0, 1.0)) + session = None + try: + with mock.patch.object(worker.time, "monotonic", side_effect=clock): + session = worker._HandlerProcessSession() + with self.assertRaisesRegex(TimeoutError, "handler execution timeout"): + session.run(None, {"input": b"x"}, 0.05) + finally: + if session is not None: + session.close() + + @unittest.skipUnless(os.name == "posix", "non-blocking write budget test") + def test_handler_request_write_rechecks_budget_within_one_write_event(self): + class CancelAfterWrites: + def __init__(self): + self.writes = 0 + + def is_cancelled(self): + return self.writes >= 2 + + class FakeStdin: + def fileno(self): + return 123 + + class FakeProcess: + stdin = FakeStdin() + + def poll(self): + return None + + class FakeSelector: + def register(self, *args): + pass + + def unregister(self, *args): + pass + + def select(self, _timeout): + return [(types.SimpleNamespace(data="request"), None)] + + context = CancelAfterWrites() + session = object.__new__(worker._HandlerProcessSession) + session._closed = False + session._process = FakeProcess() + session._selector = FakeSelector() + session._response_buffer = bytearray() + session._burst_batches = 0 + + request_parts = tuple(b"x" for _ in range(100)) + + def write(_fd, data): + context.writes += 1 + return len(data) + + with mock.patch.object( + worker, "_encode_execution_request", return_value=(request_parts, 100) + ), mock.patch.object(worker.os, "write", side_effect=write): + with self.assertRaisesRegex(TimeoutError, "handler execution cancelled"): + session.run(context, {"input": b"x"}, 10) + + self.assertLess(context.writes, len(request_parts)) + + def test_zero_argument_vector_uses_context_rows(self): + descriptor = {"type_id": worker.INT64, "offset_width": 32} + output = pa.array([7, 7, 7], type=pa.int64()) + self.assertEqual(3, len(worker._output_array(output, descriptor, 3))) + with self.assertRaisesRegex(ValueError, "result length"): + worker._output_array(pa.array([7], type=pa.int64()), descriptor, 3) + + def test_statement_context_is_whitelisted_and_frozen(self): + context = worker._statement_context( + { + "statement_id": "fence-only", + "statement_timestamp_utc": "1704067200123456", + "session_timezone_kind": "FIXED_OFFSET", + "session_timezone_offset_minutes": "+510", + "sql_mode": '["ANSI","STRICT"]', + "current_database": "app", + "current_user": "alice", + "current_role": "writer", + "connection_collation": "utf8mb4_bin", + } + ) + self.assertIsInstance(context, worker.StatementContext) + self.assertEqual(510, context.session_timezone.offset_minutes) + self.assertEqual(("ANSI", "STRICT"), context.sql_mode) + self.assertEqual("alice", context.current_user) + self.assertIsNone(worker._statement_context({"statement_id": "fence-only"})) + with self.assertRaisesRegex(ValueError, "unsupported statement context"): + worker._statement_context({"unexpected": "value"}) + with self.assertRaisesRegex(ValueError, "not canonical"): + worker._statement_context( + { + "statement_timestamp_utc": "1704067200000000", + "session_timezone_kind": "FIXED_OFFSET", + "session_timezone_offset_minutes": "0", + "sql_mode": '["STRICT", "ANSI"]', + "current_user": "alice", + "connection_collation": "utf8mb4_bin", + } + ) + + def test_statement_context_rejects_unknown_iana_timezone(self): + with self.assertRaisesRegex(ValueError, "not present in the local tzdb"): + worker._statement_context( + { + "statement_timestamp_utc": "1704067200000000", + "session_timezone_kind": "IANA", + "session_timezone_name": "NoSuch/Zone", + "session_timezone_tzdb_version": worker.TIMEZONE_DATABASE_VERSION, + "sql_mode": "[]", + "current_user": "alice", + "connection_collation": "utf8mb4_bin", + } + ) + + context = worker._statement_context( + { + "statement_timestamp_utc": "1704067200000000", + "session_timezone_kind": "IANA", + "session_timezone_name": "UTC", + "session_timezone_tzdb_version": worker.TIMEZONE_DATABASE_VERSION, + "sql_mode": "[]", + "current_user": "alice", + "connection_collation": "utf8mb4_bin", + } + ) + self.assertEqual("UTC", context.session_timezone.name) + + def test_statement_context_rejects_stale_iana_timezone_database(self): + with self.assertRaisesRegex(ValueError, "database version does not match"): + worker._statement_context( + { + "statement_timestamp_utc": "1704067200000000", + "session_timezone_kind": "IANA", + "session_timezone_name": "UTC", + "session_timezone_tzdb_version": "stale-version", + "sql_mode": "[]", + "current_user": "alice", + "connection_collation": "utf8mb4_bin", + } + ) + + def test_terminal_admission_does_not_evict_live_tombstones(self): + old_records = worker.MAX_LEDGER_ENTRIES + old_bytes = worker.MAX_LEDGER_BYTES + try: + worker.MAX_LEDGER_ENTRIES = 1 + worker.MAX_LEDGER_BYTES = 1 << 20 + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + first = (1, "statement", "group", 1, "invocation", 1) + state = server._admit(first) + with server._lock: + server._active.pop(first) + server._active_bytes -= state.terminal_bytes + server._remember_terminal_locked(first, state) + with self.assertRaisesRegex(ValueError, "entries are full"): + server._admit((1, "statement", "other-group", 1, "second", 1)) + self.assertIn(first, server._terminal) + with server._lock: + server._terminal[first] = worker._TerminalRecord( + 0.0, state.terminal_bytes, state.last_result, state.finish_id, + worker._TERMINAL_FAILED, + ) + server._close_group_epoch_locked(first) + server._purge_terminal_locked(1.0) + second = server._admit((1, "statement", "other-group", 1, "second", 1)) + self.assertIsNotNone(second) + finally: + worker.MAX_LEDGER_ENTRIES = old_records + worker.MAX_LEDGER_BYTES = old_bytes + + def test_terminal_ledger_capacity_is_bounded_until_fake_clock_expiry(self): + old_records = worker.MAX_LEDGER_ENTRIES + old_bytes = worker.MAX_LEDGER_BYTES + now = [100.0] + try: + worker.MAX_LEDGER_ENTRIES = 2 + worker.MAX_LEDGER_BYTES = 1 << 20 + server = worker.RoutineFlightServer( + "grpc://127.0.0.1:0", + clock=lambda: now[0], + terminal_ttl_seconds=10.0, + ) + first = (1, "statement", "group-first", 1, "first", 1) + second = (1, "statement", "group-second", 1, "second", 1) + third = (1, "statement", "group-third", 1, "third", 1) + for key in (first, second): + state = server._admit(key) + state.mark_finish_sent("finish-" + key[4]) + state.ack_finish("finish-" + key[4]) + server._finish_invocation(key, state) + + with self.assertRaisesRegex(ValueError, "ledger entries are full"): + server._admit(third) + # Retention is part of the de-duplication contract. Advancing the + # test clock is the only operation that makes old identities + # reclaimable; admission never evicts a live tombstone to make + # room for a new short invocation. + now[0] += 11.0 + self.assertIsNotNone(server._admit(third)) + finally: + worker.MAX_LEDGER_ENTRIES = old_records + worker.MAX_LEDGER_BYTES = old_bytes + + def test_expired_tombstone_keeps_closed_group_fence(self): + now = [10.0] + server = worker.RoutineFlightServer( + "grpc://127.0.0.1:0", clock=lambda: now[0], terminal_ttl_seconds=1.0 + ) + key = (1, "statement", "closed-group", 1, "first", 1) + state = server._admit(key) + server._finish_invocation(key, state) + now[0] += 2.0 + with self.assertRaisesRegex(ValueError, "group epoch is already closed"): + server._admit((1, "statement", "closed-group", 1, "late", 1)) + with server._lock: + server._purge_terminal_locked(now[0]) + self.assertNotIn(key, server._terminal) + + def test_active_groups_reserve_future_closed_fences(self): + old_entries = worker.MAX_CLOSED_GROUP_ENTRIES + old_bytes = worker.MAX_CLOSED_GROUP_BYTES + try: + worker.MAX_CLOSED_GROUP_ENTRIES = 1 + worker.MAX_CLOSED_GROUP_BYTES = 1 << 20 + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + first = (1, "statement", "reserved-first", 1, "first", 1) + second = (1, "statement", "reserved-second", 1, "second", 1) + first_state = server._admit(first) + self.assertIn((first[0], first[2]), server._reserved_groups) + with self.assertRaisesRegex(ValueError, "closed-group fence is full"): + server._admit(second) + + server._finish_invocation(first, first_state) + self.assertNotIn((first[0], first[2]), server._reserved_groups) + self.assertIn((first[0], first[2]), server._closed_groups) + with self.assertRaisesRegex(ValueError, "already closed"): + server._admit((1, "statement", first[2], 1, "late", 1)) + finally: + worker.MAX_CLOSED_GROUP_ENTRIES = old_entries + worker.MAX_CLOSED_GROUP_BYTES = old_bytes + + def test_active_group_rejects_a_second_member_before_handler_creation(self): + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + first = (1, "statement", "single-owner", 1, "first", 1) + first_state = server._admit(first) + try: + with self.assertRaisesRegex(ValueError, "execution group epoch is already active"): + server._admit((1, "statement", "single-owner", 1, "second", 1)) + finally: + server._finish_invocation(first, first_state) + + def test_group_fence_is_scoped_by_account(self): + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + first = (1, "statement-a", "same-name", 1, "first", 1) + second = (2, "statement-b", "same-name", 1, "second", 1) + first_state = server._admit(first) + second_state = server._admit(second) + try: + self.assertIn((1, "same-name"), server._active_groups) + self.assertIn((2, "same-name"), server._active_groups) + server._finish_invocation(first, first_state) + self.assertIn(second, server._active) + self.assertIn((1, "same-name"), server._closed_groups) + self.assertNotIn((2, "same-name"), server._closed_groups) + finally: + server._finish_invocation(second, second_state) + + # Each account can advance its own epoch independently after the + # previous same-named group has closed. + self.assertIsNotNone( + server._admit((1, "statement-a-2", "same-name", 2, "third", 1)) + ) + self.assertIsNotNone( + server._admit((2, "statement-b-2", "same-name", 2, "fourth", 1)) + ) + + def test_terminal_ack_requires_the_completed_fence(self): + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + key = (1, "statement", "group", 1, "completed", 1) + state = server._admit(key) + state.last_result = 2 + state.mark_finish_sent("finish-2") + state.ack_finish("finish-2") + server._finish_invocation(key, state) + + tuple_value = { + "account_id": key[0], + "statement_id": key[1], + "group_id": key[2], + "group_epoch": key[3], + "invocation_id": key[4], + "lease_epoch": key[5], + } + result_action = types.SimpleNamespace( + type="AcknowledgeResults", + body=worker._encode_control( + { + "kind": "AcknowledgeResults", + "tuple": tuple_value, + "ack_sequence": 2, + } + ), + ) + ack = worker._decode_control(next(server.do_action(None, result_action))) + self.assertEqual(2, ack["ack_sequence"]) + + wrong_action = types.SimpleNamespace( + type="AcknowledgeResults", + body=worker._encode_control( + { + "kind": "AcknowledgeResults", + "tuple": tuple_value, + "ack_sequence": 1, + } + ), + ) + with self.assertRaisesRegex(ValueError, "completed result"): + next(server.do_action(None, wrong_action)) + + finish_action = types.SimpleNamespace( + type="AcknowledgeFinish", + body=worker._encode_control( + { + "kind": "AcknowledgeFinish", + "tuple": tuple_value, + "finish_id": "finish-2", + } + ), + ) + finish_ack = worker._decode_control(next(server.do_action(None, finish_action))) + self.assertEqual("finish-2", finish_ack["finish_id"]) + # The first Finish ACK may have reached the worker even if its RPC + # response was lost. A retry is then an idempotent confirmation of + # the frozen SUCCESS tombstone, never a new execution. + repeat_ack = worker._decode_control(next(server.do_action(None, finish_action))) + self.assertEqual("finish-2", repeat_ack["finish_id"]) + + def test_late_finish_ack_cannot_promote_unconfirmed_terminal(self): + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + key = (1, "statement", "group", 1, "unconfirmed", 1) + state = server._admit(key) + state.mark_finish_sent("finish-unconfirmed") + server._finish_invocation(key, state) + self.assertEqual( + worker._TERMINAL_FINISH_UNCONFIRMED, + server._terminal[key].outcome, + ) + tuple_value = { + "account_id": key[0], "statement_id": key[1], "group_id": key[2], + "group_epoch": key[3], "invocation_id": key[4], "lease_epoch": key[5], + } + action = types.SimpleNamespace( + type="AcknowledgeFinish", + body=worker._encode_control({ + "kind": "AcknowledgeFinish", "tuple": tuple_value, + "finish_id": "finish-unconfirmed", + }), + ) + with self.assertRaisesRegex(ValueError, "FINISH_UNCONFIRMED"): + next(server.do_action(None, action)) + + def test_cancellation_after_accepted_finish_ack_keeps_success_idempotent(self): + state = worker._InvocationState({}, 128) + state.mark_finish_sent("finish-race") + state.ack_finish("finish-race") + state.mark_cancelled() + self.assertFalse(state.cancelled) + state.ack_finish("finish-race") + self.assertEqual(worker._TERMINAL_SUCCESS, state.freeze_terminal()) + + def test_frozen_success_rejects_stale_result_ack(self): + state = worker._InvocationState({}, 128) + state.last_result = 2 + state.mark_finish_sent("finish-stale-result") + state.ack_finish("finish-stale-result") + self.assertEqual(worker._TERMINAL_SUCCESS, state.freeze_terminal()) + with self.assertRaisesRegex(ValueError, "completed result"): + state.ack_result(1) + state.ack_result(2) + + def test_cancelled_terminal_is_frozen_and_rejects_late_ack(self): + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + key = (1, "statement", "cancel-group", 1, "cancelled", 1) + state = server._admit(key) + state.mark_cancelled() + with self.assertRaisesRegex(ValueError, "already terminal"): + state.mark_finish_sent("finish-after-cancel") + server._finish_invocation(key, state) + self.assertEqual(worker._TERMINAL_CANCELLED, server._terminal[key].outcome) + + tuple_value = { + "account_id": key[0], "statement_id": key[1], "group_id": key[2], + "group_epoch": key[3], "invocation_id": key[4], "lease_epoch": key[5], + } + action = types.SimpleNamespace( + type="AcknowledgeFinish", + body=worker._encode_control({ + "kind": "AcknowledgeFinish", "tuple": tuple_value, + "finish_id": "finish-after-cancel", + }), + ) + with self.assertRaisesRegex(ValueError, "CANCELLED"): + next(server.do_action(None, action)) + self.assertEqual(worker._TERMINAL_CANCELLED, server._terminal[key].outcome) + + def test_cancelled_or_shutdown_action_cannot_ack_active_invocation(self): + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + key = (1, "statement", "action-cancel", 1, "active", 1) + state = server._admit(key) + state.mark_finish_sent("finish-active") + tuple_value = { + "account_id": key[0], "statement_id": key[1], "group_id": key[2], + "group_epoch": key[3], "invocation_id": key[4], "lease_epoch": key[5], + } + action = types.SimpleNamespace( + type="AcknowledgeFinish", + body=worker._encode_control({ + "kind": "AcknowledgeFinish", "tuple": tuple_value, + "finish_id": "finish-active", + }), + ) + cancelled_context = types.SimpleNamespace(is_cancelled=lambda: True) + with self.assertRaisesRegex(TimeoutError, "DEADLINE_EXCEEDED"): + next(server.do_action(cancelled_context, action)) + self.assertFalse(state.finish_acked) + + server._shutdown_event.set() + with self.assertRaisesRegex(TimeoutError, "DEADLINE_EXCEEDED"): + next(server.do_action(None, action)) + self.assertFalse(state.finish_acked) + state.mark_cancelled() + server._finish_invocation(key, state) + + def test_active_fence_cannot_be_admitted_twice(self): + server = worker.RoutineFlightServer("grpc://127.0.0.1:0") + key = (1, "statement", "group", 1, "invocation", 1) + server._admit(key) + with self.assertRaisesRegex(ValueError, "fence is active"): + server._admit(key) + with self.assertRaisesRegex(ValueError, "fencing tuple changed"): + worker._require_tuple( + {"account_id": 1, "statement_id": "other", "group_id": "group", "group_epoch": 1, "invocation_id": "invocation", "lease_epoch": 1}, + {"account_id": 1, "statement_id": "statement", "group_id": "group", "group_epoch": 1, "invocation_id": "invocation", "lease_epoch": 1}, + ) + + def test_control_numeric_fields_are_strict(self): + tuple_value = { + "account_id": 0, + "statement_id": "statement", + "group_id": "group", + "group_epoch": 1, + "invocation_id": "invocation", + "lease_epoch": 1, + } + self.assertEqual( + (0, "statement", "group", 1, "invocation", 1), + worker._tuple_key(tuple_value), + ) + with self.assertRaisesRegex(ValueError, "unsupported control"): + worker._decode_control(json.dumps({"version": True, "kind": "InputBatch", "tuple": tuple_value}).encode()) + with self.assertRaisesRegex(ValueError, "invalid control field sequence"): + worker._required_uint64({"sequence": "1"}, "sequence") + with self.assertRaisesRegex(ValueError, "invalid invocation field timeout"): + worker._required_positive_float({"timeout": float("nan")}, "timeout", 60.0) + + def test_control_rejects_unknown_envelope_fields(self): + tuple_value = { + "account_id": 0, + "statement_id": "statement", + "group_id": "group", + "group_epoch": 1, + "invocation_id": "invocation", + "lease_epoch": 1, + } + value = { + "version": 1, + "kind": "InputBatch", + "tuple": tuple_value, + "sequence": 1, + "future_field": "must not be ignored", + } + with self.assertRaisesRegex(ValueError, "unsupported control field"): + worker._decode_control(json.dumps(value).encode()) + with self.assertRaisesRegex(ValueError, "unsupported control field"): + worker._encode_control(value) + + def test_control_fields_belong_to_their_kind(self): + tuple_value = { + "account_id": 1, + "statement_id": "statement", + "group_id": "group", + "group_epoch": 1, + "invocation_id": "invocation", + "lease_epoch": 1, + } + input_batch = { + "version": worker.PROTOCOL_VERSION, + "kind": "InputBatch", + "tuple": tuple_value, + "sequence": 1, + } + with self.assertRaisesRegex(ValueError, "not valid for control kind"): + worker._encode_control({**input_batch, "last_sequence": 1}) + with self.assertRaisesRegex(ValueError, "not valid for control kind"): + worker._decode_control( + json.dumps({**input_batch, "last_sequence": 1}).encode() + ) + with self.assertRaisesRegex(ValueError, "unsupported control kind"): + worker._decode_control( + json.dumps( + { + "version": worker.PROTOCOL_VERSION, + "kind": "Unknown", + "tuple": tuple_value, + } + ).encode() + ) + + def test_open_invocation_payload_must_be_object(self): + tuple_value = { + "account_id": 1, + "statement_id": "statement", + "group_id": "group", + "group_epoch": 1, + "invocation_id": "invocation", + "lease_epoch": 1, + } + for payload in (None, [], "text"): + value = { + "version": worker.PROTOCOL_VERSION, + "kind": "OpenInvocation", + "tuple": tuple_value, + "payload": payload, + } + with self.assertRaisesRegex(ValueError, "payload must be an object"): + worker._decode_control(json.dumps(value).encode()) + with self.assertRaisesRegex(ValueError, "payload must be an object"): + worker._encode_control(value) + + def test_control_encoder_rejects_nonstandard_json_numbers(self): + tuple_value = { + "account_id": 1, + "statement_id": "statement", + "group_id": "group", + "group_epoch": 1, + "invocation_id": "invocation", + "lease_epoch": 1, + } + for number in (float("nan"), float("inf"), float("-inf")): + with self.assertRaisesRegex(ValueError, "invalid control JSON"): + worker._encode_control( + { + "kind": "OpenInvocation", + "tuple": tuple_value, + "payload": {"number": number}, + } + ) + + def test_control_encoder_rejects_missing_required_fields(self): + tuple_value = { + "account_id": 1, + "statement_id": "statement", + "group_id": "group", + "group_epoch": 1, + "invocation_id": "invocation", + "lease_epoch": 1, + } + cases = ( + ("InputBatch", {}, "sequence"), + ("EndInput", {}, "last_sequence"), + ( + "Finish", + {"last_result_sequence": 0, "finish_id": "finish", "status": "OK"}, + "last_sequence", + ), + ("AcknowledgeFinish", {}, "finish_id"), + ) + for kind, fields, field in cases: + with self.assertRaisesRegex(ValueError, f"missing.*{field}"): + worker._encode_control( + {"kind": kind, "tuple": tuple_value, **fields} + ) + + def test_control_rejects_unknown_fencing_tuple_fields(self): + tuple_value = { + "account_id": 0, + "statement_id": "statement", + "group_id": "group", + "group_epoch": 1, + "invocation_id": "invocation", + "lease_epoch": 1, + "future_epoch": 2, + } + with self.assertRaisesRegex(ValueError, "unsupported fencing tuple field"): + worker._tuple_key(tuple_value) + value = {"version": 1, "kind": "InputBatch", "tuple": tuple_value, "sequence": 1} + with self.assertRaisesRegex(ValueError, "unsupported fencing tuple field"): + worker._decode_control(json.dumps(value).encode()) + + def test_fencing_tuple_rejects_invalid_utf8(self): + tuple_value = { + "account_id": 1, + "statement_id": "\ud800", + "group_id": "group", + "group_epoch": 1, + "invocation_id": "invocation", + "lease_epoch": 1, + } + with self.assertRaisesRegex(ValueError, "invalid UTF-8"): + worker._tuple_key(tuple_value) + + def test_control_rejects_duplicate_json_fields(self): + wire = ( + b'{"version":1,"kind":"InputBatch","tuple":{"account_id":1,' + b'"statement_id":"statement","group_id":"group","group_epoch":1,' + b'"invocation_id":"invocation","lease_epoch":1},' + b'"sequence":1,"sequence":2}' + ) + with self.assertRaisesRegex(ValueError, "duplicate control JSON field"): + worker._decode_control(wire) + + def test_control_rejects_excessive_json_nesting(self): + nested = "[" * worker.MAX_JSON_NESTING + "0" + "]" * worker.MAX_JSON_NESTING + value = { + "version": 1, + "kind": "OpenInvocation", + "tuple": { + "account_id": 1, + "statement_id": "statement", + "group_id": "group", + "group_epoch": 1, + "invocation_id": "invocation", + "lease_epoch": 1, + }, + "payload": {"value": json.loads(nested)}, + } + wire = json.dumps(value, separators=(",", ":")).encode() + with self.assertRaisesRegex(ValueError, "nesting exceeds"): + worker._decode_control(wire) + + def test_action_decoders_reject_excessive_json_nesting(self): + nested = "[" * worker.MAX_JSON_NESTING + "0" + "]" * worker.MAX_JSON_NESTING + with self.assertRaisesRegex(ValueError, "nesting exceeds"): + worker._decode_capability_request( + ('{"protocol_version":1,"extra":' + nested + '}').encode() + ) + with self.assertRaisesRegex(ValueError, "nesting exceeds"): + worker._decode_definition_validation( + ('{"extra":' + nested + '}').encode() + ) + + def test_result_ack_rejects_zero_sequence(self): + state = worker._InvocationState({}, 1) + state.last_result = 1 + with self.assertRaisesRegex(ValueError, "result ACK"): + state.ack_result(0) + + def test_invocation_state_keeps_input_and_result_directions_independent(self): + state = worker._InvocationState({}, 1) + state.record_input(1) + state.record_input(2) + self.assertEqual((2, 0, 0), state.sequences()) + + state.record_result(1) + self.assertEqual((2, 1, 0), state.sequences()) + with self.assertRaisesRegex(ValueError, "result sequence"): + state.record_result(3) + state.record_result(2) + self.assertEqual((2, 2, 0), state.sequences()) + + state.ack_result(1) + state.ack_result(2) + self.assertEqual((2, 2, 2), state.sequences()) + + +if __name__ == "__main__": + unittest.main() diff --git a/pkg/udf/python/worker/watchdog.py b/pkg/udf/python/worker/watchdog.py new file mode 100644 index 0000000000000..30805ad09c8a5 --- /dev/null +++ b/pkg/udf/python/worker/watchdog.py @@ -0,0 +1,52 @@ +# Copyright 2026 Matrix Origin +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. + +"""Minimal process-group liveness watchdog for a Python UDF handler.""" + +import os +import signal +import sys + + +def _watch(read_fd: int, process_group_id: int) -> None: + try: + while True: + if os.read(read_fd, 1) == b"": + try: + os.killpg(process_group_id, signal.SIGKILL) + except ProcessLookupError: + pass + return + except (OSError, ValueError): + # A broken descriptor means the worker death signal can no longer be + # observed. Kill the owned group before the watchdog exits so a + # handler descendant cannot outlive both its owners. + try: + os.killpg(process_group_id, signal.SIGKILL) + except ProcessLookupError: + pass + return + finally: + try: + os.close(read_fd) + except OSError: + pass + + +def main() -> None: + if len(sys.argv) != 3: + raise SystemExit("usage: watchdog.py READ_FD PROCESS_GROUP_ID") + try: + read_fd = int(sys.argv[1]) + process_group_id = int(sys.argv[2]) + except ValueError as exc: + raise SystemExit("watchdog arguments must be integers") from exc + if read_fd < 0 or process_group_id <= 0: + raise SystemExit("watchdog arguments are out of range") + _watch(read_fd, process_group_id) + + +if __name__ == "__main__": + main() diff --git a/pkg/udf/python/worker/worker.py b/pkg/udf/python/worker/worker.py new file mode 100644 index 0000000000000..f73ea706dc18d --- /dev/null +++ b/pkg/udf/python/worker/worker.py @@ -0,0 +1,4000 @@ +# Copyright 2026 Matrix Origin +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. + +"""Arrow Flight worker for the MatrixOne Python routine contract. + +The process is deliberately a small protocol endpoint. It does not install +packages, read SQL data, or interpret user supplied paths. This development +adapter is not a security boundary; a future production launcher must wrap it +in the sandbox and deployment policy selected for the routine. +""" + +from __future__ import annotations + +import sys + +# Handler children execute only the length-prefixed Arrow/pipe contract. Keep +# service-side modules out of that import path; the child is started for each +# invocation burst and cannot reuse the worker's imported Python heap. +_HANDLER_ENTRY = "--execute-handler" in sys.argv + +import contextlib +import datetime as _datetime +import decimal as _decimal +import hashlib +import inspect +import json +import logging +import math +import os +import pickle +import signal +import struct +import threading +import time +import uuid as _uuid +from collections import OrderedDict +from dataclasses import dataclass +from typing import Any, Dict, Iterable, Optional +from zoneinfo import TZPATH, ZoneInfo, ZoneInfoNotFoundError + +if not _HANDLER_ENTRY: + import queue + import selectors + import subprocess + +import pyarrow as pa + +# Handler children only need Arrow. Avoid importing Flight on that entry path; +# the annotations in this module are postponed, and the Flight server class is +# never instantiated by the handler child. + +class _NoFlightServerBase: + pass + + +if _HANDLER_ENTRY: + flight = None + _FlightServerBase = _NoFlightServerBase +else: + import pyarrow.flight as flight + + _FlightServerBase = flight.FlightServerBase + +PROTOCOL_VERSION = 1 +MAX_CONTROL_BYTES = 1 << 20 +# Keep control parsing shallow even when the total JSON envelope is below the +# byte limit. This is the Python counterpart of protocol.MaxJSONNesting; a +# byte scanner makes the bound independent of the interpreter's recursion +# limit and ignores bracket characters inside JSON strings. +MAX_JSON_NESTING = 64 +# Keep the Python wire boundary identical to protocol.FencingTuple's +# component limit. The control frame limit alone is not sufficient: a +# single oversized identity would otherwise consume most of every ledger +# entry and would be accepted by the worker after Go rejected it. +MAX_FENCE_COMPONENT_BYTES = 256 +# SecurityFrame uses uint32 principal identifiers in the language-neutral +# contract. Keep the Python decoder's acceptance domain identical to Go; +# checking only for a non-negative Python int would admit values that no Go +# caller can represent and would make quota/security identity non-canonical. +MAX_SECURITY_PRINCIPAL_ID = (1 << 32) - 1 +MIN_INT64 = -(1 << 63) +MAX_INT64 = (1 << 63) - 1 +# StatementContext is materialized as datetime.datetime. This is narrower +# than the wire int64 domain and must match the Go context validator before an +# invocation reaches user code. +MIN_STATEMENT_TIMESTAMP_UTC = -62135596800000000 +MAX_STATEMENT_TIMESTAMP_UTC = 253402300799999999 +MIN_INT32 = -(1 << 31) +MAX_INT32 = (1 << 31) - 1 +# Admission bounds cover active fences and retained terminal tombstones. The +# names deliberately describe the whole ledger so a future cleanup change +# cannot mistake active work for reclaimable terminal state. +MAX_LEDGER_ENTRIES = 10000 +MAX_LEDGER_BYTES = 16 << 20 +# Closed group fences are retained separately from terminal records. They are +# the proof that permits TTL collection without allowing an old tuple to +# regain an execution grant. The cap makes the safety cost explicit: once the +# owner fence is full, admission fails closed until a durable scheduler fence +# is available. +MAX_CLOSED_GROUP_ENTRIES = MAX_LEDGER_ENTRIES +MAX_CLOSED_GROUP_BYTES = MAX_LEDGER_BYTES +TERMINAL_TTL_SECONDS = 300.0 +ACK_TIMEOUT_SECONDS = 60.0 +MAX_EXECUTION_FRAME_BYTES = 1 << 30 +# The handler IPC frame keeps the control metadata in pickle and transports +# the Arrow bytes through protocol 5's out-of-band buffer. The Arrow payload +# itself is a RecordBatch message; its schema is reconstructed from the +# frozen descriptors on both sides, so a schema message is not repeated for +# every batch in a bounded invocation burst. +HANDLER_ARROW_STREAM = "stream" +HANDLER_ARROW_RECORD_BATCH = "record_batch" +# A definition validation action carries one immutable source plus its typed +# contract. The source itself is bounded by the artifact limit below; keep +# the action envelope separate from MAX_CONTROL_BYTES, which bounds the +# smaller per-invocation control frames. +MAX_DEFINITION_VALIDATION_BYTES = (2 << 20) + MAX_CONTROL_BYTES +MAX_HANDLER_PROCESSES = 8 +# H is a worker-wide child limit. The two narrower limits prevent one +# account, or one principal inside an account, from consuming all H slots. +# They are advertised as part of the worker capability so a Gateway can fail +# closed when it talks to a worker with a different fairness contract. +MAX_ACCOUNT_HANDLER_PROCESSES = MAX_HANDLER_PROCESSES +MAX_OWNER_HANDLER_PROCESSES = MAX_HANDLER_PROCESSES // 2 +_DEFAULT_HANDLER_SLOTS = threading.BoundedSemaphore(MAX_HANDLER_PROCESSES) +# Materializing a scalar column once is useful for a substantial batch, but +# costs more than indexed access for the tiny batches common in short calls. +# Keep this threshold local to the worker conversion path; it is not a wire +# or admission limit and does not change the handler's batch semantics. +SCALAR_MATERIALIZATION_MIN_ROWS = 64 +_CONTROL_KEYS = frozenset( + { + "version", + "kind", + "tuple", + "sequence", + "last_sequence", + "last_result_sequence", + "ack_sequence", + "released_bytes", + "released_batches", + "finish_id", + "status", + "reason", + "payload", + } +) +_CONTROL_BASE_KEYS = frozenset({"version", "kind", "tuple"}) +_CONTROL_FIELD_RULES = { + "OpenInvocation": (frozenset({"payload"}), frozenset({"payload"})), + "InputBatch": (frozenset({"sequence"}), frozenset({"sequence"})), + "EndInput": (frozenset({"last_sequence"}), frozenset({"last_sequence"})), + "InputConsumed": ( + frozenset({"sequence", "released_bytes", "released_batches"}), + frozenset({"sequence", "released_bytes", "released_batches"}), + ), + "ResultSchema": (frozenset(), frozenset()), + "ResultBatch": (frozenset({"sequence"}), frozenset({"sequence"})), + "Finish": ( + frozenset({"last_sequence", "last_result_sequence", "finish_id", "status"}), + frozenset({"last_sequence", "last_result_sequence", "finish_id", "status"}), + ), + "AcknowledgeResults": ( + frozenset({"ack_sequence"}), + frozenset({"ack_sequence"}), + ), + "AcknowledgeFinish": (frozenset({"finish_id"}), frozenset({"finish_id"})), + "Ack": ( + frozenset({"ack_sequence", "finish_id", "status"}), + frozenset({"status"}), + ), + "Error": (frozenset({"status", "reason"}), frozenset({"status", "reason"})), +} +_TUPLE_KEYS = frozenset( + { + "account_id", + "statement_id", + "group_id", + "group_epoch", + "invocation_id", + "lease_epoch", + } +) +_FUNCTION_REF_KEYS = frozenset( + {"account_id", "database_id", "function_id", "revision", "namespace_version"} +) +_OPEN_PAYLOAD_KEYS = frozenset( + { + "function_ref", + "handler", + "source", + "mode", + "null_policy", + "abi_contract", + "adapter_version", + "sdk_version", + "definition_schema_version", + "artifact_digest", + "environment_digest", + "definition_fingerprint", + "context", + "callsite_id", + "may_error", + "security_mode", + "leakproof", + "statement_context", + "security_frame", + "args", + "return", + "max_batch_bytes", + "max_batch_rows", + "max_invocation_rows", + "max_invocation_result_bytes", + "handler_timeout_seconds", + } +) +_OPEN_PAYLOAD_REQUIRED_KEYS = _OPEN_PAYLOAD_KEYS - { + "context", +} +_DESCRIPTOR_KEYS = frozenset( + { + "type_id", + "width", + "scale", + "charset", + "offset_width", + "json_encoding", + "temporal_encoding", + } +) +_DESCRIPTOR_INT_KEYS = frozenset( + {"type_id", "width", "scale", "charset", "offset_width"} +) +_DESCRIPTOR_TEXT_KEYS = frozenset({"json_encoding", "temporal_encoding"}) +_HANDLER_RESPONSE_ERROR = 0 +_HANDLER_RESPONSE_OK = 1 +_HANDLER_REQUEST_KIND_KEY = "__matrixone_handler_request_kind" +_HANDLER_REQUEST_FULL = "full" +_HANDLER_REQUEST_BATCH = "batch" +_HANDLER_RESPONSE_FD_ENV = "MATRIXONE_HANDLER_RESPONSE_FD" +_HANDLER_PARENT_WATCH_FD_ENV = "MATRIXONE_HANDLER_PARENT_WATCH_FD" +# UT may install the checked-out worker requirements into a temporary target +# and expose it through PYTHONPATH. Preserve only that runtime path in handler +# children; the rest of the parent environment remains excluded. +_HANDLER_ENV_ALLOWLIST = frozenset({"PATH", "PYTHONPATH"}) +_MICROS_PER_SECOND = 1_000_000 +_MAX_TIME_MICROS = (838 * 60 * 60 + 59 * 60 + 59) * _MICROS_PER_SECOND +_MIN_TIMESTAMP = _datetime.datetime(1970, 1, 1, 0, 0, 1, tzinfo=_datetime.timezone.utc) +_MAX_TIMESTAMP = _datetime.datetime(9999, 12, 31, 23, 59, 59, 999999, tzinfo=_datetime.timezone.utc) + +BOOL = 10 +INT8, INT16, INT32, INT64 = 20, 21, 22, 23 +UINT8, UINT16, UINT32, UINT64 = 25, 26, 27, 28 +FLOAT32, FLOAT64 = 30, 31 +DECIMAL64, DECIMAL128 = 32, 33 +DATE, TIME, DATETIME, TIMESTAMP = 50, 51, 52, 53 +CHAR, VARCHAR, JSON, UUID = 60, 61, 62, 63 +BINARY, VARBINARY = 64, 65 +BLOB, TEXT = 70, 71 +VECF32, VECF64 = 224, 225 + +MODE_SCALAR = "SCALAR" +MODE_VECTOR = "VECTOR" +NULL_CALL = "CALLED_ON_NULL_INPUT" +NULL_RETURN = "RETURNS_NULL_ON_NULL_INPUT" +ABI_CONTRACT = "PYTHON_ARROW" +ADAPTER_VERSION = "2026-09" +SDK_VERSION = "1.0" +DEFINITION_SCHEMA_VERSION = 1 +PLAN_CONTRACT_VERSION = 1 +TYPE_DESCRIPTOR_CONTRACT = "ARROW_DESCRIPTOR" + + +def _timezone_database_version() -> str: + for root in TZPATH: + try: + with open( + os.path.join(root, "tzdata.zi"), "r", encoding="utf-8" + ) as source: + line = source.readline().strip() + except (OSError, UnicodeError): + continue + prefix = "# version " + if line.startswith(prefix) and line[len(prefix) :].strip(): + return line[len(prefix) :].strip() + return "" + + +TIMEZONE_DATABASE_VERSION = _timezone_database_version() + + +def _contract_digest(domain: str, *parts: str) -> str: + digest = hashlib.sha256() + for part in (domain, *parts): + encoded = part.encode("utf-8") + digest.update(struct.pack(">Q", len(encoded))) + digest.update(encoded) + return digest.hexdigest() + + +def _inline_artifact_digest(handler: str, source: str) -> str: + return _contract_digest("matrixone-python-inline-artifact", handler, source) + + +def _environment_digest() -> str: + if not TIMEZONE_DATABASE_VERSION: + return "" + return _contract_digest( + "matrixone-python-environment", + str(PROTOCOL_VERSION), + ABI_CONTRACT, + ADAPTER_VERSION, + SDK_VERSION, + str(DEFINITION_SCHEMA_VERSION), + str(PLAN_CONTRACT_VERSION), + TYPE_DESCRIPTOR_CONTRACT, + TIMEZONE_DATABASE_VERSION, + ) + + +def _canonical_definition_json(value: Any) -> bytes: + """Match Go encoding/json's canonical UTF-8 output for this contract.""" + encoded = json.dumps( + value, separators=(",", ":"), ensure_ascii=False, allow_nan=False + ) + # encoding/json escapes these characters even when the payload is UTF-8. + # U+2028/U+2029 are also escaped by Go for safe embedding in JavaScript. + return ( + encoded.replace("&", "\\u0026") + .replace("<", "\\u003c") + .replace(">", "\\u003e") + .replace("\u2028", "\\u2028") + .replace("\u2029", "\\u2029") + .encode("utf-8") + ) + + +def _definition_fingerprint(payload: Dict[str, Any]) -> str: + """Hash the immutable executable contract in an Open. + + The original source is a catalog/audit payload. The artifact digest + identifies the exact bytes resolved by the trusted Gateway, so source is + intentionally absent from this canonical definition body. + """ + body = { + "definition_schema_version": payload["definition_schema_version"], + "handler": payload["handler"], + "mode": payload["mode"], + "null_policy": payload["null_policy"], + "abi_contract": payload["abi_contract"], + "adapter_version": payload["adapter_version"], + "artifact_digest": payload["artifact_digest"], + "environment_digest": payload["environment_digest"], + "sdk_version": payload["sdk_version"], + # Go's canonical definition body uses `omitempty` for ArgTypes. An + # empty VECTOR signature must therefore omit the field rather than + # encode it as an empty array, otherwise zero-argument calls would + # have different fingerprints on the two sides of the ABI. + "arg_types": [ + json.loads(_canonical_descriptor(descriptor).decode("utf-8")) + for descriptor in payload["args"] + ], + "return_type": json.loads( + _canonical_descriptor(payload["return"]).decode("utf-8") + ), + } + if not body["arg_types"]: + del body["arg_types"] + return hashlib.sha256(_canonical_definition_json(body)).hexdigest() + +_CAPABILITY_REQUEST_KEYS = frozenset({"protocol_version"}) +_DEFINITION_VALIDATION_KEYS = frozenset( + { + "account_id", + "handler", + "source", + "mode", + "null_policy", + "abi_contract", + "adapter_version", + "sdk_version", + "definition_schema_version", + "artifact_digest", + "environment_digest", + "definition_fingerprint", + "args", + "return", + } +) +_CAPABILITY_RESPONSE_KEYS = frozenset( + { + "protocol_version", + "abi_contract", + "adapter_version", + "sdk_version", + "definition_schema_version", + "plan_contract_version", + "type_descriptor_contract", + "timezone_database_version", + "modes", + "null_policies", + "window_batches", + "cumulative_ack", + "max_execution_frame_bytes", + "max_handler_processes", + "max_account_handler_processes", + "max_owner_handler_processes", + "lease_epoch", + } +) + +log = logging.getLogger("matrixone.python.udf.worker") + + +@dataclass(frozen=True, slots=True) +class SqlDate: + is_zero: bool + value: Optional[_datetime.date] + + +@dataclass(frozen=True, slots=True) +class SqlDatetime: + is_zero: bool + value: Optional[_datetime.datetime] + + +@dataclass(frozen=True, slots=True) +class SqlTimestamp: + is_zero: bool + value: Optional[_datetime.datetime] + + +@dataclass(frozen=True, slots=True) +class TimezoneContext: + kind: str + name: Optional[str] = None + offset_minutes: Optional[int] = None + tzdb_version: Optional[str] = None + + +@dataclass(frozen=True, slots=True) +class StatementContext: + statement_timestamp_utc: _datetime.datetime + session_timezone: TimezoneContext + sql_mode: tuple[str, ...] + current_database: Optional[str] + current_user: str + current_role: Optional[str] + connection_collation: str + + +class _CallLogger: + __slots__ = () + + def info(self, message: str, *args: Any) -> None: + log.info("user: " + str(message), *args) + + def warning(self, message: str, *args: Any) -> None: + log.warning("user: " + str(message), *args) + + def error(self, message: str, *args: Any) -> None: + log.error("user: " + str(message), *args) + + +@dataclass(frozen=True, slots=True) +class ScalarContext: + sdk_version: str + logger: _CallLogger + statement: Optional[StatementContext] = None + + +@dataclass(frozen=True, slots=True) +class VectorContext: + sdk_version: str + logger: _CallLogger + statement: Optional[StatementContext] = None + num_rows: int = 0 + + +@dataclass(frozen=True, slots=True) +class _TerminalRecord: + expires_at: float + bytes: int + last_result: int + finish_id: Optional[str] + outcome: str + + +_TERMINAL_SUCCESS = "SUCCESS" +_TERMINAL_FINISH_UNCONFIRMED = "FINISH_UNCONFIRMED" +_TERMINAL_CANCELLED = "CANCELLED" +_TERMINAL_FAILED = "FAILED" + + +_FENCING_CONTEXT_KEYS = frozenset( + {"account_id", "statement_id", "group_id", "group_epoch", "invocation_id", "lease_epoch"} +) +_STATEMENT_CONTEXT_KEYS = frozenset( + { + "statement_timestamp_utc", + "session_timezone_kind", + "session_timezone_name", + "session_timezone_offset_minutes", + "session_timezone_tzdb_version", + "sql_mode", + "current_database", + "current_user", + "current_role", + "connection_collation", + } +) +_TYPED_STATEMENT_CONTEXT_KEYS = frozenset( + { + "contract_version", + "statement_timestamp_utc", + "timezone_kind", + "timezone_name", + "timezone_offset_minutes", + "timezone_database_version", + "sql_mode", + "current_database", + "current_user", + "current_role", + "connection_collation", + } +) +_SECURITY_FRAME_KEYS = frozenset( + { + "contract_version", + "mode", + "invoker_user_id", + "invoker_role_id", + "effective_user_id", + "effective_role_id", + } +) + + +def _required_context_value(context: Dict[str, Any], key: str) -> str: + value = context.get(key) + if not isinstance(value, str) or not value: + raise ValueError(f"PROTOCOL: missing statement context field {key}") + return value + + +def _optional_context_value(context: Dict[str, Any], key: str) -> Optional[str]: + value = context.get(key) + if value is None: + return None + if not isinstance(value, str): + raise ValueError(f"PROTOCOL: statement context field {key} must be text") + return value or None + + +def _typed_statement_context(raw: Any) -> Optional[Dict[str, Any]]: + """Validate the typed Go execution snapshot and return canonical map data.""" + if raw is None: + return None + if not isinstance(raw, dict) or set(raw) - _TYPED_STATEMENT_CONTEXT_KEYS: + raise ValueError("PROTOCOL: unsupported typed statement context field") + if type(raw.get("contract_version")) is not int or raw["contract_version"] != 1: + raise ValueError("UNSUPPORTED_ROUTINE_VERSION: unsupported statement context contract") + timestamp = raw.get("statement_timestamp_utc") + if ( + isinstance(timestamp, bool) + or not isinstance(timestamp, int) + or timestamp < MIN_STATEMENT_TIMESTAMP_UTC + or timestamp > MAX_STATEMENT_TIMESTAMP_UTC + ): + raise ValueError("PROTOCOL: invalid typed statement timestamp") + timezone_kind = raw.get("timezone_kind") + if not isinstance(timezone_kind, str): + raise ValueError("PROTOCOL: typed statement timezone is missing") + timezone_name = raw.get("timezone_name", "") + tzdb_version = raw.get("timezone_database_version", "") + offset = raw.get("timezone_offset_minutes", 0) + if isinstance(offset, bool) or not isinstance(offset, int): + raise ValueError("PROTOCOL: invalid typed timezone offset") + if timezone_kind == "IANA": + if not isinstance(timezone_name, str) or not timezone_name or not isinstance(tzdb_version, str) or not tzdb_version or offset != 0: + raise ValueError("PROTOCOL: incomplete typed IANA timezone") + elif timezone_kind == "FIXED_OFFSET": + if timezone_name != "" or tzdb_version != "" or offset < -839 or offset > 840: + raise ValueError("PROTOCOL: invalid typed fixed timezone") + else: + raise ValueError("PROTOCOL: unsupported typed statement timezone") + sql_mode = raw.get("sql_mode") + if not isinstance(sql_mode, list) or any(not isinstance(item, str) or not item for item in sql_mode): + raise ValueError("PROTOCOL: typed statement sql_mode must be an array of strings") + if sql_mode != sorted(set(sql_mode)): + raise ValueError("PROTOCOL: typed statement sql_mode is not canonical") + current_user = raw.get("current_user") + collation = raw.get("connection_collation") + if not isinstance(current_user, str) or not current_user or not isinstance(collation, str) or not collation: + raise ValueError("PROTOCOL: typed statement principal or collation is missing") + optional_text = ("current_database", "current_role") + for key in optional_text: + if key in raw and not isinstance(raw[key], str): + raise ValueError(f"PROTOCOL: typed statement field {key} must be text") + value = { + "statement_timestamp_utc": str(timestamp), + "session_timezone_kind": timezone_kind, + "sql_mode": json.dumps(sql_mode, separators=(",", ":"), ensure_ascii=True), + "current_user": current_user, + "connection_collation": collation, + } + if timezone_kind == "IANA": + value["session_timezone_name"] = timezone_name + value["session_timezone_tzdb_version"] = tzdb_version + else: + value["session_timezone_offset_minutes"] = str(offset) + for key in optional_text: + if raw.get(key, ""): + value[key] = raw[key] + return value + + +def _validate_typed_call_contract(payload: Dict[str, Any]) -> None: + fields = {"callsite_id", "may_error", "security_mode", "leakproof"} + present = fields & set(payload) + if not present: + return + if present != fields: + raise ValueError("UNSUPPORTED_ROUTINE_VERSION: incomplete typed routine semantic contract") + callsite_id = payload.get("callsite_id") + if not isinstance(callsite_id, str) or not callsite_id or len(callsite_id) > 256 or "\n" in callsite_id or "\r" in callsite_id: + raise ValueError("UNSUPPORTED_ROUTINE_VERSION: invalid typed routine callsite id") + if payload.get("may_error") is not True or payload.get("security_mode") != "INVOKER" or payload.get("leakproof") is not False: + raise ValueError("UNSUPPORTED_ROUTINE_VERSION: unsupported typed routine semantic contract") + frame = payload.get("security_frame") + if not isinstance(frame, dict) or set(frame) != _SECURITY_FRAME_KEYS: + raise ValueError("UNSUPPORTED_ROUTINE_VERSION: incomplete Python security frame") + if ( + type(frame.get("contract_version")) is not int + or frame["contract_version"] != 1 + or frame.get("mode") != "INVOKER" + ): + raise ValueError("UNSUPPORTED_ROUTINE_VERSION: unsupported Python security frame") + integer_fields = ("invoker_user_id", "invoker_role_id", "effective_user_id", "effective_role_id") + if any( + type(frame.get(key)) is not int + or frame[key] < 0 + or frame[key] > MAX_SECURITY_PRINCIPAL_ID + for key in integer_fields + ): + raise ValueError("UNSUPPORTED_ROUTINE_VERSION: invalid Python security frame") + if frame["invoker_user_id"] != frame["effective_user_id"] or frame["invoker_role_id"] != frame["effective_role_id"]: + raise ValueError("UNSUPPORTED_ROUTINE_VERSION: Python security frame changed effective principal") + + +def _handler_quota_owner(payload: Dict[str, Any]) -> str: + """Return the stable effective principal key used by the H budget. + + A session display username is mutable text and is not an identity boundary: + two principals can share it across roles or accounts. The typed security + frame has already been validated before this helper is called, so the + numeric effective IDs are the only values used for account/owner quota + accounting. + """ + frame = payload.get("security_frame") if isinstance(payload, dict) else None + if not isinstance(frame, dict): + raise ValueError("UNSUPPORTED_ROUTINE_VERSION: missing Python security frame") + user_id = frame.get("effective_user_id") + role_id = frame.get("effective_role_id") + if type(user_id) is not int or user_id < 0 or type(role_id) is not int or role_id < 0: + raise ValueError("UNSUPPORTED_ROUTINE_VERSION: invalid Python effective principal") + return f"user:{user_id}/role:{role_id}" + + +def _statement_context(raw: Any) -> Optional[StatementContext]: + if raw is None: + return None + if not isinstance(raw, dict): + raise ValueError("PROTOCOL: statement context must be an object") + unknown = set(raw) - _FENCING_CONTEXT_KEYS - _STATEMENT_CONTEXT_KEYS + if unknown: + raise ValueError("PROTOCOL: unsupported statement context field") + if not (set(raw) & _STATEMENT_CONTEXT_KEYS): + # The fencing fields are transport identity, not user-visible context. + return None + + timestamp_text = _required_context_value(raw, "statement_timestamp_utc") + try: + timestamp_micros = int(timestamp_text, 10) + if timestamp_micros < MIN_STATEMENT_TIMESTAMP_UTC or timestamp_micros > MAX_STATEMENT_TIMESTAMP_UTC: + raise ValueError("timestamp is outside the Python datetime range") + seconds, micros = divmod(timestamp_micros, 1_000_000) + timestamp = _datetime.datetime(1970, 1, 1, tzinfo=_datetime.timezone.utc) + _datetime.timedelta(seconds=seconds, microseconds=micros) + except (TypeError, ValueError, OverflowError) as exc: + raise ValueError("PROTOCOL: invalid statement_timestamp_utc") from exc + + timezone_kind = _required_context_value(raw, "session_timezone_kind") + if timezone_kind == "IANA": + timezone_name = _required_context_value(raw, "session_timezone_name") + tzdb_version = _required_context_value(raw, "session_timezone_tzdb_version") + if "session_timezone_offset_minutes" in raw: + raise ValueError("PROTOCOL: IANA timezone cannot carry a fixed offset") + if not TIMEZONE_DATABASE_VERSION or tzdb_version != TIMEZONE_DATABASE_VERSION: + raise ValueError("PROTOCOL: IANA timezone database version does not match the worker contract") + try: + ZoneInfo(timezone_name) + except (ZoneInfoNotFoundError, ValueError) as exc: + raise ValueError("PROTOCOL: IANA timezone is not present in the local tzdb") from exc + timezone = TimezoneContext("IANA", name=timezone_name, tzdb_version=tzdb_version) + elif timezone_kind == "FIXED_OFFSET": + offset_text = _required_context_value(raw, "session_timezone_offset_minutes") + try: + offset_minutes = int(offset_text, 10) + except (TypeError, ValueError) as exc: + raise ValueError("PROTOCOL: invalid fixed timezone offset") from exc + if offset_minutes < -839 or offset_minutes > 840: + raise ValueError("PROTOCOL: fixed timezone offset is outside SQL range") + if "session_timezone_name" in raw or "session_timezone_tzdb_version" in raw: + raise ValueError("PROTOCOL: fixed timezone cannot carry IANA identity") + timezone = TimezoneContext("FIXED_OFFSET", offset_minutes=offset_minutes) + else: + raise ValueError("PROTOCOL: unsupported timezone kind") + + sql_mode_text = _required_context_value(raw, "sql_mode") + try: + sql_mode_value = json.loads(sql_mode_text) + except (TypeError, ValueError) as exc: + raise ValueError("PROTOCOL: sql_mode must be canonical JSON array") from exc + if not isinstance(sql_mode_value, list) or any(not isinstance(item, str) for item in sql_mode_value): + raise ValueError("PROTOCOL: sql_mode must be an array of strings") + sql_mode = tuple(sorted(set(sql_mode_value))) + if list(sql_mode) != sql_mode_value or json.dumps(sql_mode_value, separators=(",", ":"), ensure_ascii=True) != sql_mode_text: + raise ValueError("PROTOCOL: sql_mode is not canonical") + + current_user = _required_context_value(raw, "current_user") + connection_collation = _required_context_value(raw, "connection_collation") + return StatementContext( + statement_timestamp_utc=timestamp, + session_timezone=timezone, + sql_mode=sql_mode, + current_database=_optional_context_value(raw, "current_database"), + current_user=current_user, + current_role=_optional_context_value(raw, "current_role"), + connection_collation=connection_collation, + ) + + +def _tuple_key(value: Dict[str, Any]) -> tuple: + if not isinstance(value, dict) or set(value) - _TUPLE_KEYS: + raise ValueError("PROTOCOL: unsupported fencing tuple field") + string_fields = ("statement_id", "group_id", "invocation_id") + if not isinstance(value, dict) or any(not isinstance(value.get(k), str) or not value[k] for k in string_fields): + raise ValueError("PROTOCOL: incomplete fencing tuple") + try: + for key in string_fields: + encoded = value[key].encode("utf-8") + if len(encoded) > MAX_FENCE_COMPONENT_BYTES: + raise ValueError("PROTOCOL: fencing tuple component is too large") + except UnicodeEncodeError as exc: + raise ValueError("PROTOCOL: fencing tuple contains invalid UTF-8") from exc + account_id = value.get("account_id") + if ( + isinstance(account_id, bool) + or not isinstance(account_id, int) + or account_id < 0 + or account_id > (1 << 64) - 1 + ): + raise ValueError("PROTOCOL: incomplete fencing tuple") + if any( + isinstance(value.get(k), bool) + or not isinstance(value.get(k), int) + or value[k] <= 0 + or value[k] > (1 << 64) - 1 + for k in ("group_epoch", "lease_epoch") + ): + raise ValueError("PROTOCOL: incomplete fencing tuple") + return ( + value["account_id"], + value["statement_id"], + value["group_id"], + value["group_epoch"], + value["invocation_id"], + value["lease_epoch"], + ) + + +def _function_ref(value: Any, tuple_value: Dict[str, Any]) -> tuple: + if not isinstance(value, dict) or set(value) != _FUNCTION_REF_KEYS: + raise ValueError("PROTOCOL: incomplete FunctionRef") + fields = {} + for key in _FUNCTION_REF_KEYS: + item = value.get(key) + minimum = 0 if key == "account_id" else 1 + if ( + isinstance(item, bool) + or not isinstance(item, int) + or item < minimum + or item > (1 << 64) - 1 + ): + raise ValueError(f"PROTOCOL: invalid FunctionRef field {key}") + fields[key] = item + if fields["account_id"] != tuple_value["account_id"]: + raise ValueError("PROTOCOL: FunctionRef account does not match the fencing tuple") + return tuple(fields[key] for key in ("account_id", "database_id", "function_id", "revision", "namespace_version")) + + +def _reject_duplicate_json_pairs(pairs): + result = {} + for key, value in pairs: + if key in result: + raise ValueError(f"PROTOCOL: duplicate control JSON field {key!r}") + result[key] = value + return result + + +def _reject_nonstandard_json_constant(value): + raise ValueError(f"PROTOCOL: invalid JSON constant {value}") + + +def _validate_json_nesting(data: bytes) -> None: + depth = 0 + in_string = False + escaped = False + for byte in data: + if in_string: + if escaped: + escaped = False + elif byte == 0x5C: # backslash + escaped = True + elif byte == 0x22: # double quote + in_string = False + continue + if byte == 0x22: + in_string = True + elif byte == 0x7B or byte == 0x5B: # { or [ + depth += 1 + if depth > MAX_JSON_NESTING: + raise ValueError( + f"PROTOCOL: control JSON nesting exceeds {MAX_JSON_NESTING} levels" + ) + elif byte == 0x7D or byte == 0x5D: # } or ] + depth -= 1 + + +def _decode_control(data: bytes) -> Dict[str, Any]: + if not data or len(data) > MAX_CONTROL_BYTES: + raise ValueError("PROTOCOL: invalid control size") + _validate_json_nesting(data) + try: + text = bytes(data).decode("utf-8") + except UnicodeDecodeError as exc: + raise ValueError("PROTOCOL: invalid control UTF-8") from exc + try: + value = json.loads( + text, + object_pairs_hook=_reject_duplicate_json_pairs, + parse_constant=_reject_nonstandard_json_constant, + ) + except json.JSONDecodeError as exc: + raise ValueError("PROTOCOL: invalid control JSON") from exc + except RecursionError as exc: + raise ValueError("PROTOCOL: control JSON is too deeply nested") from exc + if ( + not isinstance(value, dict) + or type(value.get("version")) is not int + or value["version"] != PROTOCOL_VERSION + or not isinstance(value.get("kind"), str) + or not value["kind"] + ): + raise ValueError("PROTOCOL: unsupported control") + if set(value) - _CONTROL_KEYS: + raise ValueError("PROTOCOL: unsupported control field") + _tuple_key(value.get("tuple") or {}) + _validate_control_fields(value, wire=True) + return value + + +def _decode_capability_request(data: bytes) -> Dict[str, Any]: + if not data or len(data) > MAX_CONTROL_BYTES: + raise ValueError("PROTOCOL: invalid capability request size") + _validate_json_nesting(data) + try: + value = json.loads( + bytes(data).decode("utf-8"), + object_pairs_hook=_reject_duplicate_json_pairs, + parse_constant=_reject_nonstandard_json_constant, + ) + except (UnicodeDecodeError, json.JSONDecodeError, RecursionError) as exc: + raise ValueError("PROTOCOL: invalid capability request JSON") from exc + if not isinstance(value, dict) or set(value) != _CAPABILITY_REQUEST_KEYS: + raise ValueError("PROTOCOL: invalid capability request fields") + if type(value.get("protocol_version")) is not int or value["protocol_version"] != PROTOCOL_VERSION: + raise ValueError("PROTOCOL: unsupported capability protocol version") + return value + + +def _decode_definition_validation(data: bytes) -> Dict[str, Any]: + """Decode the strict, pre-publication definition validation payload.""" + if not data or len(data) > MAX_DEFINITION_VALIDATION_BYTES: + raise ValueError("PROTOCOL: invalid definition validation size") + _validate_json_nesting(data) + try: + value = json.loads( + bytes(data).decode("utf-8"), + object_pairs_hook=_reject_duplicate_json_pairs, + parse_constant=_reject_nonstandard_json_constant, + ) + except (UnicodeDecodeError, json.JSONDecodeError, RecursionError) as exc: + raise ValueError("PROTOCOL: invalid definition validation JSON") from exc + if not isinstance(value, dict) or set(value) != _DEFINITION_VALIDATION_KEYS: + raise ValueError("PROTOCOL: invalid definition validation fields") + + account_id = value.get("account_id") + if ( + isinstance(account_id, bool) + or not isinstance(account_id, int) + or account_id < 0 + or account_id > (1 << 64) - 1 + ): + raise ValueError("PROTOCOL: invalid definition validation account") + handler = _required_string(value, "handler") + if ":" in handler: + raise ValueError( + "UNSUPPORTED_ROUTINE_VERSION: Python external handler import requires the immutable artifact catalog" + ) + source = _required_string(value, "source") + try: + source_bytes = source.encode("utf-8") + except UnicodeEncodeError as exc: + raise ValueError("PROTOCOL: definition validation source is not valid UTF-8") from exc + if len(source_bytes) > (1 << 20): + raise ValueError("RESOURCE_EXHAUSTED: Python artifact exceeds 1048576 bytes") + + mode = _required_string(value, "mode") + null_policy = _required_string(value, "null_policy") + abi_contract = _required_string(value, "abi_contract") + adapter_version = _required_string(value, "adapter_version") + sdk_version = _required_string(value, "sdk_version") + if mode not in (MODE_SCALAR, MODE_VECTOR) or null_policy not in (NULL_CALL, NULL_RETURN): + raise ValueError("UNSUPPORTED_ROUTINE_VERSION: unsupported Python mode or NULL policy") + if abi_contract != ABI_CONTRACT or adapter_version != ADAPTER_VERSION: + raise ValueError("UNSUPPORTED_ROUTINE_VERSION: unsupported Python ABI contract") + if sdk_version != SDK_VERSION: + raise ValueError("UNSUPPORTED_ROUTINE_VERSION: unsupported Python SDK") + definition_schema_version = value.get("definition_schema_version") + if ( + type(definition_schema_version) is not int + or definition_schema_version != DEFINITION_SCHEMA_VERSION + ): + raise ValueError("UNSUPPORTED_ROUTINE_VERSION: unsupported Python definition schema") + artifact_digest = _required_digest(value, "artifact_digest") + environment_digest = _required_digest(value, "environment_digest") + definition_fingerprint = _required_digest(value, "definition_fingerprint") + if artifact_digest != _inline_artifact_digest(handler, source): + raise ValueError( + "UNSUPPORTED_ROUTINE_VERSION: Python artifact digest does not match the source" + ) + if environment_digest != _environment_digest(): + raise ValueError( + "UNSUPPORTED_ROUTINE_VERSION: Python environment digest does not match the worker contract" + ) + + args = value.get("args") + result_descriptor = value.get("return") + if not isinstance(args, list) or any(not isinstance(item, dict) for item in args): + raise ValueError("TYPE_CONTRACT: definition validation args must be an array of descriptors") + if not isinstance(result_descriptor, dict): + raise ValueError("TYPE_CONTRACT: definition validation return must be a descriptor") + for index, descriptor in enumerate(args): + _field(f"arg_{index}", descriptor) + _field("return", result_descriptor) + expected_fingerprint = _definition_fingerprint(value) + if definition_fingerprint != expected_fingerprint: + raise ValueError( + "UNSUPPORTED_ROUTINE_VERSION: Python definition fingerprint does not match the typed definition" + ) + return value + + +def _validate_definition_syntax(value: Dict[str, Any]) -> None: + """Validate source and the static handler binding without executing it.""" + import ast + + try: + compile(value["source"], "", "exec") + except SyntaxError as exc: + line = exc.lineno or 0 + column = exc.offset or 0 + message = exc.msg or "invalid syntax" + raise ValueError( + f"USER_CODE: Python syntax error at line {line}, column {column}: {message}" + ) from exc + handler = value["handler"] + if not handler.isidentifier(): + raise ValueError( + "USER_CODE: Python handler must be a module-level identifier" + ) + tree = ast.parse(value["source"], filename="", mode="exec") + binding = None + + class NestedModuleBindingVisitor(ast.NodeVisitor): + """Find handler bindings below a module statement. + + A handler must be established by an unconditional module-level + function definition or lambda assignment. Assignments in control + flow, imports, and pattern targets can otherwise leave CREATE looking + valid while the value exposed by exec() is absent or non-callable. + Function/class bodies and comprehension targets have their own scope + and are deliberately not treated as module rebinding. + """ + + def __init__(self): + self.found = False + + def _mark(self): + self.found = True + + def visit_Name(self, node): + if node.id == handler and isinstance(node.ctx, (ast.Store, ast.Del)): + self._mark() + + def visit_FunctionDef(self, node): + if node.name == handler: + self._mark() + + def visit_AsyncFunctionDef(self, node): + if node.name == handler: + self._mark() + + def visit_ClassDef(self, node): + if node.name == handler: + self._mark() + + def visit_Lambda(self, node): + return + + def visit_ListComp(self, node): + self.visit(node.elt) + for generator in node.generators: + self.visit(generator.iter) + for condition in generator.ifs: + self.visit(condition) + + visit_SetComp = visit_ListComp + visit_GeneratorExp = visit_ListComp + + def visit_DictComp(self, node): + self.visit(node.key) + self.visit(node.value) + for generator in node.generators: + self.visit(generator.iter) + for condition in generator.ifs: + self.visit(condition) + + def visit_Import(self, node): + for alias in node.names: + bound = alias.asname or alias.name.split(".", 1)[0] + if bound == handler: + self._mark() + + def visit_ImportFrom(self, node): + for alias in node.names: + if alias.name == "*" or (alias.asname or alias.name) == handler: + self._mark() + + def visit_ExceptHandler(self, node): + if node.name == handler: + self._mark() + # A bare ``except:`` has no exception-expression node. Keep + # walking its body without asking NodeVisitor to visit None. + if node.type is not None: + self.visit(node.type) + self.visit_nodes(node.body) + + def visit_MatchAs(self, node): + if node.name == handler: + self._mark() + if node.pattern is not None: + self.visit(node.pattern) + + def visit_MatchStar(self, node): + if node.name == handler: + self._mark() + + def visit_MatchMapping(self, node): + # ``rest`` is the capture name in a ``**name`` mapping pattern, + # represented as a plain string rather than an ast.Name. + if node.rest == handler: + self._mark() + self.visit_nodes(node.keys) + self.visit_nodes(node.patterns) + + def visit_nodes(self, nodes): + for child in nodes: + self.visit(child) + + for node in tree.body: + if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)) and node.name == handler: + # Continue scanning: a later module-level assignment can replace + # the function object that exec() will expose to the runtime. + binding = "async" if isinstance(node, ast.AsyncFunctionDef) else "sync" + continue + if isinstance(node, ast.ClassDef) and node.name == handler: + binding = "other" + continue + if isinstance(node, ast.Assign): + if any(isinstance(target, ast.Name) and target.id == handler for target in node.targets): + binding = "lambda" if isinstance(node.value, ast.Lambda) else "other" + continue + if isinstance(node, ast.AnnAssign): + if isinstance(node.target, ast.Name) and node.target.id == handler: + binding = "lambda" if isinstance(node.value, ast.Lambda) else "other" + continue + if isinstance(node, ast.Delete): + if any(isinstance(target, ast.Name) and target.id == handler for target in node.targets): + binding = "other" + continue + visitor = NestedModuleBindingVisitor() + visitor.visit(node) + if visitor.found: + binding = "other" + if binding == "async": + raise ValueError("USER_CODE: Python handler must be synchronous") + if binding not in ("sync", "lambda"): + raise ValueError( + f"USER_CODE: Python handler {handler!r} is not a module-level function" + ) + + +def _encode_definition_validation_result( + value: Dict[str, Any], status: str, reason: Optional[str] = None +) -> bytes: + response = {"status": status} + if reason: + response["reason"] = reason + if status == "OK": + response["artifact_digest"] = value["artifact_digest"] + response["definition_fingerprint"] = value["definition_fingerprint"] + return json.dumps(response, separators=(",", ":"), sort_keys=True, allow_nan=False).encode( + "utf-8" + ) + + +def _encode_capabilities(request: Dict[str, Any], lease_epoch: int = 1) -> bytes: + _decode_capability_request(json.dumps(request, separators=(",", ":")).encode("utf-8")) + if isinstance(lease_epoch, bool) or not isinstance(lease_epoch, int) or lease_epoch <= 0 or lease_epoch > (1 << 64) - 1: + raise ValueError("PROTOCOL: invalid worker lease epoch") + value = { + "protocol_version": PROTOCOL_VERSION, + "abi_contract": ABI_CONTRACT, + "adapter_version": ADAPTER_VERSION, + "sdk_version": SDK_VERSION, + "definition_schema_version": DEFINITION_SCHEMA_VERSION, + "plan_contract_version": PLAN_CONTRACT_VERSION, + "type_descriptor_contract": TYPE_DESCRIPTOR_CONTRACT, + "timezone_database_version": TIMEZONE_DATABASE_VERSION, + "modes": [MODE_SCALAR, MODE_VECTOR], + "null_policies": [NULL_CALL, NULL_RETURN], + # The current implementation intentionally exposes one in-flight + # batch per invocation. This is a capability, not an implied promise + # that a future worker accepts cumulative ACKs. + "window_batches": 1, + "cumulative_ack": False, + "max_execution_frame_bytes": MAX_EXECUTION_FRAME_BYTES, + "max_handler_processes": MAX_HANDLER_PROCESSES, + "max_account_handler_processes": MAX_ACCOUNT_HANDLER_PROCESSES, + "max_owner_handler_processes": MAX_OWNER_HANDLER_PROCESSES, + # This is an instance lease, not a liveness timer. A new worker + # process gets a new value, so a Gateway cannot accidentally reuse an + # invocation tuple that was admitted by a previous worker instance. + "lease_epoch": lease_epoch, + } + if set(value) != _CAPABILITY_RESPONSE_KEYS: + raise ValueError("PROTOCOL: invalid capability response") + encoded = json.dumps( + value, separators=(",", ":"), sort_keys=True, allow_nan=False + ).encode("utf-8") + if len(encoded) > MAX_CONTROL_BYTES: + raise ValueError("RESOURCE_EXHAUSTED: capability response is too large") + return encoded + + +def _require_tuple(value: Dict[str, Any], expected: Dict[str, Any]) -> None: + if _tuple_key(value) != _tuple_key(expected): + raise ValueError("PROTOCOL: fencing tuple changed") + + +def _required_string(value: Dict[str, Any], key: str) -> str: + item = value.get(key) + if not isinstance(item, str) or not item: + raise ValueError(f"PROTOCOL: missing invocation field {key}") + return item + + +def _required_digest(value: Dict[str, Any], key: str) -> str: + item = _required_string(value, key) + if len(item) != hashlib.sha256().digest_size * 2: + raise ValueError(f"PROTOCOL: invalid invocation field {key}") + try: + decoded = bytes.fromhex(item) + except ValueError as exc: + raise ValueError(f"PROTOCOL: invalid invocation field {key}") from exc + if item.lower() != item or len(decoded) != hashlib.sha256().digest_size: + raise ValueError(f"PROTOCOL: invalid invocation field {key}") + return item + + +def _required_positive_int(value: Dict[str, Any], key: str, maximum: int) -> int: + item = value.get(key) + if isinstance(item, bool) or not isinstance(item, int) or item <= 0 or item > maximum: + raise ValueError(f"PROTOCOL: invalid invocation field {key}") + return item + + +def _required_positive_float(value: Dict[str, Any], key: str, maximum: float) -> float: + item = value.get(key) + if ( + isinstance(item, bool) + or not isinstance(item, (int, float)) + or not math.isfinite(item) + or item <= 0 + or item > maximum + ): + raise ValueError(f"PROTOCOL: invalid invocation field {key}") + return float(item) + + +def _required_uint64(value: Dict[str, Any], key: str, allow_zero: bool = False) -> int: + item = value.get(key) + minimum = 0 if allow_zero else 1 + if isinstance(item, bool) or not isinstance(item, int) or item < minimum or item > (1 << 64) - 1: + raise ValueError(f"PROTOCOL: invalid control field {key}") + return item + + +def _validate_control_fields(value: Dict[str, Any], wire: bool) -> None: + kind = value["kind"] + rule = _CONTROL_FIELD_RULES.get(kind) + if rule is None: + raise ValueError(f"PROTOCOL: unsupported control kind {kind!r}") + allowed, required = rule + fields = set(value) - _CONTROL_BASE_KEYS + invalid = fields - allowed + if invalid: + raise ValueError( + f"PROTOCOL: field {next(iter(invalid))!r} is not valid for control kind {kind!r}" + ) + if wire: + missing = required - set(value) + if missing: + raise ValueError( + f"PROTOCOL: control kind {kind!r} is missing field {next(iter(missing))!r}" + ) + if "sequence" in value: + _required_uint64(value, "sequence") + if "last_sequence" in value: + _required_uint64(value, "last_sequence", allow_zero=True) + if "last_result_sequence" in value: + _required_uint64(value, "last_result_sequence", allow_zero=True) + if "ack_sequence" in value: + _required_uint64(value, "ack_sequence") + if "released_bytes" in value: + _required_positive_int(value, "released_bytes", MAX_EXECUTION_FRAME_BYTES) + if "released_batches" in value: + _required_uint64(value, "released_batches") + if "finish_id" in value: + _required_string(value, "finish_id") + if "status" in value: + _required_string(value, "status") + if "reason" in value: + _required_string(value, "reason") + if kind == "Ack": + if ("ack_sequence" in value) == ("finish_id" in value): + raise ValueError("PROTOCOL: Ack requires exactly one acknowledgement identity") + elif kind == "OpenInvocation": + if "payload" not in value: + raise ValueError("PROTOCOL: control kind 'OpenInvocation' is missing field 'payload'") + if not isinstance(value["payload"], dict): + raise ValueError("PROTOCOL: control kind 'OpenInvocation' payload must be an object") + + +def _encode_control(value: Dict[str, Any]) -> bytes: + value = dict(value) + if set(value) - _CONTROL_KEYS: + raise ValueError("PROTOCOL: unsupported control field") + value.setdefault("version", PROTOCOL_VERSION) + _tuple_key(value["tuple"]) + # The encoder is the last boundary before bytes leave the worker. It + # must enforce the same required fields as the decoder; otherwise a new + # producer can emit a frame that Go's MarshalControl would reject. + _validate_control_fields(value, wire=True) + try: + data = json.dumps( + value, + separators=(",", ":"), + ensure_ascii=True, + allow_nan=False, + ).encode("utf-8") + except (TypeError, ValueError, UnicodeError) as exc: + raise ValueError("PROTOCOL: invalid control JSON") from exc + if len(data) > MAX_CONTROL_BYTES: + raise ValueError("PROTOCOL: control is too large") + return data + + +def _canonical_descriptor(descriptor: Dict[str, Any]) -> bytes: + if not isinstance(descriptor, dict): + raise ValueError("TYPE_CONTRACT: descriptor must be an object") + unknown = set(descriptor) - _DESCRIPTOR_KEYS + if unknown: + raise ValueError("TYPE_CONTRACT: unsupported descriptor field") + if type(descriptor.get("type_id")) is not int: + raise ValueError("TYPE_CONTRACT: descriptor type_id must be an integer") + for key in _DESCRIPTOR_INT_KEYS - {"type_id"}: + if key in descriptor and type(descriptor[key]) is not int: + raise ValueError(f"TYPE_CONTRACT: descriptor {key} must be an integer") + for key in _DESCRIPTOR_INT_KEYS: + if key in descriptor and not MIN_INT32 <= descriptor[key] <= MAX_INT32: + raise ValueError(f"TYPE_CONTRACT: descriptor {key} is outside int32 range") + for key in _DESCRIPTOR_TEXT_KEYS: + if key in descriptor and type(descriptor[key]) is not str: + raise ValueError(f"TYPE_CONTRACT: descriptor {key} must be text") + _validate_descriptor_domain(descriptor) + order = ("type_id", "width", "scale", "charset", "offset_width", "json_encoding", "temporal_encoding") + result = {} + for key in order: + value = descriptor.get(key) + if key == "type_id" or value not in (None, 0, ""): + result[key] = value + return json.dumps(result, separators=(",", ":"), ensure_ascii=True).encode("utf-8") + + +def _validate_descriptor_domain(descriptor: Dict[str, Any]) -> None: + type_id = int(descriptor["type_id"]) + width = int(descriptor.get("width") or 0) + scale = int(descriptor.get("scale") or 0) + charset = int(descriptor.get("charset") or 0) + expected_offset_width = 0 if type_id in (UUID, VECF32, VECF64) else 32 + if width < 0: + raise ValueError("TYPE_CONTRACT: descriptor width must be non-negative") + if scale < 0: + raise ValueError("TYPE_CONTRACT: descriptor scale must be non-negative") + # A 32-bit offset is part of the canonical descriptor for ordinary values + # and is serialized by the Go descriptor. Only fixed-width UUID/vector + # descriptors omit the zero-valued field. Do not turn a missing or + # explicitly zero ordinary offset into an implicit default: that would + # accept a damaged Catalog row and produce a different ABI on the two + # sides. + if expected_offset_width == 32 and "offset_width" not in descriptor: + raise ValueError("TYPE_CONTRACT: descriptor offset_width is required") + if int(descriptor.get("offset_width", expected_offset_width)) != expected_offset_width: + raise ValueError( + f"TYPE_CONTRACT: descriptor offset_width must be {expected_offset_width}" + ) + json_encoding = descriptor.get("json_encoding") + if json_encoding not in (None, "") and (type_id != JSON or json_encoding != "canonical_text"): + raise ValueError("TYPE_CONTRACT: unsupported JSON encoding") + if type_id == JSON and json_encoding != "canonical_text": + raise ValueError("TYPE_CONTRACT: JSON descriptor must use canonical_text encoding") + temporal_encoding = descriptor.get("temporal_encoding") + if temporal_encoding not in (None, "") and ( + type_id not in (DATE, DATETIME, TIMESTAMP) or temporal_encoding != "sql_zero_struct" + ): + raise ValueError("TYPE_CONTRACT: unsupported temporal encoding") + if type_id in (DATE, DATETIME, TIMESTAMP) and temporal_encoding != "sql_zero_struct": + raise ValueError("TYPE_CONTRACT: temporal descriptor must use sql_zero_struct encoding") + + if type_id in ( + BOOL, INT8, INT16, INT32, INT64, UINT8, UINT16, UINT32, UINT64, + FLOAT32, FLOAT64, JSON, + ): + if width or scale or charset: + raise ValueError("TYPE_CONTRACT: descriptor carries unused fields") + elif type_id in (DECIMAL64, DECIMAL128): + maximum = 18 if type_id == DECIMAL64 else 38 + if width < 1 or width > maximum: + raise ValueError("TYPE_CONTRACT: decimal precision is outside the supported range") + if scale > width: + raise ValueError("TYPE_CONTRACT: decimal scale exceeds precision") + if charset: + raise ValueError("TYPE_CONTRACT: decimal descriptor carries a charset") + elif type_id == DATE: + if width or scale or charset: + raise ValueError("TYPE_CONTRACT: DATE descriptor has invalid scale or charset") + elif type_id in (TIME, DATETIME, TIMESTAMP): + if width or scale > 6 or charset: + raise ValueError("TYPE_CONTRACT: temporal scale or charset is outside the supported range") + elif type_id in (CHAR, VARCHAR, TEXT): + if scale: + raise ValueError("TYPE_CONTRACT: text descriptor carries an unused scale") + if charset not in (0, 2, 3): + raise ValueError("TYPE_CONTRACT: unsupported text charset") + elif type_id in (BINARY, VARBINARY, BLOB): + if scale or charset != 1: + raise ValueError("TYPE_CONTRACT: binary descriptor must use the binary charset") + elif type_id == UUID: + if width or scale or charset: + raise ValueError("TYPE_CONTRACT: UUID descriptor carries unused fields") + elif type_id in (VECF32, VECF64): + if width < 1 or width > 65535 or scale or charset: + raise ValueError("TYPE_CONTRACT: vector dimension or metadata is outside the supported range") + else: + raise ValueError(f"TYPE_CONTRACT: unsupported type id {type_id}") + + +def _physical_fingerprint(descriptor: Dict[str, Any]) -> str: + type_id = int(descriptor["type_id"]) + primitive = { + BOOL: "@B", INT8: "@D", INT16: "@F", INT32: "@H", INT64: "@J", + UINT8: "@C", UINT16: "@E", UINT32: "@G", UINT64: "@I", + FLOAT32: "@L", FLOAT64: "@M", BINARY: "@O", BLOB: "@O", VARBINARY: "@O", + TIME: "@bu", + } + if type_id in primitive: + return primitive[type_id] + if type_id in (CHAR, VARCHAR, TEXT, JSON): + return "@d" if int(descriptor.get("offset_width", 32)) == 64 else "@N" + if type_id == UUID: + return "@P[16]" + if type_id in (DECIMAL64, DECIMAL128): + precision = int(descriptor.get("width") or (18 if type_id == DECIMAL64 else 38)) + return f"@X[128,{precision},{int(descriptor.get('scale') or 0)}]" + if type_id == DATE: + return "@[{FNis_zero{@B};FNvalue{@Q};}" + if type_id == DATETIME: + return "@[{FNis_zero{@B};FNvalue{@Su0:};}" + if type_id == TIMESTAMP: + return "@[{FNis_zero{@B};FNvalue{@Su3:UTC};}" + if type_id == VECF32: + return f"@a[{int(descriptor.get('width') or 0)}]{{@L}}" + if type_id == VECF64: + return f"@a[{int(descriptor.get('width') or 0)}]{{@M}}" + raise ValueError(f"TYPE_CONTRACT: unsupported type id {type_id}") + + +def _fingerprint(descriptor: Dict[str, Any]) -> str: + data = b"matrixone-python-udf-type\x00" + _canonical_descriptor(descriptor) + b"\x00" + _physical_fingerprint(descriptor).encode() + return hashlib.sha256(data).hexdigest() + + +def _arrow_type(descriptor: Dict[str, Any]) -> pa.DataType: + type_id = int(descriptor["type_id"]) + simple = { + BOOL: pa.bool_, INT8: pa.int8, INT16: pa.int16, INT32: pa.int32, INT64: pa.int64, + UINT8: pa.uint8, UINT16: pa.uint16, UINT32: pa.uint32, UINT64: pa.uint64, + FLOAT32: pa.float32, FLOAT64: pa.float64, + } + if type_id in simple: + return simple[type_id]() + if type_id in (DECIMAL64, DECIMAL128): + precision = int(descriptor.get("width") or (18 if type_id == DECIMAL64 else 38)) + return pa.decimal128(precision, int(descriptor.get("scale") or 0)) + if type_id in (CHAR, VARCHAR, TEXT, JSON): + return pa.large_string() if int(descriptor.get("offset_width", 32)) == 64 else pa.string() + if type_id in (BINARY, VARBINARY, BLOB): + return pa.large_binary() if int(descriptor.get("offset_width", 32)) == 64 else pa.binary() + if type_id == UUID: + return pa.binary(16) + if type_id == TIME: + return pa.duration("us") + if type_id in (VECF32, VECF64): + width = int(descriptor.get("width") or 0) + if width <= 0: + raise ValueError("TYPE_CONTRACT: vector dimension must be positive") + return pa.list_(pa.float32() if type_id == VECF32 else pa.float64(), width) + if type_id == DATE: + child = pa.date32() + elif type_id == DATETIME: + child = pa.timestamp("us") + elif type_id == TIMESTAMP: + child = pa.timestamp("us", tz="UTC") + else: + raise ValueError(f"TYPE_CONTRACT: unsupported type id {type_id}") + return pa.struct([pa.field("is_zero", pa.bool_(), nullable=False), pa.field("value", child, nullable=False)]) + + +def _field(name: str, descriptor: Dict[str, Any]) -> pa.Field: + metadata = { + TypeMetadataKey: _canonical_descriptor(descriptor), + TypeFingerprintKey: _fingerprint(descriptor).encode("ascii"), + } + return pa.field(name, _arrow_type(descriptor), nullable=True, metadata=metadata) + + +def _schema_from_descriptors( + descriptors: Iterable[Dict[str, Any]], prefix: str +) -> pa.Schema: + return pa.schema( + [_field(f"{prefix}_{index}", descriptor) for index, descriptor in enumerate(descriptors)] + ) + + +TypeMetadataKey = b"mo.udf.type" +TypeFingerprintKey = b"mo.udf.type_fingerprint" + + +def _validate_field(field: pa.Field, name: str, descriptor: Dict[str, Any]) -> None: + expected = _field(name, descriptor) + if field.name != name: + raise ValueError(f"TYPE_CONTRACT: Arrow field name {field.name!r} does not match {name!r}") + if field.type != expected.type: + raise ValueError(f"TYPE_CONTRACT: Arrow type {field.type} does not match {expected.type}") + if field.nullable != expected.nullable: + raise ValueError( + f"TYPE_CONTRACT: Arrow field nullable={field.nullable} does not match {expected.nullable}" + ) + if field.metadata != expected.metadata: + raise ValueError("TYPE_CONTRACT: Arrow logical metadata does not match the frozen descriptor") + + +def _validate_schema(schema: pa.Schema, descriptors: Iterable[Dict[str, Any]]) -> None: + descriptors = list(descriptors) + if len(schema) != len(descriptors): + raise ValueError("TYPE_CONTRACT: input column count does not match the routine signature") + for index, descriptor in enumerate(descriptors): + _validate_field(schema.field(index), f"arg_{index}", descriptor) + + +def _validate_input_batch_schema( + batch: pa.RecordBatch, expected_schema: pa.Schema, descriptors: Iterable[Dict[str, Any]] +) -> None: + # Flight carries one stream schema, but each received RecordBatch still + # owns a schema object. Validate every batch so a later frame cannot + # replace a fixed-width Arrow type after the first frame was admitted. + # The first batch validates every field against the descriptor. Later + # batches only need the schema equality check in the normal case; rebuilding + # every Field and its metadata for every batch was measurable overhead on + # small W=1 bursts. Retain the detailed validation on the mismatch path so + # a malformed later frame still gets the same contract diagnosis. + # PyArrow's Schema equality ignores metadata by default. The metadata + # carries the frozen logical descriptor and fingerprint, so a later batch + # with the same physical type but a different contract must not pass this + # fast path. + if batch.schema.equals(expected_schema, check_metadata=True): + return + _validate_schema(batch.schema, descriptors) + raise ValueError("TYPE_CONTRACT: input batch schema changed") + + +def _load_handler(source: str, handler: str): + if ":" in handler: + raise ValueError( + "UNSUPPORTED_ROUTINE_VERSION: Python external handler import requires an immutable artifact catalog" + ) + # CREATE validates the source without executing it, but execution may be + # reached through a direct Flight request or a stale/malformed caller. + # Reapply the static binding contract before exec so invalid module-level + # rebinding cannot run top-level user code before being rejected. + _validate_definition_syntax({"source": source, "handler": handler}) + namespace: Dict[str, Any] = {"__name__": "__matrixone_routine__"} + exec(compile(source, "", "exec"), namespace, namespace) + function = namespace.get(handler) + if not callable(function) or inspect.iscoroutinefunction(function): + raise ValueError("USER_CODE: handler must be a synchronous callable") + return function + + +def _scalar_input(array: pa.Array, row: int, descriptor: Dict[str, Any]): + return _scalar_input_value(array[row].as_py(), descriptor) + + +def _scalar_input_value(value: Any, descriptor: Dict[str, Any]): + if value is None: + return None + type_id = int(descriptor["type_id"]) + if type_id in (VECF32, VECF64): + # A scalar vector is exposed as read-only bytes. Consumers can use + # memoryview.cast("f"/"d") without receiving a mutable Arrow buffer. + import struct + values = value + fmt = "f" if type_id == VECF32 else "d" + return memoryview(struct.pack("<" + fmt * len(values), *values)) + if type_id in (DATE, DATETIME, TIMESTAMP): + zero = bool(value["is_zero"]) + child = value["value"] + if type_id == DATE: + return SqlDate(zero, None if zero else child) + if type_id == DATETIME: + return SqlDatetime(zero, None if zero else child) + return SqlTimestamp(zero, None if zero else child) + if type_id == JSON: + return _canonical_json_text(value) + if type_id == UUID: + return _uuid.UUID(bytes=bytes(value)) + return value + + +def _scalar_column_values(array: pa.Array): + """Materialize cheap fixed-width scalar columns once per batch. + + Calling Array.__getitem__().as_py() for every argument and row crosses + the PyArrow/Python boundary repeatedly. Primitive values have a bounded + representation under the batch row/byte limits, so one to_pylist() call + lets the scalar loop reuse those Python objects. Keep small, nested, and + variable-width values on the indexed path: that avoids retaining a second + copy of user data while preserving the same per-row conversion contract. + """ + if len(array) < SCALAR_MATERIALIZATION_MIN_ROWS: + return None + data_type = array.type + if ( + pa.types.is_boolean(data_type) + or pa.types.is_integer(data_type) + or pa.types.is_floating(data_type) + ): + return array.to_pylist() + return None + + +def _canonical_json_text(value: str) -> str: + if not isinstance(value, str): + raise ValueError("TYPE_CONTRACT: JSON value must be text") + + def reject_nonstandard_number(_constant: str): + raise ValueError("non-standard JSON number") + + try: + json.loads( + value, + parse_constant=reject_nonstandard_number, + # JSON values cross the ABI as compact text. Parsing numbers as + # strings keeps validation independent of Python's binary-float + # range; Go's json.Compact accepts valid tokens such as 1e999 and + # the handler must observe that exact token unchanged. + parse_int=str, + parse_float=str, + ) + except Exception as exc: + raise ValueError("TYPE_CONTRACT: invalid JSON input") from exc + # Match the Gateway's json.Compact contract: remove insignificant + # whitespace without rewriting number or string tokens. A loads/dumps + # round trip changes e.g. 1e-7 to 1e-07 and makes SCALAR and VECTOR + # handlers observe different text for the same SQL value. + compact = [] + in_string = False + escaped = False + for char in value: + if in_string: + compact.append(char) + if escaped: + escaped = False + elif char == "\\": + escaped = True + elif char == '"': + in_string = False + elif char == '"': + in_string = True + compact.append(char) + elif char not in " \t\r\n": + compact.append(char) + return "".join(compact) + + +def _check_json(value: str) -> str: + try: + canonical = _canonical_json_text(value) + except ValueError as exc: + raise ValueError("TYPE_CONTRACT: JSON result must be canonical text") from exc + if canonical != value: + raise ValueError("TYPE_CONTRACT: JSON result is not canonical text") + return value + + +def _check_microsecond_scale(value: int, descriptor: Dict[str, Any]) -> None: + scale = int(descriptor.get("scale") or 0) + if scale < 0 or scale > 6: + raise ValueError("TYPE_CONTRACT: temporal scale is outside the supported range") + quantum = 10 ** (6 - scale) + if value % quantum != 0: + raise ValueError("TYPE_CONTRACT: temporal value exceeds the declared scale") + + +def _timedelta_micros(value: _datetime.timedelta) -> int: + return (value.days * 24 * 60 * 60 + value.seconds) * _MICROS_PER_SECOND + value.microseconds + + +def _check_scalar(value: Any, descriptor: Dict[str, Any]): + if value is None: + return None + type_id = int(descriptor["type_id"]) + if type_id == BOOL and type(value) is not bool: raise ValueError("TYPE_CONTRACT: expected bool") + if type_id in (INT8, INT16, INT32, INT64, UINT8, UINT16, UINT32, UINT64) and (type(value) is not int): raise ValueError("TYPE_CONTRACT: expected integer") + if type_id in (FLOAT32, FLOAT64) and type(value) is not float: raise ValueError("TYPE_CONTRACT: expected float") + if type_id in (CHAR, VARCHAR, TEXT): + if type(value) is not str: raise ValueError("TYPE_CONTRACT: expected string") + width = int(descriptor.get("width") or 0) + if width > 0 and len(value) > width: raise ValueError("TYPE_CONTRACT: string exceeds the declared width") + return value + if type_id == JSON: return _check_json(value) + if type_id in (BINARY, VARBINARY, BLOB): + if type(value) is not bytes: raise ValueError("TYPE_CONTRACT: expected bytes") + width = int(descriptor.get("width") or 0) + if width > 0 and len(value) > width: raise ValueError("TYPE_CONTRACT: binary value exceeds the declared width") + return value + if type_id == UUID: + if not isinstance(value, _uuid.UUID): raise ValueError("TYPE_CONTRACT: expected uuid.UUID") + return value + if type_id == TIME: + if not isinstance(value, _datetime.timedelta): raise ValueError("TYPE_CONTRACT: expected datetime.timedelta") + micros = _timedelta_micros(value) + if abs(micros) > _MAX_TIME_MICROS: raise ValueError("TYPE_CONTRACT: TIME is outside the SQL range") + _check_microsecond_scale(micros, descriptor) + return value + if type_id == DATE: + if not isinstance(value, SqlDate) or (value.is_zero and value.value is not None) or (not value.is_zero and type(value.value) is not _datetime.date): raise ValueError("TYPE_CONTRACT: invalid SqlDate") + return value + if type_id == DATETIME: + if not isinstance(value, SqlDatetime) or (value.is_zero and value.value is not None) or (not value.is_zero and (not isinstance(value.value, _datetime.datetime) or value.value.tzinfo is not None)): raise ValueError("TYPE_CONTRACT: invalid SqlDatetime") + if not value.is_zero: _check_microsecond_scale(value.value.microsecond, descriptor) + return value + if type_id == TIMESTAMP: + if not isinstance(value, SqlTimestamp) or (value.is_zero and value.value is not None) or (not value.is_zero and (not isinstance(value.value, _datetime.datetime) or value.value.tzinfo is None or value.value.utcoffset() != _datetime.timedelta(0))): raise ValueError("TYPE_CONTRACT: invalid SqlTimestamp") + if not value.is_zero and not (_MIN_TIMESTAMP <= value.value <= _MAX_TIMESTAMP): raise ValueError("TYPE_CONTRACT: TIMESTAMP is outside the SQL range") + if not value.is_zero: _check_microsecond_scale(value.value.microsecond, descriptor) + if not value.is_zero and value.value.tzinfo is not _datetime.timezone.utc: + return SqlTimestamp(False, value.value.astimezone(_datetime.timezone.utc)) + return value + if type_id in (VECF32, VECF64): + if not isinstance(value, memoryview) or not value.readonly: + raise ValueError("TYPE_CONTRACT: vector scalar result must be a read-only memoryview") + width = int(descriptor.get("width") or 0) + fmt = "f" if type_id == VECF32 else "d" + try: + values = list(value.cast(fmt)) + except (TypeError, ValueError) as exc: + raise ValueError("TYPE_CONTRACT: invalid vector memoryview") from exc + if len(values) != width: + raise ValueError("TYPE_CONTRACT: vector dimension mismatch") + return values + if type_id in (DECIMAL64, DECIMAL128): + if not isinstance(value, _decimal.Decimal): raise ValueError("TYPE_CONTRACT: expected decimal.Decimal") + if not value.is_finite(): raise ValueError("TYPE_CONTRACT: decimal must be finite") + scale = int(descriptor.get("scale") or 0) + exponent = value.as_tuple().exponent + if not isinstance(exponent, int) or -exponent != scale: raise ValueError("TYPE_CONTRACT: decimal scale mismatch") + precision = int(descriptor.get("width") or (18 if type_id == DECIMAL64 else 38)) + if len(value.as_tuple().digits) > precision: raise ValueError("TYPE_CONTRACT: decimal precision exceeded") + return value + + +def _temporal_array(values: list, descriptor: Dict[str, Any]) -> pa.Array: + type_id = int(descriptor["type_id"]) + valid = [] + zeroes = [] + child_values = [] + for value in values: + if value is None: + valid.append(False); zeroes.append(False); child_values.append(0); continue + value = _check_scalar(value, descriptor) + valid.append(True); zeroes.append(bool(value.is_zero)); child_values.append(0 if value.is_zero else value.value) + if type_id == DATE: child_type = pa.date32() + elif type_id == DATETIME: child_type = pa.timestamp("us") + else: child_type = pa.timestamp("us", tz="UTC") + children = [pa.array(zeroes, type=pa.bool_()), pa.array(child_values, type=child_type)] + return pa.StructArray.from_arrays(children, names=["is_zero", "value"], mask=pa.array([not item for item in valid])) + + +def _output_array(values: Any, descriptor: Dict[str, Any], rows: int) -> pa.Array: + # Keep this helper safe when called directly by a runtime adapter or a + # conformance harness. The normal exchange path validates the Open payload + # first, but _arrow_type alone can construct a physical type for an + # invalid semantic descriptor (for example DECIMAL64 precision 19). + _canonical_descriptor(descriptor) + if isinstance(values, pa.ChunkedArray): + values = values.combine_chunks() + if isinstance(values, pa.Array): + if len(values) != rows: raise ValueError("TYPE_CONTRACT: result length does not match input rows") + if values.type != _arrow_type(descriptor): raise ValueError("TYPE_CONTRACT: result Arrow type does not match the return descriptor") + _validate_array_values(values, descriptor) + return values + if not isinstance(values, (list, tuple)): + raise ValueError("TYPE_CONTRACT: VECTOR handler must return an Arrow Array or ChunkedArray") + if len(values) != rows: raise ValueError("TYPE_CONTRACT: result length does not match input rows") + type_id = int(descriptor["type_id"]) + if type_id in (DATE, DATETIME, TIMESTAMP): return _temporal_array(list(values), descriptor) + if type_id in (VECF32, VECF64): + width = int(descriptor.get("width") or 0) + checked = [] + for value in values: + if value is None: + checked.append(None) + continue + checked.append(_check_scalar(value, descriptor)) + try: + child_type = pa.float32() if type_id == VECF32 else pa.float64() + # A NULL parent still owns exactly `width` child slots in a + # FixedSizeListArray. Leaving those slots out changes the row + # layout and makes the following non-NULL rows shift left. + flat = [item for row in checked for item in (row if row is not None else [0] * width)] + child = pa.array(flat, type=child_type) + mask = pa.array([row is None for row in checked]) + return pa.FixedSizeListArray.from_arrays(child, width, mask=mask) + except (TypeError, ValueError, pa.ArrowException) as exc: + raise ValueError("TYPE_CONTRACT: vector result is outside the declared SQL domain") from exc + checked = [_check_scalar(value, descriptor) for value in values] + if type_id == UUID: checked = [None if value is None else value.bytes for value in checked] + try: return pa.array(checked, type=_arrow_type(descriptor)) + except (TypeError, ValueError, pa.ArrowException) as exc: raise ValueError("TYPE_CONTRACT: result value is outside the declared SQL domain") from exc + + +def _validate_array_values(array: pa.Array, descriptor: Dict[str, Any]) -> None: + type_id = int(descriptor["type_id"]) + if type_id in (DATE, DATETIME, TIMESTAMP): + struct = array + for index in range(len(struct)): + if not struct[index].is_valid: continue + is_zero_scalar = struct.field("is_zero")[index] + value_scalar = struct.field("value")[index] + if not is_zero_scalar.is_valid: + raise ValueError("TYPE_CONTRACT: temporal zero flag is null") + if not value_scalar.is_valid: + raise ValueError("TYPE_CONTRACT: temporal child is null") + is_zero = bool(is_zero_scalar.as_py()) + value = value_scalar.as_py() + if is_zero and ((type_id == DATE and value != _datetime.date(1970, 1, 1)) or (type_id == DATETIME and value != _datetime.datetime(1970, 1, 1)) or (type_id == TIMESTAMP and value != _datetime.datetime(1970, 1, 1, tzinfo=_datetime.timezone.utc))): + raise ValueError("TYPE_CONTRACT: temporal zero placeholder is invalid") + if not is_zero: + if type_id == DATE: _check_scalar(SqlDate(False, value), descriptor) + elif type_id == DATETIME: _check_scalar(SqlDatetime(False, value), descriptor) + else: _check_scalar(SqlTimestamp(False, value), descriptor) + elif type_id in (VECF32, VECF64): + # A FixedSizeListArray may have both null parents and a non-zero row + # offset. Its backing child array can therefore contain nulls that + # are either hidden behind a null parent or outside the visible slice. + # Only the children belonging to visible, non-null rows are part of + # the SQL value domain. + for row in range(len(array)): + value = array[row] + if not value.is_valid: + continue + for child in value.values: + if not child.is_valid: + raise ValueError("TYPE_CONTRACT: vector child validity must be non-null") + elif type_id in (CHAR, VARCHAR, TEXT, JSON, BINARY, VARBINARY, BLOB, UUID, TIME, DECIMAL64, DECIMAL128): + for index in range(len(array)): + if not array[index].is_valid: continue + value = array[index].as_py() + if type_id == UUID: + if not isinstance(value, (bytes, bytearray)) or len(value) != 16: raise ValueError("TYPE_CONTRACT: UUID must contain 16 bytes") + else: + _check_scalar(value, descriptor) + + +class _DiscardText: + def write(self, value: str) -> int: + return len(value) + + def flush(self) -> None: + return None + + +def _serialize_record_batch(record: pa.RecordBatch) -> bytes: + sink = pa.BufferOutputStream() + with pa.ipc.new_stream(sink, record.schema) as stream: + stream.write_batch(record) + return sink.getvalue().to_pybytes() + + +def _serialize_record_batch_message(record: pa.RecordBatch) -> memoryview: + """Serialize one Arrow record-batch message without repeating its schema.""" + try: + # Keep the Arrow-owned buffer alive through the returned memoryview so + # the parent can hand it directly to protocol 5's out-of-band buffer + # without first copying it into a Python bytes object. + return memoryview(record.serialize()) + except (pa.ArrowException, OSError, ValueError, TypeError) as exc: + raise ValueError("PROTOCOL: cannot serialize Arrow record batch") from exc + + +def _deserialize_record_batch(data: bytes) -> pa.RecordBatch: + if isinstance(data, pickle.PickleBuffer): + data = data.raw() + if not isinstance(data, (bytes, bytearray, memoryview)) or not data: + raise ValueError("PROTOCOL: execution payload is missing an Arrow batch") + try: + reader = pa.ipc.open_stream(pa.py_buffer(data)) + except pa.ArrowException as exc: + raise ValueError("PROTOCOL: execution payload is not a valid Arrow stream") from exc + try: + try: + record = reader.read_next_batch() + except StopIteration as exc: + raise ValueError("PROTOCOL: execution payload contains no Arrow batch") from exc + try: + reader.read_next_batch() + except StopIteration: + return record + raise ValueError("PROTOCOL: execution payload contains multiple Arrow batches") + finally: + reader.close() + + +def _deserialize_record_batch_message(data: Any, schema: pa.Schema) -> pa.RecordBatch: + """Decode one schema-free Arrow IPC record-batch message. + + The schema is derived from the already validated routine descriptor. This + is an internal handler IPC format, not a replacement for the Flight + schema, which remains validated independently at the worker boundary. + """ + if isinstance(data, pickle.PickleBuffer): + data = data.raw() + if not isinstance(data, (bytes, bytearray, memoryview)) or not data: + raise ValueError("PROTOCOL: execution payload is missing an Arrow batch") + if not isinstance(schema, pa.Schema): + raise ValueError("PROTOCOL: execution payload schema is invalid") + try: + reader = pa.BufferReader(pa.py_buffer(data)) + record = pa.ipc.read_record_batch(reader, schema) + if reader.tell() != reader.size(): + raise ValueError("trailing bytes after Arrow record batch") + return record + except (pa.ArrowException, OSError, ValueError, TypeError) as exc: + raise ValueError("PROTOCOL: execution payload is not a valid Arrow record batch") from exc + + +def _execute_handler_batch( + request: Dict[str, Any], + *, + handler=None, + statement_context: Optional[StatementContext] = None, + input_schema: Optional[pa.Schema] = None, + result_schema: Optional[pa.Schema] = None, +) -> bytes: + args = request["args"] + result_descriptor = request["return"] + arrow_encoding = request.get("arrow_encoding", HANDLER_ARROW_STREAM) + if arrow_encoding == HANDLER_ARROW_RECORD_BATCH: + if input_schema is None: + input_schema = _schema_from_descriptors(args, "arg") + batch = _deserialize_record_batch_message( + request["input"], input_schema + ) + elif arrow_encoding == HANDLER_ARROW_STREAM: + batch = _deserialize_record_batch(request["input"]) + else: + raise ValueError("PROTOCOL: unsupported handler Arrow encoding") + mode = request["mode"] + null_policy = request["null_policy"] + sdk_version = request["sdk_version"] + if statement_context is None: + statement_context = _statement_context(request.get("context")) + + # User code has no stdout/stderr channel in the Flight protocol. Discard + # it so a print() cannot corrupt the length-prefixed response frame. + with contextlib.redirect_stdout(_DiscardText()), contextlib.redirect_stderr(_DiscardText()): + if handler is None: + handler = _load_handler(request["source"], request["handler"]) + if mode == MODE_VECTOR: + call_context = VectorContext(sdk_version, _CallLogger(), statement_context, batch.num_rows) + output = handler(call_context, *[batch.column(index) for index in range(batch.num_columns)]) + if not isinstance(output, (pa.Array, pa.ChunkedArray)): + raise ValueError("TYPE_CONTRACT: VECTOR handler must return an Arrow Array or ChunkedArray") + else: + call_context = ScalarContext(sdk_version, _CallLogger(), statement_context) + values = [] + if batch.num_rows < SCALAR_MATERIALIZATION_MIN_ROWS: + for row in range(batch.num_rows): + params = [ + _scalar_input(batch.column(index), row, args[index]) + for index in range(batch.num_columns) + ] + if null_policy == NULL_RETURN and any(value is None for value in params): + values.append(None) + else: + values.append(handler(call_context, *params)) + else: + columns = [batch.column(index) for index in range(batch.num_columns)] + scalar_columns = [ + _scalar_column_values(column) for column in columns + ] + if not any(column_values is not None for column_values in scalar_columns): + for row in range(batch.num_rows): + params = [ + _scalar_input(columns[index], row, args[index]) + for index in range(batch.num_columns) + ] + if null_policy == NULL_RETURN and any(value is None for value in params): + values.append(None) + else: + values.append(handler(call_context, *params)) + else: + for row in range(batch.num_rows): + params = [ + _scalar_input_value( + column_values[row] + if column_values is not None + else columns[index][row].as_py(), + args[index], + ) + for index, column_values in enumerate(scalar_columns) + ] + if null_policy == NULL_RETURN and any(value is None for value in params): + values.append(None) + else: + values.append(handler(call_context, *params)) + output = values + output_array = _output_array(output, result_descriptor, batch.num_rows) + if result_schema is None: + result_schema = pa.schema([_field("result", result_descriptor)]) + result_batch = pa.RecordBatch.from_arrays( + [output_array], schema=result_schema + ) + if pa.ipc.get_record_batch_size(result_batch) > request["max_batch_bytes"]: + raise ValueError("RESOURCE_EXHAUSTED: output batch exceeds byte limit") + if arrow_encoding == HANDLER_ARROW_RECORD_BATCH: + return _serialize_record_batch_message(result_batch) + return _serialize_record_batch(result_batch) + + +def _read_exact(stream, size: int) -> bytearray: + if size < 0: + raise ValueError("execution frame read size is negative") + result = bytearray(size) + readinto = getattr(stream, "readinto", None) + if callable(readinto): + view = memoryview(result) + offset = 0 + try: + while offset < size: + count = readinto(view[offset:]) + if not isinstance(count, int) or count <= 0: + raise EOFError("execution frame ended unexpectedly") + offset += count + finally: + view.release() + return result + + # Keep compatibility with the small stream doubles used by the contract + # tests and with file-like readers that expose only read(). + offset = 0 + while offset < size: + chunk = stream.read(size - offset) + if not chunk: + raise EOFError("execution frame ended unexpectedly") + result[offset : offset + len(chunk)] = chunk + offset += len(chunk) + return result + + +def _write_all(stream, data) -> None: + """Write one frame component completely to a byte stream. + + The handler response channel is a pipe-backed ``FileIO`` object. A + blocking write normally transfers all bytes, but the file API still + permits a short write (for example when a signal interrupts a large + transfer). Treating that count as success would publish a truncated + length-prefixed frame and desynchronize every later response. + """ + view = memoryview(data) + try: + offset = 0 + while offset < len(view): + written = stream.write(view[offset:]) + if not isinstance(written, int) or written <= 0 or written > len(view) - offset: + raise OSError("execution frame stream made no valid progress") + offset += written + finally: + view.release() + + +def _write_execution_frame_parts(stream, parts: Iterable[bytes]) -> None: + parts = tuple(parts) + payload_size = sum(len(part) for part in parts) + if payload_size > MAX_EXECUTION_FRAME_BYTES: + raise ValueError("RESOURCE_EXHAUSTED: execution frame is too large") + _write_all(stream, struct.pack(">Q", payload_size)) + for part in parts: + _write_all(stream, part) + stream.flush() + + +def _write_execution_frame(stream, payload: bytes) -> None: + _write_execution_frame_parts(stream, (payload,)) + + +def _encode_execution_request(request: Dict[str, Any], *, compact: bool = False): + """Build a handler frame without copying Arrow bytes into pickle. + + The outer length bounds the complete frame. The first eight bytes of the + payload bound the pickle metadata, and protocol 5 carries exactly one + out-of-band Arrow buffer. Returning write parts lets the nonblocking + sender avoid concatenating another full request-sized byte string. + """ + if not isinstance(request, dict) or "input" not in request: + raise ValueError("PROTOCOL: execution request is missing an Arrow batch") + input_wire = request["input"] + if isinstance(input_wire, pickle.PickleBuffer): + input_wire = input_wire.raw() + if not isinstance(input_wire, (bytes, bytearray, memoryview)): + raise ValueError("PROTOCOL: execution request Arrow batch is not bytes-like") + if not input_wire: + raise ValueError("PROTOCOL: execution request Arrow batch is empty") + if compact: + metadata = {_HANDLER_REQUEST_KIND_KEY: _HANDLER_REQUEST_BATCH} + else: + metadata = dict(request) + metadata[_HANDLER_REQUEST_KIND_KEY] = _HANDLER_REQUEST_FULL + buffers = [] + try: + metadata["input"] = pickle.PickleBuffer(input_wire) + metadata_wire = pickle.dumps( + metadata, protocol=5, buffer_callback=buffers.append + ) + if len(buffers) != 1: + raise ValueError("PROTOCOL: execution request must contain one Arrow buffer") + arrow_wire = buffers[0].raw() + except (BufferError, pickle.PickleError, TypeError, ValueError) as exc: + raise ValueError("PROTOCOL: cannot encode execution request") from exc + payload_size = 8 + len(metadata_wire) + len(arrow_wire) + if payload_size > MAX_EXECUTION_FRAME_BYTES: + raise ValueError("RESOURCE_EXHAUSTED: execution request is too large") + parts = ( + struct.pack(">Q", payload_size), + struct.pack(">Q", len(metadata_wire)), + metadata_wire, + arrow_wire, + ) + return parts, payload_size + + +def _read_execution_request(stream) -> Optional[Dict[str, Any]]: + """Read and validate one metadata plus out-of-band Arrow frame.""" + # A pipe is a byte stream: one read is allowed to return a prefix even + # when the sender has already written the complete frame. Read one byte + # first so only an empty read means clean burst EOF, then complete the + # fixed-width header through the same exact-read path as the body. + first = stream.read(1) + if not first: + return None + if len(first) != 1: + raise EOFError("execution request header ended unexpectedly") + header = bytearray(8) + header[0] = first[0] + header[1:] = _read_exact(stream, 7) + payload_size = struct.unpack(">Q", header)[0] + if payload_size > MAX_EXECUTION_FRAME_BYTES or payload_size < 8: + raise ValueError("RESOURCE_EXHAUSTED: execution request is too large") + metadata_size = struct.unpack(">Q", _read_exact(stream, 8))[0] + if metadata_size > payload_size - 8: + raise ValueError("PROTOCOL: execution request metadata is too large") + metadata_wire = _read_exact(stream, metadata_size) + arrow_size = payload_size - 8 - metadata_size + if arrow_size <= 0: + raise ValueError("PROTOCOL: execution request Arrow batch is empty") + arrow_wire = _read_exact(stream, arrow_size) + try: + request = pickle.loads( + metadata_wire, + # A readonly memoryview preserves the protocol-5 PickleBuffer + # type when the exact-read backing is a bytearray, while keeping + # the Arrow payload zero-copy and preventing handler code from + # mutating the receive buffer through the request object. + buffers=[pickle.PickleBuffer(memoryview(arrow_wire).toreadonly())], + ) + except (EOFError, pickle.PickleError, TypeError, ValueError) as exc: + raise ValueError("PROTOCOL: execution request metadata is invalid") from exc + if not isinstance(request, dict) or not isinstance( + request.get("input"), pickle.PickleBuffer + ): + raise ValueError("PROTOCOL: execution request does not contain one Arrow buffer") + return request + + +def _watch_parent_liveness(read_fd: int) -> None: + """Terminate the whole handler group when the worker disappears. + + The worker cannot run its normal cleanup after SIGKILL/OOM. A pipe whose + write end is owned by the worker gives the handler a kernel-owned death + notification, including the race where the worker exits before the + handler has finished starting. This is a reliability owner for ordinary + handler processes; it is deliberately not described as a security + sandbox, because unisolated user code can inspect or interfere with its + own process. + """ + try: + while True: + if os.read(read_fd, 1) == b"": + if os.name == "posix": + try: + os.killpg(os.getpgrp(), signal.SIGKILL) + except ProcessLookupError: + pass + os._exit(137) + except (OSError, ValueError): + # A broken watch descriptor is also a lost parent notification. The + # handler must terminate its whole process group before leaving; an + # ordinary thread exit would leave descendants alive after the worker + # has already lost ownership of them. + if os.name == "posix": + try: + os.killpg(os.getpgrp(), signal.SIGKILL) + except ProcessLookupError: + pass + os._exit(137) + + +def _execute_handler_subprocess() -> None: + response_fd_text = os.environ.pop(_HANDLER_RESPONSE_FD_ENV, None) + parent_watch_fd_text = os.environ.pop(_HANDLER_PARENT_WATCH_FD_ENV, None) + if response_fd_text is None or parent_watch_fd_text is None: + raise ValueError("PROTOCOL: handler response channel is missing") + try: + response_fd = int(response_fd_text) + parent_watch_fd = int(parent_watch_fd_text) + response_stream = os.fdopen(response_fd, "wb", buffering=0, closefd=True) + threading.Thread( + target=_watch_parent_liveness, + args=(parent_watch_fd,), + name="matrixone-udf-parent-watch", + daemon=True, + ).start() + except (OSError, TypeError, ValueError) as exc: + raise ValueError("PROTOCOL: handler response channel is invalid") from exc + try: + # A child is reused only within one bounded invocation burst. The + # source is compiled once and every later request must carry the same + # frozen contract; input Arrow batches remain independently validated + # by the parent and by _execute_handler_batch. + frozen = None + frozen_request = None + handler = None + statement_context = None + input_schema = None + result_schema = None + while True: + try: + request = _read_execution_request(sys.stdin.buffer) + if request is None: + # EOF before a new frame is the normal burst shutdown. + break + request_kind = request.get(_HANDLER_REQUEST_KIND_KEY) + if request_kind not in ( + _HANDLER_REQUEST_FULL, + _HANDLER_REQUEST_BATCH, + ): + raise ValueError("PROTOCOL: handler request kind is invalid") + if request_kind == _HANDLER_REQUEST_BATCH: + if frozen is None or frozen_request is None: + raise ValueError( + "PROTOCOL: compact handler request arrived before the full contract" + ) + batch_input = request.get("input") + request = dict(frozen_request) + request["input"] = batch_input + contract = { + key: request.get(key) + for key in ( + "source", "handler", "mode", "null_policy", "abi_contract", + "adapter_version", "sdk_version", "definition_schema_version", + "artifact_digest", "environment_digest", "definition_fingerprint", + "context", "args", "return", "max_batch_bytes", "max_batch_rows", + "max_invocation_rows", "max_invocation_result_bytes", "arrow_encoding", + ) + } + if frozen is None: + frozen = contract + # Do not retain the first Arrow batch while the child is + # reused. The immutable contract is enough to reconstruct + # later compact requests. + frozen_request = { + key: value for key, value in request.items() if key != "input" + } + statement_context = _statement_context(request.get("context")) + handler = _load_handler(request["source"], request["handler"]) + if request.get("arrow_encoding") == HANDLER_ARROW_RECORD_BATCH: + input_schema = _schema_from_descriptors(request["args"], "arg") + result_schema = pa.schema([_field("result", request["return"])]) + elif contract != frozen: + raise ValueError("PROTOCOL: handler burst contract changed") + output = _execute_handler_batch( + request, + handler=handler, + statement_context=statement_context, + input_schema=input_schema, + result_schema=result_schema, + ) + response_parts = (bytes([_HANDLER_RESPONSE_OK]), output) + succeeded = True + except Exception as exc: + response_parts = ( + bytes([_HANDLER_RESPONSE_ERROR]), + _safe_error(exc).encode("utf-8"), + ) + succeeded = False + # This descriptor is created by the adapter and is distinct from + # process stdout/stderr descriptors available to handler code. + _write_execution_frame_parts(response_stream, response_parts) + if not succeeded: + break + finally: + response_stream.close() + + +def _context_is_cancelled(context) -> bool: + if context is None: + return False + try: + return bool(context.is_cancelled()) + except Exception: + return False + + +class _ExchangeContext: + """Combine the Flight cancellation state with server shutdown intent.""" + + __slots__ = ("_context", "_shutdown") + + def __init__(self, context, shutdown: threading.Event): + self._context = context + self._shutdown = shutdown + + def is_cancelled(self) -> bool: + return self._shutdown.is_set() or _context_is_cancelled(self._context) + + +class _ExchangeInputReader: + """Read Flight input without letting native reader ownership escape. + + The reader passed to a Flight server callback is a PyArrow C++ object whose + lifetime is owned by the RPC. It must be read by the callback thread: a + daemon thread that is still inside ``read_chunk`` when + ``FlightServerBase.shutdown`` destroys the RPC can dereference a freed + native reader and crash the worker. The Flight implementation itself + interrupts a direct ``read_chunk`` when the RPC is cancelled. A + ``FlightServerBase.shutdown`` waits for an open input RPC; it is not a + cancellation mechanism, so the owner must cancel the client exchange (or + terminate the worker process) before waiting for server shutdown. + + Some contract tests and non-native adapters expose an explicit + ``cancel``/``close`` operation but do not have Flight's RPC cancellation + semantics. Keep the bounded polling thread only for those cooperative + readers. Never use it for a reader from PyArrow's native Flight module. + """ + + _POLL_SECONDS = 0.05 + + def __init__(self, reader): + self._reader = reader + self._stop = threading.Event() + self._items = queue.Queue(maxsize=1) + self._thread = None + self._native_cancel = self._find_cancel(reader) + if not self._is_native_flight_reader(reader) and self._native_cancel is not None: + self._thread = threading.Thread( + target=self._read_loop, + name="matrixone-udf-flight-reader", + daemon=True, + ) + self._thread.start() + + @staticmethod + def _is_native_flight_reader(reader): + # PyArrow exposes the server-side reader as a private extension type + # (currently MetadataRecordBatchReader). The module check is kept at + # this narrow boundary so the execution path does not depend on a + # particular private class name across supported PyArrow releases. + return type(reader).__module__.startswith("pyarrow._flight") + + @staticmethod + def _find_cancel(reader): + cancel = getattr(reader, "cancel", None) + if callable(cancel): + return cancel + close = getattr(reader, "close", None) + return close if callable(close) else None + + def _publish(self, kind, value=None): + item = (kind, value) + while not self._stop.is_set(): + try: + self._items.put(item, timeout=self._POLL_SECONDS) + return True + except queue.Full: + continue + return False + + def _read_loop(self): + try: + while not self._stop.is_set(): + try: + chunk = self._reader.read_chunk() + except StopIteration: + self._publish("eof") + return + self._publish("chunk", chunk) + except Exception as exc: + self._publish("error", exc) + + def _cancel_native_reader(self): + if self._native_cancel is not None: + try: + self._native_cancel() + except Exception: + # The RPC may already be tearing down. The join below still + # verifies whether a cooperative reader actually returned. + pass + + def next(self, context): + if self._thread is None: + if _context_is_cancelled(context): + self.cancel() + raise TimeoutError("DEADLINE_EXCEEDED: input stream cancelled") + try: + chunk = self._reader.read_chunk() + except StopIteration: + if _context_is_cancelled(context): + raise TimeoutError("DEADLINE_EXCEEDED: input stream cancelled") + raise + if _context_is_cancelled(context): + self.cancel() + raise TimeoutError("DEADLINE_EXCEEDED: input stream cancelled") + return chunk + while True: + if _context_is_cancelled(context): + self.cancel() + raise TimeoutError("DEADLINE_EXCEEDED: input stream cancelled") + try: + kind, value = self._items.get(timeout=self._POLL_SECONDS) + except queue.Empty: + continue + if kind == "chunk": + return value + if kind == "eof": + raise StopIteration + raise value + + def cancel(self): + self._stop.set() + self._cancel_native_reader() + + def close(self): + self.cancel() + if self._thread is None: + return + self._thread.join(timeout=1.0) + if self._thread.is_alive(): + raise ValueError( + "RESOURCE_EXHAUSTED: Flight input reader did not stop after cancellation" + ) +def _kill_execution_process(process: subprocess.Popen) -> None: + # Check the process group before reaping the leader. A handler can exit + # while a descendant keeps the group alive; polling first would reap the + # leader and skip killpg, leaving that descendant behind until the + # asynchronous watchdog happens to run. Before process.poll() reaps the + # leader, its PID is still owned by this session and the group identity + # cannot have been reused. + if os.name == "posix": + group_alive = _execution_group_alive(process) + leader_alive = process.poll() is None + if group_alive: + try: + os.killpg(process.pid, signal.SIGKILL) + except ProcessLookupError: + pass + except PermissionError: + # A process-group kill can be denied during a platform or + # teardown race even though the worker still owns the leader. + # Kill the Popen child directly so the handler slot is not + # stranded; the parent-liveness watchdog remains responsible + # for descendants when the group cannot be addressed here. + if leader_alive: + try: + process.kill() + except ProcessLookupError: + pass + else: + raise + elif leader_alive: + # The group disappeared in the small race between the liveness + # probe and poll(); still make sure the owned leader is stopped. + process.kill() + elif process.poll() is None: + process.kill() + try: + process.wait(timeout=1.0) + except subprocess.TimeoutExpired: + process.kill() + try: + process.wait(timeout=1.0) + except subprocess.TimeoutExpired as exc: + # The caller retains the handler session, H slot, and invocation + # ledger in the bounded pending-cleanup owner. Do not let an + # unbounded reap wait turn a cancellation path into a worker-wide + # hang; the process group has already received SIGKILL and the + # failure is surfaced to the owner. + raise TimeoutError( + "DEADLINE_EXCEEDED: handler process did not exit after SIGKILL" + ) from exc + + +def _execution_group_alive(process: subprocess.Popen) -> bool: + if os.name != "posix": + return process.poll() is None + try: + os.killpg(process.pid, 0) + except ProcessLookupError: + return False + except PermissionError: + return True + return True + + +DEFAULT_BURST_BATCHES = 64 +DEFAULT_BURST_BYTES = 64 << 20 +DEFAULT_BURST_SECONDS = 30.0 +# A pending cleanup retains an admitted invocation, so it is bounded by the +# same ledger entry budget as active invocations. H is only the bound for +# child processes; empty/ALL-NULL invocations can still own a Flight reader +# without owning a handler child. +MAX_PENDING_CLEANUPS = MAX_LEDGER_ENTRIES +PENDING_HANDLER_CLEANUP_INITIAL_DELAY = 0.05 +PENDING_HANDLER_CLEANUP_MAX_DELAY = 1.0 + + +class _HandlerQuotaLease: + """Idempotent ownership token for one live handler child.""" + + def __init__(self, quota, account_id: int, owner_id: str): + self._quota = quota + self._account_id = account_id + self._owner_id = owner_id + self._released = False + self._lock = threading.Lock() + + def release(self) -> None: + with self._lock: + if self._released: + return + # Keep ownership until the quota counter has actually been + # decremented. Cleanup callers retry a failed release; marking + # this token first would turn a transient quota error into a + # permanent handler-budget leak because the retry would become a + # no-op. + self._quota._release(self._account_id, self._owner_id) + self._released = True + + +class _HandlerQuota: + """Non-blocking worker, account, and principal handler budgets. + + The owner key is scoped by account. Two tenants using the same username + therefore do not contend for one another's principal budget. Acquisition + is deliberately all-or-nothing and never waits while a caller owns an + input buffer or a process slot. + """ + + def __init__( + self, + max_account_handlers: int = MAX_ACCOUNT_HANDLER_PROCESSES, + max_owner_handlers: int = MAX_OWNER_HANDLER_PROCESSES, + ): + if ( + type(max_account_handlers) is not int + or max_account_handlers <= 0 + or max_account_handlers > MAX_HANDLER_PROCESSES + ): + raise ValueError("PROTOCOL: invalid account handler budget") + if ( + type(max_owner_handlers) is not int + or max_owner_handlers <= 0 + or max_owner_handlers > max_account_handlers + ): + raise ValueError("PROTOCOL: invalid owner handler budget") + self._max_account_handlers = max_account_handlers + self._max_owner_handlers = max_owner_handlers + self._lock = threading.Lock() + self._account_counts: Dict[int, int] = {} + self._owner_counts: Dict[tuple[int, str], int] = {} + + def acquire(self, account_id: int, owner_id: str) -> _HandlerQuotaLease: + if type(account_id) is not int or account_id < 0: + raise ValueError("PROTOCOL: invalid handler budget account") + if not isinstance(owner_id, str) or not owner_id: + raise ValueError("PROTOCOL: invalid handler budget owner") + owner_key = (account_id, owner_id) + with self._lock: + account_count = self._account_counts.get(account_id, 0) + if account_count >= self._max_account_handlers: + raise ValueError("RESOURCE_EXHAUSTED: account handler budget is full") + owner_count = self._owner_counts.get(owner_key, 0) + if owner_count >= self._max_owner_handlers: + raise ValueError("RESOURCE_EXHAUSTED: owner handler budget is full") + self._account_counts[account_id] = account_count + 1 + self._owner_counts[owner_key] = owner_count + 1 + return _HandlerQuotaLease(self, account_id, owner_id) + + def _release(self, account_id: int, owner_id: str) -> None: + owner_key = (account_id, owner_id) + with self._lock: + account_count = self._account_counts.get(account_id, 0) + owner_count = self._owner_counts.get(owner_key, 0) + if account_count <= 0 or owner_count <= 0: + raise RuntimeError("handler quota release without ownership") + if account_count == 1: + del self._account_counts[account_id] + else: + self._account_counts[account_id] = account_count - 1 + if owner_count == 1: + del self._owner_counts[owner_key] + else: + self._owner_counts[owner_key] = owner_count - 1 + + def counts(self) -> tuple[Dict[int, int], Dict[tuple[int, str], int]]: + """Return copies for deterministic tests and bounded diagnostics.""" + with self._lock: + return dict(self._account_counts), dict(self._owner_counts) + + +class _HandlerCleanupPending(Exception): + """Transfer a session whose cleanup failed, preserving the primary error. + + Callers must retain ``session`` until close succeeds. Exchanges hand it to + their bounded cleanup owner; standalone helper callers own the retry. + """ + + def __init__(self, error: BaseException, session): + super().__init__(str(error)) + self.error = error + self.session = session + + +class _HandlerProcessSession: + """One handler child reused only inside a bounded invocation burst.""" + + def __init__( + self, + execution_slots: Optional[threading.BoundedSemaphore] = None, + *, + handler_quota: Optional[_HandlerQuota] = None, + account_id: int = 0, + owner_id: str = "__anonymous__", + ): + self._slots = execution_slots or _DEFAULT_HANDLER_SLOTS + self._slot_acquired = False + self._quota_lease = None + self._process = None + self._watchdog_process = None + self._selector = None + self._response_read_fd = -1 + self._parent_watch_write_fd = -1 + self._response_buffer = bytearray() + self._closed = False + self._close_lock = threading.Lock() + self._burst_started = time.monotonic() + self._burst_batches = 0 + self._burst_bytes = 0 + try: + if handler_quota is not None: + self._quota_lease = handler_quota.acquire(account_id, owner_id) + if not self._slots.acquire(blocking=False): + raise ValueError("RESOURCE_EXHAUSTED: handler execution slots are full") + self._slot_acquired = True + response_read_fd, response_write_fd = os.pipe() + # Publish each acquired descriptor to its cleanup owner before + # the next allocation can fail (in particular under FD pressure). + self._response_read_fd = response_read_fd + parent_watch_read_fd, parent_watch_write_fd = os.pipe() + self._parent_watch_write_fd = parent_watch_write_fd + watchdog_read_fd = os.dup(parent_watch_read_fd) + popen_kwargs = { + "stdin": subprocess.PIPE, + # Handler output is diagnostic-only. It must never share the + # adapter response channel, even when user code writes directly + # to file descriptor 1. + "stdout": subprocess.DEVNULL, + "stderr": subprocess.DEVNULL, + "close_fds": True, + } + if os.name == "posix": + popen_kwargs["start_new_session"] = True + popen_kwargs["pass_fds"] = (response_write_fd, parent_watch_read_fd) + # User code runs under a separate execution identity. In + # particular, do not inherit CN, object-store, database, or tenant + # credentials from the worker process. This is process hygiene, + # not a sandbox boundary. + child_env = { + name: value + for name, value in os.environ.items() + if name in _HANDLER_ENV_ALLOWLIST + } + child_env[_HANDLER_RESPONSE_FD_ENV] = str(response_write_fd) + child_env[_HANDLER_PARENT_WATCH_FD_ENV] = str(parent_watch_read_fd) + popen_kwargs["env"] = child_env + self._process = subprocess.Popen( + [sys.executable, os.path.abspath(__file__), "--execute-handler"], + **popen_kwargs, + ) + os.close(response_write_fd) + response_write_fd = -1 + os.close(parent_watch_read_fd) + parent_watch_read_fd = -1 + if os.name == "posix": + watchdog_path = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "watchdog.py" + ) + watchdog_env = { + name: value + for name, value in os.environ.items() + if name in _HANDLER_ENV_ALLOWLIST + } + self._watchdog_process = subprocess.Popen( + [ + sys.executable, + # The watchdog is a standard-library-only helper; + # skipping site-package discovery trims its startup + # without changing the handler's Python environment. + "-S", + watchdog_path, + str(watchdog_read_fd), + str(self._process.pid), + ], + stdin=subprocess.DEVNULL, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + close_fds=True, + env=watchdog_env, + start_new_session=True, + pass_fds=(watchdog_read_fd,), + ) + os.close(watchdog_read_fd) + watchdog_read_fd = -1 + self._selector = selectors.DefaultSelector() + stdin_fd = self._process.stdin.fileno() + os.set_blocking(stdin_fd, False) + os.set_blocking(response_read_fd, False) + self._selector.register(response_read_fd, selectors.EVENT_READ, "response") + except Exception as error: + for fd in ( + locals().get("response_write_fd", -1), + locals().get("parent_watch_read_fd", -1), + locals().get("watchdog_read_fd", -1), + ): + if fd >= 0: + try: + os.close(fd) + except OSError: + pass + try: + self.close() + except Exception: + # __init__ never returns on this path, so the assignment in + # the caller cannot publish us. Transfer ownership explicitly. + raise _HandlerCleanupPending(error, self) from error + raise + + @property + def should_rollover(self) -> bool: + return ( + self._burst_batches >= DEFAULT_BURST_BATCHES + or self._burst_bytes >= DEFAULT_BURST_BYTES + or time.monotonic() - self._burst_started >= DEFAULT_BURST_SECONDS + ) + + def _take_response(self, max_payload_size: int = MAX_EXECUTION_FRAME_BYTES) -> Optional[tuple[int, bytes]]: + if len(self._response_buffer) < 8: + return None + expected = struct.unpack(">Q", self._response_buffer[:8])[0] + if expected > max_payload_size or expected > MAX_EXECUTION_FRAME_BYTES: + raise ValueError("RESOURCE_EXHAUSTED: execution response is too large") + if len(self._response_buffer) < expected + 8: + return None + if expected < 1: + raise ValueError("PROTOCOL: handler process returned an empty response") + status = self._response_buffer[8] + # A memoryview avoids an intermediate bytearray slice. Release it + # before resizing the receive buffer below; the returned Arrow bytes + # remain the only copy needed by the parent decoder. + response_view = memoryview(self._response_buffer) + try: + payload = bytes(response_view[9 : expected + 8]) + finally: + response_view.release() + del self._response_buffer[: expected + 8] + return status, payload + + def run(self, context, request: Dict[str, Any], timeout_seconds: float) -> bytes: + if self._closed or self._process is None or self._selector is None: + raise ValueError("PROTOCOL: handler session is closed") + # The handler budget is an absolute deadline for the whole request, + # including serialization and the non-blocking write. Starting the + # clock after pickle.dumps would let a large request consume an + # unbounded part of the caller's budget before the deadline was even + # installed. + deadline = time.monotonic() + timeout_seconds + request_parts, request_size = _encode_execution_request( + request, compact=self._burst_batches > 0 + ) + max_batch_bytes = request.get("max_batch_bytes") + if max_batch_bytes is None: + # Direct helper callers from older tests do not carry the full + # exchange contract. The real do_exchange path always supplies + # this field; retaining the global bound here keeps those helper + # calls diagnostic rather than silently weakening the real path. + response_payload_limit = MAX_EXECUTION_FRAME_BYTES + elif type(max_batch_bytes) is not int or max_batch_bytes <= 0: + raise ValueError("PROTOCOL: handler request has an invalid max_batch_bytes") + else: + # The response payload consists of one status byte followed by + # the schema-free Arrow message. The child checks the same + # max_batch_bytes before serializing, but the parent must bound + # its receive buffer independently in case a mismatched or + # malformed child writes an oversized frame. + response_payload_limit = min( + MAX_EXECUTION_FRAME_BYTES, max_batch_bytes + 1 + ) + + def check_budget() -> None: + if _context_is_cancelled(context): + raise TimeoutError("DEADLINE_EXCEEDED: handler execution cancelled") + if time.monotonic() >= deadline: + raise TimeoutError("DEADLINE_EXCEEDED: handler execution timeout") + + check_budget() + request_part_index = 0 + request_part_offset = 0 + stdin_fd = self._process.stdin.fileno() + self._selector.register(stdin_fd, selectors.EVENT_WRITE, "request") + try: + while True: + check_budget() + remaining = deadline - time.monotonic() + if remaining <= 0: + raise TimeoutError("DEADLINE_EXCEEDED: handler execution timeout") + response = self._take_response(response_payload_limit) + if response is not None: + break + events = self._selector.select(min(remaining, 0.1)) + for event, _ in events: + if event.data == "request": + try: + while request_part_index < len(request_parts): + # A single writable notification can drain many + # small frame parts. Re-check the caller budget + # inside that loop so serialization/write work + # cannot outrun cancellation or the deadline. + check_budget() + part = request_parts[request_part_index] + if request_part_offset == len(part): + request_part_index += 1 + request_part_offset = 0 + continue + written = os.write(stdin_fd, part[request_part_offset:]) + if written <= 0: + raise BrokenPipeError("handler request channel made no progress") + request_part_offset += written + check_budget() + if request_part_offset < len(part): + break + except BlockingIOError: + continue + except BrokenPipeError as exc: + raise ValueError( + "USER_CODE: handler process closed its request channel" + ) from exc + if request_part_index == len(request_parts): + self._selector.unregister(stdin_fd) + else: + try: + chunk = os.read(self._response_read_fd, 65536) + except BlockingIOError: + continue + if not chunk: + raise ValueError("USER_CODE: handler process exited without a response") + if len(self._response_buffer) + len(chunk) > response_payload_limit + 8: + raise ValueError("RESOURCE_EXHAUSTED: execution response exceeds batch byte limit") + self._response_buffer.extend(chunk) + if self._process.poll() is not None: + if self._process.returncode != 0: + raise ValueError("USER_CODE: handler process exited abnormally") + if _execution_group_alive(self._process): + raise ValueError("USER_CODE: handler process left descendant processes") + raise ValueError("USER_CODE: handler process exited before the burst completed") + status, output = response + if status == _HANDLER_RESPONSE_ERROR: + try: + message = output.decode("utf-8") + except UnicodeDecodeError as exc: + raise ValueError("PROTOCOL: handler process returned an invalid error") from exc + raise ValueError(message or "USER_CODE: handler process failed") + if status != _HANDLER_RESPONSE_OK: + raise ValueError("PROTOCOL: handler process returned an unknown status") + self._burst_batches += 1 + self._burst_bytes += request_size + len(output) + 1 + return output + finally: + # A failed write/read must not leave a stale registration that a + # later close or diagnostic path mistakes for active work. + try: + self._selector.unregister(stdin_fd) + except (KeyError, ValueError): + pass + + def close(self) -> None: + # Mark the session closed before taking the lock so no new batch can + # enter while another terminal path is retrying cleanup. Ownership + # fields are cleared only after their operation succeeds; otherwise a + # transient kill/close error would make a later cleanup call unable to + # find the resource it still owns. + self._closed = True + with self._close_lock: + close_error = None + + def attempt(operation, commit) -> None: + nonlocal close_error + operation_error = None + # Process reaping can race a child exiting and descriptor + # close can transiently fail during RPC teardown. A bounded + # second attempt makes cleanup retryable without turning + # cancellation into an unbounded wait. + for _ in range(2): + try: + operation() + commit() + return + except Exception as exc: + operation_error = exc + if close_error is None: + close_error = operation_error + + if self._selector is not None: + selector = self._selector + attempt(selector.close, lambda: setattr(self, "_selector", None)) + if self._parent_watch_write_fd >= 0: + parent_watch_write_fd = self._parent_watch_write_fd + + def close_parent_watch() -> None: + os.close(parent_watch_write_fd) + + attempt( + close_parent_watch, + lambda: setattr(self, "_parent_watch_write_fd", -1), + ) + if self._process is not None: + process = self._process + + def close_process() -> None: + _kill_execution_process(process) + if process.stdin is not None: + process.stdin.close() + + attempt(close_process, lambda: setattr(self, "_process", None)) + if self._watchdog_process is not None: + watchdog_process = self._watchdog_process + + def wait_for_watchdog() -> None: + try: + watchdog_process.wait(timeout=0.1) + except subprocess.TimeoutExpired: + try: + watchdog_process.kill() + except ProcessLookupError: + pass + watchdog_process.wait(timeout=1.0) + + attempt( + wait_for_watchdog, + lambda: setattr(self, "_watchdog_process", None), + ) + if self._response_read_fd >= 0: + response_read_fd = self._response_read_fd + + def close_response_read() -> None: + os.close(response_read_fd) + + attempt( + close_response_read, + lambda: setattr(self, "_response_read_fd", -1), + ) + # H and the account/owner quota describe a live handler child. A + # failed kill must therefore keep both leases held while this + # session is owned by the pending-cleanup reaper. Releasing them + # merely because the close attempt returned an error would let a + # later invocation exceed the real process budget. The fields are + # cleared only after every process/IPC owner has been cleared. + resources_closed = ( + self._selector is None + and self._process is None + and self._watchdog_process is None + and self._response_read_fd < 0 + and self._parent_watch_write_fd < 0 + ) + if resources_closed and self._slot_acquired: + attempt(self._slots.release, lambda: setattr(self, "_slot_acquired", False)) + quota_lease = getattr(self, "_quota_lease", None) + if resources_closed and quota_lease is not None: + attempt(quota_lease.release, lambda: setattr(self, "_quota_lease", None)) + if close_error is not None: + raise close_error + + +# Keep stable class identities for cleanup ownership checks. Contract tests +# replace the module constructors to inject failures; using the mutable module +# attributes in isinstance() would then turn a valid cleanup path into a +# TypeError and could mask the original exchange outcome. +_EXCHANGE_INPUT_READER_TYPE = _ExchangeInputReader +_HANDLER_PROCESS_SESSION_TYPE = _HandlerProcessSession + + +@dataclass +class _PendingInvocationCleanup: + input_reader: Optional[_ExchangeInputReader] + handler_session: Optional[_HandlerProcessSession] + key: tuple + state: _InvocationState + next_attempt: float + failures: int = 0 + + +def _run_handler_process( + context, request: Dict[str, Any], timeout_seconds: float, + execution_slots: Optional[threading.BoundedSemaphore] = None, +) -> bytes: + # Construction failures already transfer their pending session in + # _HandlerCleanupPending. This standalone helper has no server reaper; + # its caller must retain that exception and retry session.close(). + session = _HandlerProcessSession(execution_slots) + try: + result = session.run(context, request, timeout_seconds) + except BaseException as error: + # Preserve the handler/transport failure as the primary diagnosis. + # Cleanup is still mandatory, but a close failure must not replace a + # deadline, user-code, or protocol error and hide the actual cause. + try: + session.close() + except Exception: + raise _HandlerCleanupPending(error, session) from error + raise + else: + try: + session.close() + except Exception as error: + raise _HandlerCleanupPending(error, session) from error + return result + + + +class _InvocationState: + def __init__(self, tuple_value: Dict[str, Any], terminal_bytes: int): + self.tuple = tuple_value + self.terminal_bytes = terminal_bytes + self.condition = threading.Condition() + self.last_input = 0 + self.last_result = 0 + self.acked_result = 0 + self.finish_id: Optional[str] = None + self.finish_acked = False + self.finish_sent = False + self.cancelled = False + self.terminal_outcome: Optional[str] = None + + def input_sequence(self) -> int: + with self.condition: + return self.last_input + + def record_input(self, sequence: int) -> None: + with self.condition: + if self.terminal_outcome is not None or self.cancelled: + raise ValueError("PROTOCOL: invocation is already terminal") + if sequence != self.last_input + 1: + raise ValueError("PROTOCOL: input sequence is not contiguous") + self.last_input = sequence + self.condition.notify_all() + + def sequences(self) -> tuple: + with self.condition: + return self.last_input, self.last_result, self.acked_result + + def record_result(self, sequence: int) -> None: + with self.condition: + if self.terminal_outcome is not None or self.cancelled: + raise ValueError("PROTOCOL: invocation is already terminal") + if sequence != self.last_result + 1 or sequence > self.last_input: + raise ValueError("PROTOCOL: result sequence is not contiguous") + self.last_result = sequence + self.condition.notify_all() + + def terminal_snapshot(self) -> tuple: + with self.condition: + outcome = self.terminal_outcome + if outcome is None: + if self.finish_acked: + outcome = _TERMINAL_SUCCESS + elif self.finish_sent: + outcome = _TERMINAL_FINISH_UNCONFIRMED + elif self.cancelled: + outcome = _TERMINAL_CANCELLED + else: + outcome = _TERMINAL_FAILED + return self.last_result, self.finish_id, outcome + + def mark_finish_sent(self, finish_id: str) -> str: + with self.condition: + if self.terminal_outcome is not None or self.cancelled: + raise ValueError("PROTOCOL: invocation is already terminal") + if self.finish_sent or not finish_id: + raise ValueError("PROTOCOL: Finish was already sent") + self.finish_id = finish_id + self.finish_sent = True + return finish_id + + def freeze_terminal(self) -> str: + """Linearize the outcome before the active entry is removed. + + A Finish identifier only proves that the worker emitted Finish. It + does not prove that the peer accepted AcknowledgeFinish. The latter + is the condition for SUCCESS; otherwise a sent Finish is frozen as + FINISH_UNCONFIRMED and cannot be promoted by a late action. + """ + with self.condition: + if self.terminal_outcome is None: + if self.finish_acked: + self.terminal_outcome = _TERMINAL_SUCCESS + elif self.finish_sent: + self.terminal_outcome = _TERMINAL_FINISH_UNCONFIRMED + elif self.cancelled: + self.terminal_outcome = _TERMINAL_CANCELLED + else: + self.terminal_outcome = _TERMINAL_FAILED + return self.terminal_outcome + + def mark_cancelled(self) -> None: + """Freeze cancellation intent before the active lease is removed. + + Cancellation is recorded on the invocation state rather than inferred + from cleanup timing. This lets a concurrent ACK observe the same + terminal gate: an already accepted Finish ACK still wins, while a + result or Finish ACK arriving after cancellation cannot advance the + invocation. + """ + with self.condition: + if self.terminal_outcome is None: + # An accepted Finish ACK is the terminal proof. Cancellation + # may race the transport teardown after that ACK, but it must + # not overwrite SUCCESS or make a later cleanup publish a + # contradictory CANCELLED tombstone. + if self.finish_acked: + return + self.cancelled = True + self.condition.notify_all() + + def ack_result(self, sequence: int) -> None: + with self.condition: + if self.cancelled: + raise ValueError("PROTOCOL: invocation terminal outcome is CANCELLED") + if self.terminal_outcome is not None: + if self.terminal_outcome != _TERMINAL_SUCCESS: + raise ValueError( + f"PROTOCOL: invocation terminal outcome is {self.terminal_outcome}" + ) + # An action can retain a state reference while cleanup moves + # that state to the terminal ledger. Once SUCCESS is frozen, + # only the final result sequence is an idempotent confirmation; + # accepting an earlier cumulative ACK would bypass the + # terminal ledger's exact-fence rule. + if sequence != self.last_result: + raise ValueError( + "PROTOCOL: terminal result ACK does not match the completed result" + ) + if sequence <= 0 or sequence < self.acked_result or sequence > self.last_result: + raise ValueError("PROTOCOL: result ACK is outside the received range") + self.acked_result = sequence + self.condition.notify_all() + + def wait_result_ack(self, sequence: int, context=None) -> None: + deadline = time.monotonic() + ACK_TIMEOUT_SECONDS + with self.condition: + while self.acked_result < sequence: + if context is not None and context.is_cancelled(): + raise TimeoutError("DEADLINE_EXCEEDED: result ACK wait cancelled") + remaining = deadline - time.monotonic() + if remaining <= 0: raise TimeoutError("DEADLINE_EXCEEDED: result ACK timeout") + self.condition.wait(min(remaining, 0.2)) + + def ack_finish(self, finish_id: str) -> None: + with self.condition: + if self.terminal_outcome is not None: + if self.terminal_outcome == _TERMINAL_SUCCESS and finish_id == self.finish_id: + return + raise ValueError( + f"PROTOCOL: invocation terminal outcome is {self.terminal_outcome}" + ) + # Cancellation may race the response after the peer has already + # accepted this exact Finish ACK. The accepted acknowledgement + # is the terminal proof and remains idempotent; a cancellation + # that won the race before the ACK is still rejected below. + if self.finish_acked and finish_id == self.finish_id: + return + if self.cancelled: + raise ValueError("PROTOCOL: invocation terminal outcome is CANCELLED") + if not self.finish_id or finish_id != self.finish_id: raise ValueError("PROTOCOL: invalid finish id") + self.finish_acked = True + self.condition.notify_all() + + def wait_finish_ack(self, context=None) -> None: + deadline = time.monotonic() + ACK_TIMEOUT_SECONDS + with self.condition: + while not self.finish_acked: + if context is not None and context.is_cancelled(): + raise TimeoutError("DEADLINE_EXCEEDED: Finish ACK wait cancelled") + remaining = deadline - time.monotonic() + if remaining <= 0: raise TimeoutError("DEADLINE_EXCEEDED: Finish ACK timeout") + self.condition.wait(min(remaining, 0.2)) + + +class RoutineFlightServer(_FlightServerBase): + def __init__( + self, + location: str, + *, + clock=time.monotonic, + terminal_ttl_seconds=TERMINAL_TTL_SECONDS, + lease_epoch=1, + ): + if isinstance(lease_epoch, bool) or not isinstance(lease_epoch, int) or lease_epoch <= 0 or lease_epoch > (1 << 64) - 1: + raise ValueError("PROTOCOL: invalid worker lease epoch") + super().__init__(location) + self._lock = threading.RLock() + self._active: Dict[tuple, _InvocationState] = {} + self._terminal: OrderedDict[tuple, _TerminalRecord] = OrderedDict() + self._terminal_bytes = 0 + self._active_bytes = 0 + # A group id is scoped by the account in the fencing tuple. Keeping + # only the textual id here would let one tenant block or close a + # same-named group owned by another tenant. + self._active_groups: Dict[tuple, int] = {} + self._closed_groups: Dict[tuple, int] = {} + self._closed_group_bytes = 0 + self._reserved_groups: set[tuple] = set() + self._reserved_group_bytes = 0 + self._clock = clock + self._terminal_ttl_seconds = terminal_ttl_seconds + self._lease_epoch = lease_epoch + # H is independent from the number of admitted Flight invocations K. + # A rejected acquire fails before the handler process is created and + # therefore cannot accumulate a hidden Python task queue. + self._handler_slots = threading.BoundedSemaphore(MAX_HANDLER_PROCESSES) + self._handler_quota = _HandlerQuota() + # A Flight reader or handler session remains owned by the Flight + # server until every resource close has succeeded. This queue is + # bounded by the active ledger budget, so a transient cleanup failure + # cannot create an unbounded reaper queue or silently release an + # invocation while a native reader or child is still live. + self._pending_cleanup_condition = threading.Condition() + self._pending_cleanups: Dict[tuple, _PendingInvocationCleanup] = {} + self._pending_cleanup_thread: Optional[threading.Thread] = None + self._pending_cleanup_stopping = False + # FlightServerBase.shutdown waits for active RPC methods to return. + # Set this before entering that wait so input readers, handler loops, + # and ACK waits have an independent cancellation source during a + # graceful worker shutdown. + self._shutdown_event = threading.Event() + + @staticmethod + def _entry_bytes(key: tuple) -> int: + # The admission estimate is deliberately conservative. The tuple is + # already bounded by MAX_CONTROL_BYTES, and its serialized size is + # stable for the lifetime of the fence. + encoded = json.dumps(key, separators=(",", ":"), ensure_ascii=True).encode("utf-8") + return len(encoded) + 128 + + @staticmethod + def _group_key(key: tuple) -> tuple: + """Return the account-scoped identity of a group epoch.""" + return key[0], key[2] + + @staticmethod + def _group_fence_bytes(group_key: tuple) -> int: + # Account id is a fixed-width uint64 on the wire. Include it in the + # bounded fence estimate so the capacity accounting matches the + # account-scoped key rather than only charging the display id. + return len(group_key[1].encode("utf-8")) + 16 + + def _purge_terminal_locked(self, now: float) -> None: + expired = [ + key + for key, record in self._terminal.items() + if record.expires_at <= now + and self._closed_groups.get(self._group_key(key), 0) >= key[3] + ] + for key in expired: + record = self._terminal.pop(key) + self._terminal_bytes -= record.bytes + + def _admit(self, key: tuple) -> _InvocationState: + size = self._entry_bytes(key) + group_key, group_epoch = self._group_key(key), key[3] + with self._lock: + if self._closed_groups.get(group_key, 0) >= group_epoch: + raise ValueError("PROTOCOL: execution group epoch is already closed") + self._purge_terminal_locked(self._clock()) + if key in self._active: + raise ValueError("PROTOCOL: invocation fence is active") + if key in self._terminal: + raise ValueError("PROTOCOL: invocation fence is terminal") + if group_key in self._active_groups: + raise ValueError("PROTOCOL: execution group epoch is already active") + if len(self._active) + len(self._terminal) >= MAX_LEDGER_ENTRIES: + raise ValueError("RESOURCE_EXHAUSTED: terminal ledger entries are full") + if self._active_bytes + self._terminal_bytes + size > MAX_LEDGER_BYTES: + raise ValueError("RESOURCE_EXHAUSTED: terminal ledger bytes are full") + if group_key not in self._closed_groups and group_key not in self._reserved_groups: + fence_bytes = self._group_fence_bytes(group_key) + if ( + len(self._closed_groups) + len(self._reserved_groups) + >= MAX_CLOSED_GROUP_ENTRIES + or self._closed_group_bytes + self._reserved_group_bytes + fence_bytes + > MAX_CLOSED_GROUP_BYTES + ): + raise ValueError("RESOURCE_EXHAUSTED: closed-group fence is full") + # Reserve the future tombstone before creating the handler. + # Terminal cleanup converts this reservation into the + # closed-generation fence. + self._reserved_groups.add(group_key) + self._reserved_group_bytes += fence_bytes + state = _InvocationState({}, size) + self._active[key] = state + self._active_bytes += size + self._active_groups[group_key] = group_epoch + return state + + def _require_current_lease(self, key: tuple) -> None: + if key[5] != self._lease_epoch: + raise ValueError( + "STALE_LEASE_EPOCH: invocation belongs to a different worker instance" + ) + + def _remember_terminal_locked(self, key: tuple, state: _InvocationState) -> None: + deadline = self._clock() + self._terminal_ttl_seconds + last_result, finish_id, outcome = state.terminal_snapshot() + self._terminal[key] = _TerminalRecord( + deadline, state.terminal_bytes, last_result, finish_id, outcome + ) + self._terminal.move_to_end(key) + self._terminal_bytes += state.terminal_bytes + + def _close_group_epoch_locked(self, key: tuple) -> None: + group_key, group_epoch = self._group_key(key), key[3] + current = self._closed_groups.get(group_key, 0) + if group_epoch <= current: + return + if group_key not in self._closed_groups: + fence_bytes = self._group_fence_bytes(group_key) + if group_key in self._reserved_groups: + self._reserved_groups.remove(group_key) + self._reserved_group_bytes -= fence_bytes + elif ( + len(self._closed_groups) >= MAX_CLOSED_GROUP_ENTRIES + or self._closed_group_bytes + fence_bytes > MAX_CLOSED_GROUP_BYTES + ): + # This is only reachable for state restored from an adapter + # predating group-fence reservations. Keep the terminal record + # and refuse collection until the fence is reconstructed. + return + self._closed_group_bytes += fence_bytes + self._closed_groups[group_key] = group_epoch + + def _finish_invocation(self, key: tuple, state: Optional[_InvocationState]) -> None: + # A rejected duplicate Open has no ownership of the existing state. + # Cleanup must therefore be identity based, not key based. + if key is None or state is None: + return + state.freeze_terminal() + with self._lock: + current = self._active.get(key) + if current is not state: + return + self._active.pop(key, None) + self._active_bytes -= state.terminal_bytes + group_key, group_epoch = self._group_key(key), key[3] + if self._active_groups.get(group_key) == group_epoch: + self._active_groups.pop(group_key, None) + # A started invocation is terminal even when the worker reports an + # error. Retaining the fence prevents a late retry from running + # user code a second time. + self._remember_terminal_locked(key, state) + # The current Gateway contract uses one member per group. The + # worker records that owner closure before allowing TTL collection; + # a future multi-member scheduler must send an explicit group + # closure before reusing this hook. + self._close_group_epoch_locked(key) + + def _ensure_pending_cleanup_thread_locked(self) -> None: + thread = self._pending_cleanup_thread + if thread is not None and thread.is_alive(): + return + thread = threading.Thread( + target=self._pending_cleanup_loop, + name="matrixone-python-udf-cleanup", + daemon=True, + ) + self._pending_cleanup_thread = thread + thread.start() + + def _retain_pending_cleanup( + self, + input_reader: Optional[_ExchangeInputReader], + handler_session: Optional[_HandlerProcessSession], + key: Optional[tuple], + state: Optional[_InvocationState], + ) -> bool: + """Retain exchange resources until every cleanup operation succeeds.""" + if key is None or state is None or (input_reader is None and handler_session is None): + return False + with self._pending_cleanup_condition: + existing = self._pending_cleanups.get(key) + if existing is not None: + return True + if len(self._pending_cleanups) >= MAX_PENDING_CLEANUPS: + # An admitted invocation must not lose its cleanup owner. A + # full queue is an adapter invariant violation; keeping the + # invocation active is safer than pretending ownership was + # released. + logging.critical( + "Python UDF pending cleanup capacity is full for %r", + key, + ) + return False + self._pending_cleanups[key] = _PendingInvocationCleanup( + input_reader=input_reader, + handler_session=handler_session, + key=key, + state=state, + next_attempt=time.monotonic(), + ) + self._ensure_pending_cleanup_thread_locked() + self._pending_cleanup_condition.notify_all() + return True + + def _pending_cleanup_loop(self) -> None: + while True: + with self._pending_cleanup_condition: + while True: + if self._pending_cleanup_stopping and not self._pending_cleanups: + return + if not self._pending_cleanups: + self._pending_cleanup_condition.wait() + continue + now = time.monotonic() + ready = [ + item for item in self._pending_cleanups.values() + if item.next_attempt <= now + ] + if ready: + break + wait_for = min( + item.next_attempt + for item in self._pending_cleanups.values() + ) - now + self._pending_cleanup_condition.wait(max(0.01, wait_for)) + + for item in ready: + errors = [] + if item.input_reader is not None: + try: + item.input_reader.close() + except Exception as exc: + errors.append(exc) + else: + with self._pending_cleanup_condition: + current = self._pending_cleanups.get(item.key) + if current is item: + item.input_reader = None + if item.handler_session is not None: + try: + item.handler_session.close() + except Exception as exc: + errors.append(exc) + else: + with self._pending_cleanup_condition: + current = self._pending_cleanups.get(item.key) + if current is item: + item.handler_session = None + if errors: + exc = errors[0] + item.failures += 1 + delay = min( + PENDING_HANDLER_CLEANUP_MAX_DELAY, + PENDING_HANDLER_CLEANUP_INITIAL_DELAY + * (2 ** min(item.failures, 5)), + ) + with self._pending_cleanup_condition: + current = self._pending_cleanups.get(item.key) + if current is item: + item.next_attempt = time.monotonic() + delay + self._pending_cleanup_condition.notify_all() + logging.error( + "Python UDF exchange cleanup retry failed for %r: %s", + item.key, + exc, + ) + continue + + # The session is now fully closed. Only then can the + # invocation owner release K, the ledger entry, and the group + # fence. _finish_invocation is idempotent with respect to any + # late ACK that arrived while the cleanup was pending. + finish_error = None + try: + self._finish_invocation(item.key, item.state) + except Exception as exc: + finish_error = exc + with self._pending_cleanup_condition: + current = self._pending_cleanups.get(item.key) + if current is item and finish_error is None: + del self._pending_cleanups[item.key] + elif current is item: + item.failures += 1 + item.next_attempt = time.monotonic() + PENDING_HANDLER_CLEANUP_MAX_DELAY + self._pending_cleanup_condition.notify_all() + if finish_error is not None: + logging.error( + "Python UDF invocation cleanup retry failed for %r: %s", + item.key, + finish_error, + ) + + def _stop_pending_cleanup_reaper(self) -> None: + # The base Flight server may fail while interrupting an RPC. The + # worker still owns its cleanup reaper in that case, so stopping and + # joining it cannot depend on the base shutdown returning normally. + with self._pending_cleanup_condition: + self._pending_cleanup_stopping = True + self._pending_cleanup_condition.notify_all() + thread = self._pending_cleanup_thread + if thread is not None: + # Normal shutdown has no pending sessions and joins immediately. + # A persistent OS/resource failure remains owned by the daemon + # reaper; the handler's parent-liveness pipe still guarantees + # child-group cleanup if this worker process exits. + thread.join(timeout=2.0) + with self._pending_cleanup_condition: + pending = len(self._pending_cleanups) + if pending: + logging.error( + "Python UDF worker shutdown left %d handler cleanups pending", + pending, + ) + + def shutdown(self): + self._shutdown_event.set() + try: + return super().shutdown() + finally: + self._stop_pending_cleanup_reaper() + + def _cleanup_exchange( + self, + key: Optional[tuple], + state: Optional[_InvocationState], + input_reader, + handler_session, + ) -> Optional[Exception]: + """Run every exchange cleanup step and return its first error. + + Closing a native Flight reader or a handler process is allowed to + fail while an RPC is already being cancelled. Those failures must + not skip the invocation fence cleanup: otherwise K, handler slots, + group reservations, and terminal de-duplication can disagree about + whether the invocation still owns resources. The caller decides + whether a cleanup error should replace an existing exchange error. + """ + cleanup_error: Optional[Exception] = None + + def close_with_retry(resource) -> tuple[bool, Optional[Exception]]: + last_error = None + for _ in range(2): + try: + resource.close() + return True, None + except Exception as exc: + last_error = exc + return False, last_error + + input_cleanup_succeeded = input_reader is None + if input_reader is not None: + input_cleanup_succeeded, cleanup_error = close_with_retry(input_reader) + + handler_cleanup_succeeded = handler_session is None + handler_error = None + if handler_session is not None: + handler_cleanup_succeeded, handler_error = close_with_retry(handler_session) + if cleanup_error is None: + cleanup_error = handler_error + + # Real native readers and process sessions retain ownership when close + # fails. Test doubles deliberately keep the old direct-cleanup + # behaviour so the helper tests do not create a false production + # resource owner. + pending_reader = ( + input_reader + if isinstance(input_reader, _EXCHANGE_INPUT_READER_TYPE) and not input_cleanup_succeeded + else None + ) + pending_session = ( + handler_session + if isinstance(handler_session, _HANDLER_PROCESS_SESSION_TYPE) and not handler_cleanup_succeeded + else None + ) + if pending_reader is None and pending_session is None: + try: + self._finish_invocation(key, state) + except Exception as exc: + if cleanup_error is None: + cleanup_error = exc + elif not self._retain_pending_cleanup(pending_reader, pending_session, key, state): + # Keep the invocation active if no cleanup owner could be + # registered. Returning the error makes the failure visible and + # prevents a false terminal record from authorizing a retry. + if cleanup_error is None: + cleanup_error = RuntimeError( + "Python UDF exchange cleanup owner could not be retained" + ) + return cleanup_error + + def do_action(self, context, action): + self._ensure_action_active(context) + if action.type == "GetPythonCapabilities": + request = _decode_capability_request(action.body) + # pyarrow exposes Result as a one positional-buffer value across + # supported releases; using a keyword here breaks the real Flight + # path before any routine is opened. + yield flight.Result(_encode_capabilities(request, self._lease_epoch)) + return + if action.type == "ValidatePythonDefinition": + value = _decode_definition_validation(action.body) + try: + _validate_definition_syntax(value) + except Exception as exc: + # A syntax error is a definition result, not an invocation + # failure. Returning a bounded structured result lets the + # Gateway reject CREATE/REPLACE without creating an active + # invocation, handler process, or terminal tombstone. + yield flight.Result( + _encode_definition_validation_result( + value, "ERROR", _safe_error(exc) + ) + ) + else: + yield flight.Result(_encode_definition_validation_result(value, "OK")) + return + control = _decode_control(action.body) + key = _tuple_key(control["tuple"]) + self._require_current_lease(key) + if action.type not in ("AcknowledgeResults", "AcknowledgeFinish"): + raise ValueError("PROTOCOL: unknown action") + if control["kind"] != action.type: + raise ValueError("PROTOCOL: action kind does not match action type") + with self._lock: + self._purge_terminal_locked(self._clock()) + state = self._active.get(key) + terminal = self._terminal.get(key) + # A cancelled action must not advance an active invocation. This is + # checked again after decoding and ledger lookup because an action can + # be queued while its Flight context or the worker is being closed. + # If cancellation races this check, the state mutation is the action + # acceptance point; the caller may then safely retry the idempotent + # acknowledgement when its parent context is still alive. + self._ensure_action_active(context) + if state is None: + if terminal is None: + raise ValueError("PROTOCOL: unknown invocation") + if terminal.outcome != _TERMINAL_SUCCESS: + raise ValueError( + f"PROTOCOL: invocation terminal outcome is {terminal.outcome}" + ) + if not terminal.finish_id: + raise ValueError("PROTOCOL: successful invocation has no Finish") + if action.type == "AcknowledgeResults": + sequence = _required_uint64(control, "ack_sequence") + if sequence != terminal.last_result: + raise ValueError("PROTOCOL: terminal result ACK does not match the completed result") + else: + finish_id = _required_string(control, "finish_id") + if finish_id != terminal.finish_id: + raise ValueError("PROTOCOL: terminal Finish ACK does not match the completed Finish") + yield _encode_control(self._ack_control(control)) + return + if action.type == "AcknowledgeResults": + state.ack_result(_required_uint64(control, "ack_sequence")) + elif action.type == "AcknowledgeFinish": + state.ack_finish(_required_string(control, "finish_id")) + yield _encode_control(self._ack_control(control)) + + def _ensure_action_active(self, context) -> None: + if self._shutdown_event.is_set() or _context_is_cancelled(context): + raise TimeoutError("DEADLINE_EXCEEDED: Flight action is cancelled") + + @staticmethod + def _ack_control(control: Dict[str, Any]) -> Dict[str, Any]: + value = {"kind": "Ack", "tuple": control["tuple"], "status": "OK"} + if control["kind"] == "AcknowledgeResults": + value["ack_sequence"] = control["ack_sequence"] + else: + value["finish_id"] = control["finish_id"] + return value + + def do_exchange(self, context, descriptor, reader, writer): + exchange_context = _ExchangeContext(context, self._shutdown_event) + state = None + key = None + handler_session = None + input_reader = None + writer_started = False + try: + if exchange_context.is_cancelled(): + raise TimeoutError("DEADLINE_EXCEEDED: Flight server is shutting down") + command = getattr(descriptor, "command", None) + if command is None: + raise ValueError("PROTOCOL: exchange is missing the invocation descriptor") + open_control = _decode_control(command) + if open_control["kind"] != "OpenInvocation": raise ValueError("PROTOCOL: first message must open an invocation") + if not isinstance(open_control.get("payload"), dict): + raise ValueError("PROTOCOL: invocation payload must be an object") + key = _tuple_key(open_control["tuple"]) + self._require_current_lease(key) + payload = open_control["payload"] + unknown_payload = set(payload) - _OPEN_PAYLOAD_KEYS + missing_payload = _OPEN_PAYLOAD_REQUIRED_KEYS - set(payload) + if unknown_payload: + raise ValueError("PROTOCOL: unsupported invocation payload field") + if missing_payload: + raise ValueError("PROTOCOL: invocation payload is missing a required field") + _validate_typed_call_contract(payload) + _function_ref(payload.get("function_ref"), open_control["tuple"]) + args = payload.get("args") + result_descriptor = payload.get("return") + if not isinstance(args, list) or any(not isinstance(item, dict) for item in args): + raise ValueError("PROTOCOL: invocation args must be an array of descriptors") + if not isinstance(result_descriptor, dict): + raise ValueError("PROTOCOL: invocation return must be a descriptor") + context_values = payload.get("context") + statement_context = _statement_context(context_values) + typed_context_values = _typed_statement_context(payload.get("statement_context")) + if typed_context_values is None: + raise ValueError("UNSUPPORTED_ROUTINE_VERSION: missing typed statement context") + typed_statement_context = _statement_context(typed_context_values) + if statement_context is not None and statement_context != typed_statement_context: + raise ValueError("PROTOCOL: typed statement context does not match context") + statement_context = typed_statement_context + effective_context = dict(context_values or {}) + # The typed form is the canonical wire representation. The + # trusted CN map predates it and may use equivalent textual + # encodings such as "+480" for a fixed offset. The parsed + # StatementContext comparison above rejects semantic drift; + # overwrite the handler-facing map with canonical values so + # equivalent encodings do not become a false protocol error. + effective_context.update(typed_context_values) + mode = _required_string(payload, "mode") + null_policy = _required_string(payload, "null_policy") + abi_contract = _required_string(payload, "abi_contract") + adapter_version = _required_string(payload, "adapter_version") + sdk_version = _required_string(payload, "sdk_version") + definition_schema_version = payload.get("definition_schema_version") + if type(definition_schema_version) is not int or definition_schema_version != DEFINITION_SCHEMA_VERSION: + raise ValueError("UNSUPPORTED_ROUTINE_VERSION: unsupported Python definition schema") + artifact_digest = _required_digest(payload, "artifact_digest") + environment_digest = _required_digest(payload, "environment_digest") + definition_fingerprint = _required_digest(payload, "definition_fingerprint") + max_batch_bytes = _required_positive_int(payload, "max_batch_bytes", 1 << 30) + max_batch_rows = _required_positive_int(payload, "max_batch_rows", 1 << 30) + max_invocation_rows = _required_positive_int(payload, "max_invocation_rows", 1 << 32) + max_invocation_result_bytes = _required_positive_int( + payload, "max_invocation_result_bytes", 1 << 40 + ) + handler_timeout_seconds = _required_positive_float( + payload, "handler_timeout_seconds", 3600.0 + ) + if mode not in (MODE_SCALAR, MODE_VECTOR) or null_policy not in (NULL_CALL, NULL_RETURN): raise ValueError("PROTOCOL: unsupported call mode or NULL policy") + if abi_contract != ABI_CONTRACT or adapter_version != ADAPTER_VERSION: raise ValueError("PROTOCOL: unsupported Python ABI contract") + if sdk_version != SDK_VERSION: raise ValueError("PROTOCOL: unsupported Python SDK") + source = _required_string(payload, "source") + handler_name = _required_string(payload, "handler") + if artifact_digest != _inline_artifact_digest(handler_name, source): + raise ValueError("UNSUPPORTED_ROUTINE_VERSION: Python artifact digest does not match the source") + if environment_digest != _environment_digest(): + raise ValueError("UNSUPPORTED_ROUTINE_VERSION: Python environment digest does not match the worker contract") + # Validate the complete frozen type contract before reserving a + # ledger entry. A malformed Open is rejected before it can leave + # a terminal tombstone behind. + for index, descriptor in enumerate(args): + _field(f"arg_{index}", descriptor) + result_field = _field("result", result_descriptor) + expected_fingerprint = _definition_fingerprint(payload) + if definition_fingerprint != expected_fingerprint: + raise ValueError( + "UNSUPPORTED_ROUTINE_VERSION: Python definition fingerprint does not match the typed definition" + ) + state = self._admit(key) + state.tuple = open_control["tuple"] + schema = None + result_schema = pa.schema([result_field]) + writer.begin(result_schema) + writer_started = True + writer.write_metadata(_encode_control({"kind": "ResultSchema", "tuple": open_control["tuple"]})) + ended = False + invocation_rows = 0 + invocation_result_bytes = 0 + input_reader = _ExchangeInputReader(reader) + while True: + try: + chunk = input_reader.next(exchange_context) + except StopIteration: + break + # The reader can publish a chunk at the same instant that the + # RPC is cancelled. Re-check after the blocking handoff so a + # chunk already dequeued after cancellation cannot start user + # code or consume another handler slot. + if exchange_context.is_cancelled(): + raise TimeoutError("DEADLINE_EXCEEDED: input stream cancelled") + if chunk is None or (chunk.data is None and not chunk.app_metadata): + raise ValueError("PROTOCOL: empty input frame") + if chunk.data is not None: + if ended: + raise ValueError("PROTOCOL: input arrived after EndInput") + if schema is None: + schema = reader.schema + _validate_schema(schema, args) + batch = chunk.data + _validate_input_batch_schema(batch, schema, args) + control = _decode_control(chunk.app_metadata) + _require_tuple(control["tuple"], open_control["tuple"]) + if control["kind"] != "InputBatch": raise ValueError("PROTOCOL: data batch is missing InputBatch") + sequence = _required_uint64(control, "sequence") + if sequence != state.input_sequence() + 1: raise ValueError("PROTOCOL: input sequence is not contiguous") + if batch.num_rows <= 0: raise ValueError("PROTOCOL: empty input batch") + if batch.num_rows > max_batch_rows: raise ValueError("RESOURCE_EXHAUSTED: input batch has too many rows") + if invocation_rows > max_invocation_rows - batch.num_rows: + raise ValueError("RESOURCE_EXHAUSTED: invocation has too many rows") + if batch.nbytes > max_batch_bytes: raise ValueError("RESOURCE_EXHAUSTED: input batch exceeds byte limit") + for index, descriptor in enumerate(args): + _validate_array_values(batch.column(index), descriptor) + state.record_input(sequence) + if handler_session is None: + # Start the bounded child while the parent builds the + # handler request. The child imports the frozen + # runtime concurrently with this Arrow snapshot; + # admission and all input validation still happen + # before a handler slot is acquired. + owner_id = _handler_quota_owner(payload) + try: + handler_session = _HandlerProcessSession( + self._handler_slots, + handler_quota=self._handler_quota, + account_id=key[0], + owner_id=owner_id, + ) + except _HandlerCleanupPending as pending: + handler_session = pending.session + raise pending.error from None + execution_request = { + "source": source, + "handler": handler_name, + "mode": mode, + "null_policy": null_policy, + "abi_contract": abi_contract, + "adapter_version": adapter_version, + "sdk_version": sdk_version, + "definition_schema_version": definition_schema_version, + "artifact_digest": artifact_digest, + "environment_digest": environment_digest, + "definition_fingerprint": definition_fingerprint, + "context": effective_context, + "args": args, + "return": result_descriptor, + "max_batch_bytes": max_batch_bytes, + "max_batch_rows": max_batch_rows, + "max_invocation_rows": max_invocation_rows, + "max_invocation_result_bytes": max_invocation_result_bytes, + "arrow_encoding": HANDLER_ARROW_RECORD_BATCH, + "input": _serialize_record_batch_message(batch), + } + output_wire = handler_session.run( + exchange_context, execution_request, handler_timeout_seconds + ) + output_batch = _deserialize_record_batch_message( + output_wire, result_schema + ) + if output_batch.num_rows != batch.num_rows or output_batch.num_columns != 1: + raise ValueError("TYPE_CONTRACT: handler result has the wrong shape") + _validate_field(output_batch.schema.field(0), "result", result_descriptor) + output_array = output_batch.column(0) + _validate_array_values(output_array, result_descriptor) + if pa.ipc.get_record_batch_size(output_batch) > max_batch_bytes: + raise ValueError("RESOURCE_EXHAUSTED: output batch exceeds byte limit") + invocation_result_bytes += pa.ipc.get_record_batch_size(output_batch) + if invocation_result_bytes > max_invocation_result_bytes: + raise ValueError("RESOURCE_EXHAUSTED: invocation result exceeds byte limit") + invocation_rows += batch.num_rows + state.record_result(sequence) + writer.write_metadata(_encode_control({ + "kind": "InputConsumed", + "tuple": open_control["tuple"], + "sequence": sequence, + # This is the decoded Arrow backing released by the + # worker after the handler has returned. It is bounded + # by max_batch_bytes and is distinct from the CN's + # transport framing bytes. A zero-column batch has + # no value buffers, but still consumes one logical + # accounting unit so the positive-credit protocol + # remains valid for zero-argument VECTOR calls. + "released_bytes": max(int(batch.nbytes), 1), + "released_batches": 1, + })) + writer.write_with_metadata(output_batch, _encode_control({"kind": "ResultBatch", "tuple": open_control["tuple"], "sequence": sequence})) + state.wait_result_ack(sequence, exchange_context) + if handler_session.should_rollover: + handler_session.close() + handler_session = None + elif chunk.app_metadata: + control = _decode_control(chunk.app_metadata) + _require_tuple(control["tuple"], open_control["tuple"]) + if control["kind"] == "EndInput": + last_sequence = _required_uint64(control, "last_sequence", allow_zero=True) + if ended: + if last_sequence != state.input_sequence(): + raise ValueError("PROTOCOL: EndInput changed after input was closed") + continue + if last_sequence != state.input_sequence(): + raise ValueError("PROTOCOL: invalid EndInput") + ended = True + elif control["kind"] == "OpenInvocation": + raise ValueError("PROTOCOL: duplicate OpenInvocation") + else: + raise ValueError("PROTOCOL: unexpected control without Arrow data") + if not ended: raise ValueError("PROTOCOL: input stream ended before EndInput") + last_input, last_result, acked_result = state.sequences() + if acked_result != last_result: raise ValueError("PROTOCOL: result is not acknowledged") + finish_id = state.mark_finish_sent(_uuid.uuid4().hex) + writer.write_metadata(_encode_control({ + "kind": "Finish", + "tuple": open_control["tuple"], + "status": "OK", + "finish_id": finish_id, + "last_sequence": last_input, + "last_result_sequence": last_result, + })) + state.wait_finish_ack(exchange_context) + except Exception as exc: + if state is not None and _is_cancellation_error(exc, exchange_context): + state.mark_cancelled() + if writer_started and key is not None: + try: + writer.write_metadata(_encode_control({"kind": "Error", "tuple": open_control["tuple"], "status": "ERROR", "reason": _safe_error(exc)})) + except Exception: + pass + raise + finally: + exchange_error = sys.exc_info()[1] + cleanup_error = self._cleanup_exchange( + key, state, input_reader, handler_session + ) + if cleanup_error is not None and exchange_error is None: + raise cleanup_error + if cleanup_error is not None: + logging.error( + "Python UDF exchange cleanup failed after an exchange error: %s", + cleanup_error, + ) + + +def _is_cancellation_error(exc: Exception, context) -> bool: + if _context_is_cancelled(context): + return True + # Handler, result-ACK, and Finish-ACK deadlines use this stable protocol + # category. Once observed, they are a cancellation terminal outcome even + # if the transport context has not yet reported cancellation locally. + return isinstance(exc, TimeoutError) and str(exc).startswith("DEADLINE_EXCEEDED:") + + +def _safe_error(exc: Exception) -> str: + message = str(exc) + categories = ("PROTOCOL:", "TYPE_CONTRACT:", "USER_CODE:", "RESOURCE_EXHAUSTED:", "DEADLINE_EXCEEDED:") + if not message.startswith(categories): + return "USER_CODE: handler or runtime failed" + return message[:512] + + +def main() -> None: + if _HANDLER_ENTRY: + _execute_handler_subprocess() + return + + import argparse + import secrets + + parser = argparse.ArgumentParser() + parser.add_argument("--execute-handler", action="store_true") + parser.add_argument("--address") + args = parser.parse_args() + if not args.address: + parser.error("--address is required for the Flight server") + logging.basicConfig(level=logging.INFO, format="[%(asctime)s] %(levelname)s %(message)s") + address = args.address if "://" in args.address else "grpc://" + args.address + # Every worker process is a distinct execution owner. A random positive + # epoch prevents a restarted worker at the same endpoint from accepting + # control messages issued to the previous process. Direct unit-test + # servers keep the deterministic default of one. + lease_epoch = secrets.randbits(63) or 1 + server = RoutineFlightServer(address, lease_epoch=lease_epoch) + server.serve() + + +if __name__ == "__main__": + main() diff --git a/pkg/udf/python_contract.go b/pkg/udf/python_contract.go new file mode 100644 index 0000000000000..60bfd4d12f679 --- /dev/null +++ b/pkg/udf/python_contract.go @@ -0,0 +1,95 @@ +// Copyright 2026 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 udf + +import ( + "crypto/sha256" + "encoding/binary" + "encoding/hex" + "fmt" + + "github.com/matrixorigin/matrixone/pkg/udf/protocol" +) + +const ( + pythonInlineArtifactDigestDomain = "matrixone-python-inline-artifact" + pythonEnvironmentDigestDomain = "matrixone-python-environment" +) + +// PythonInlineArtifactDigest identifies the exact source payload sent to the +// worker. Length-prefixing each UTF-8 string prevents delimiter ambiguity and +// gives the Python adapter an unambiguous, language-independent algorithm. +func PythonInlineArtifactDigest(handler, source string) string { + return pythonContractDigest(pythonInlineArtifactDigestDomain, handler, source) +} + +// PythonEnvironmentDigest identifies the worker-side contract that interprets +// an inline source definition. The current environment plane is deliberately +// small: the executable artifact is inline, while the ABI, plan, type and +// timezone contracts are fixed by the negotiated worker capability. A future +// artifact store may add its immutable environment digest without changing +// this current digest algorithm. +func PythonEnvironmentDigest() (string, error) { + tzVersion, err := TimezoneDatabaseVersion() + if err != nil { + return "", err + } + return pythonContractDigest( + pythonEnvironmentDigestDomain, + fmt.Sprintf("%d", protocol.Version), + PythonABIContract, + PythonAdapterVersion, + PythonSDKVersion, + fmt.Sprintf("%d", PythonDefinitionSchemaVersion), + fmt.Sprintf("%d", PythonPlanContractVersion), + PythonTypeDescriptorContract, + tzVersion, + ), nil +} + +// IsSHA256Digest is used at execution boundaries for persisted digests and +// fingerprints. It accepts the canonical lower-case hexadecimal spelling +// only, so malformed or alternate encodings cannot create ambiguous identity. +func IsSHA256Digest(value string) bool { + if len(value) != sha256.Size*2 { + return false + } + decoded, err := hex.DecodeString(value) + if err != nil || len(decoded) != sha256.Size { + return false + } + for _, ch := range value { + if ch >= 'A' && ch <= 'F' { + return false + } + } + return true +} + +func pythonContractDigest(domain string, parts ...string) string { + hash := sha256.New() + writePythonDigestPart(hash, domain) + for _, part := range parts { + writePythonDigestPart(hash, part) + } + return hex.EncodeToString(hash.Sum(nil)) +} + +func writePythonDigestPart(hash interface{ Write([]byte) (int, error) }, value string) { + var length [8]byte + binary.BigEndian.PutUint64(length[:], uint64(len(value))) + _, _ = hash.Write(length[:]) + _, _ = hash.Write([]byte(value)) +} diff --git a/pkg/udf/python_contract_test.go b/pkg/udf/python_contract_test.go new file mode 100644 index 0000000000000..543e489773c52 --- /dev/null +++ b/pkg/udf/python_contract_test.go @@ -0,0 +1,37 @@ +// Copyright 2026 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 udf + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestPythonInlineArtifactDigestMatchesCrossLanguageVector(t *testing.T) { + const want = "d3b06769662f0e30fca60e6dedc479c5aacef6c488c6489366fdb540ee374f26" + require.Equal(t, want, PythonInlineArtifactDigest("add", "def add(ctx, value): return value")) + require.True(t, IsSHA256Digest(want)) + require.False(t, IsSHA256Digest("D3B06769662F0E30FCA60E6DED C479C5AACEF6C488C6489366FDB540EE374F26")) +} + +func TestPythonEnvironmentDigestIsCurrentAndStable(t *testing.T) { + first, err := PythonEnvironmentDigest() + require.NoError(t, err) + second, err := PythonEnvironmentDigest() + require.NoError(t, err) + require.Equal(t, first, second) + require.True(t, IsSHA256Digest(first)) +} diff --git a/pkg/udf/pythonservice/cfg.go b/pkg/udf/pythonservice/cfg.go deleted file mode 100644 index 30df376f7c0ce..0000000000000 --- a/pkg/udf/pythonservice/cfg.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2023 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 pythonservice - -import ( - "context" - "github.com/matrixorigin/matrixone/pkg/common/moerr" -) - -type Config struct { - UUID string `toml:"uuid"` - Address string `toml:"address"` - // Path code path - Path string `toml:"path"` - // Python is the python executable path, optional, default to 'python' - Python string `toml:"python"` -} - -func (c *Config) Validate() error { - if c.Address == "" { - return moerr.NewInternalError(context.Background(), "missing python udf server address") - } - if c.Path == "" { - return moerr.NewInternalError(context.Background(), "missing python udf server path") - } - return nil -} - -type ClientConfig struct { - ServerAddress string `toml:"server-address"` -} - -func (c *ClientConfig) Validate() error { - if c.ServerAddress == "" { - return moerr.NewInternalError(context.Background(), "missing python udf server address") - } - return nil -} diff --git a/pkg/udf/pythonservice/client.go b/pkg/udf/pythonservice/client.go deleted file mode 100644 index 0abaae0e42bc6..0000000000000 --- a/pkg/udf/pythonservice/client.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2023 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 pythonservice - -import ( - "context" - "io" - "math" - "sync" - - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - - "github.com/matrixorigin/matrixone/pkg/common/moerr" - "github.com/matrixorigin/matrixone/pkg/udf" -) - -type Client struct { - cfg ClientConfig - sc udf.ServiceClient - mutex sync.Mutex -} - -func NewClient(cfg ClientConfig) (*Client, error) { - err := cfg.Validate() - if err != nil { - return nil, err - } - return &Client{cfg: cfg}, nil -} - -func (c *Client) init() error { - if c.sc == nil { - err := func() error { - c.mutex.Lock() - defer c.mutex.Unlock() - if c.sc == nil { - conn, err := grpc.NewClient(c.cfg.ServerAddress, - grpc.WithTransportCredentials(insecure.NewCredentials()), - grpc.WithDefaultCallOptions( - grpc.MaxCallSendMsgSize(math.MaxInt32), - grpc.MaxCallRecvMsgSize(math.MaxInt32), - ), - ) - if err != nil { - return err - } - c.sc = udf.NewServiceClient(conn) - } - return nil - }() - if err != nil { - return err - } - } - return nil -} - -func (c *Client) Run(ctx context.Context, request *udf.Request, pkgReader udf.PkgReader) (*udf.Response, error) { - if request.Udf.Language != udf.LanguagePython { - return nil, moerr.NewInvalidArg(ctx, "udf language", request.Udf.Language) - } - - if request.Type != udf.RequestType_DataRequest { - return nil, moerr.NewInvalidInput(ctx, "type of the first udf request must be 'DataRequest'") - } - - err := c.init() - if err != nil { - return nil, err - } - - stream, err := c.sc.Run(ctx) - if err != nil { - return nil, err - } - defer stream.CloseSend() - err = stream.Send(request) - if err != nil { - return nil, err - } - response, err := stream.Recv() - if err != nil { - return nil, err - } - switch response.Type { - case udf.ResponseType_DataResponse: - return response, nil - case udf.ResponseType_PkgRequest: - var reader io.ReadCloser - reader, err = pkgReader.Get(ctx, request.Udf.Body) - if reader != nil { - defer reader.Close() - } - if err != nil { - return nil, err - } - - pkgRequest := &udf.Request{ - Udf: request.Udf, - Type: udf.RequestType_PkgResponse, - Context: request.Context, - } - for { - pkg := &udf.Package{} - buffer := make([]byte, 5*1024*1024) - var offset int - for { - var n int - n, err = reader.Read(buffer[offset:]) - if err != nil { - if err == io.EOF { - pkg.Last = true - } else { - return nil, err - } - } - offset += n - - if pkg.Last || len(buffer) == offset { - pkg.Data = buffer[:offset] - break - } - } - - pkgRequest.Udf.ImportPkg = pkg - err = stream.Send(pkgRequest) - if err != nil { - return nil, err - } - - response, err = stream.Recv() - if err != nil { - return nil, err - } - - if pkg.Last { - return response, nil - } - } - default: - return nil, moerr.NewInternalError(ctx, "error udf response type") - } -} - -func (c *Client) Language() string { - return udf.LanguagePython -} diff --git a/pkg/udf/pythonservice/demo/README.md b/pkg/udf/pythonservice/demo/README.md deleted file mode 100644 index c68dce2404808..0000000000000 --- a/pkg/udf/pythonservice/demo/README.md +++ /dev/null @@ -1,295 +0,0 @@ -# MO Python UDF Demo - -This document briefly describes the use of python UDFs in MO, showing the flexibility and convenience of python UDFs. - -## Standalone Deployment - -1. Before the deployment, we need to make sure we have [python3](https://www.python.org/downloads/) locally and install the grpc package in python: - -``` -pip install protobuf -pip install grpcio -``` - -2. Follow the steps in [Getting Started](https://docs.matrixorigin.cn/en/1.0.0-rc1/MatrixOne/Get-Started/install-standalone-matrixone/) to complete the installation, and modify the configuration of mo_ctl by running the following command before starting MO: - -```shell -mo_ctl set_conf MO_CONF_FILE="${MO_PATH}/matrixone/etc/launch-with-python-udf-server/launch.toml" -``` - -3. Launch and connect to MO. - -## "Hello world" - -Let's start with a simple function: a python UDF that adds two numbers together. - -Input the following SQL in the client to create the function: - -```sql -create or replace function py_add(a int, b int) returns int language python as -$$ -def add(a, b): - return a + b -$$ -handler 'add'; -``` - -> Note: currently, matrixone does not perform syntax checking on the python script in UDF body. - -This SQL defines a function called py_add that takes two parameters of type `int` and returns the sum of the two parameters. Python code comes after `as`. `handler` represents the name of the python function that will be called. - -Now we can use the function: - -```sql -select py_add(1,2); -``` - -Output: - -``` -+--------------+ -| py_add(1, 2) | -+--------------+ -| 3 | -+--------------+ -``` - -We can remove the function when we no longer need it: - -```sql -drop function py_add(int, int); -``` - -We now have a basic understanding of how to use python UDFs. - -## Advancement - -In this section, we'll look at some more advanced uses of python UDFs. - -### Imported Python UDF - -In the previous section, the py_add function is written directly in SQL, and the python code is written after the keyword `as`. We call this form **embedded UDF**. However, if the function logic is very complex, writing it directly in SQL is not a good choice. It bloats the SQL statements and makes the code less maintainable. In this case, we can choose another way to create python UDFs: importing python code from an external file, known as **imported UDF**. There are two types of files that are supported: (1) a single python file, and (2) the wheel package. Let's continue with the example of the py_add function from the previous section, and write the python code to a file. - -The code for ./add func.py is as follows: - -```python -def add(a, b): - return a + b -``` - -Input the following SQL in the client to create the function(if you connect to matrixone via `mysql` cli, `--local-infile` flag is required to allow the cli reading local python files): - -```sql -create or replace function py_add(a int, b int) returns int language python import -'./add_func.py' -handler 'add'; -``` - -We use the keyword `import` to import the flie add_func.py from the current working directory. - -Call the function: - -```sql -select py_add(1,2); -``` - -We still get the same output as in the previous section: - -``` -+--------------+ -| py_add(1, 2) | -+--------------+ -| 3 | -+--------------+ -``` - -Importing a wheel package and a single python file share the same syntax, so we won't go into detail here. In the final example, we will create a python UDF by importing a wheel package. - -### Vector Option - -In some scenarios, we may want a python function to receive multiple tuples at once to improve the efficiency. For example, in model inference, we typically process data in batches, where each batch is a vector of tuples. The vector option is designed to handle this situation. We'll continue to use the py_add function as an example to demonstrate the usage of the vector option. - -Input the following SQL in the client to create the function: - -```sql -create or replace function py_add(a int, b int) returns int language python as -$$ -def add(a, b): # a, b are list - return [a[i] + b[i] for i in range(len(a))] -add.vector = True -$$ -handler 'add'; -``` - -We use `add.vector = True` to indicate that the python function add should receive two integer lists (vectors) as input, rather than individual integer values. - -Call the function: - -```sql -select py_add(1,2); -``` - -We still get the same output as in the previous section: - -``` -+--------------+ -| py_add(1, 2) | -+--------------+ -| 3 | -+--------------+ -``` - -With the vector option, we have the freedom to choose how the function processes its input, whether it's one tuple at a time or multiple tuples at once. - -### Type Mapping - -The correspondence between MO types and python types is as follows: - -| MO Types | Python Types | -| -------------------------------------------------------- | --------------------------- | -| bool | bool | -| int8, int16, int32, int64, uint8, uint16, uint32, uint64 | int | -| float32, float64 | float | -| char, varchar, text, uuid | str | -| json | str, int, float, list, dict | -| time | datetime.timedelta | -| date | datetime.date | -| datetime, timestamp | datetime.datetime | -| decimal64, decimal128 | decimal.Decimal | -| binary, varbinary, blob | bytes | - -### Function Overloading and Matching - -Overloading is not supported in MO UDF yet, all function names must be unique across an MO cluster. - -## Example: Credit Card Fraud Detection - -In this section, we use the example "Credit card fraud detection" to illustrate how python UDFs can be used in a machine learning inference pipeline. (Detailed code in [github](https://github.com/matrixorigin/matrixone/tree/main/pkg/udf/pythonservice/demo)) - -We need to ensure that the local python environment has numpy and scikit-learn installed. - -### Background - -It is important that credit card companies are able to recognize fraudulent credit card transactions so that customers are not charged for items that they did not purchase. (Details in kaggle [Credit Card Fraud Detection](https://www.kaggle.com/datasets/mlg-ulb/creditcardfraud)) - -### Data - -The dataset contains transactions made by credit cards in September 2013 by European cardholders. The data format is as follows: - -| Column Name | Type | Explanation | -| ----------- | ------ | ------------------------------------------------------------ | -| Time | int | Number of seconds elapsed between this transaction and the first transaction in the dataset | -| V1 ~ V28 | double | May be result of a PCA Dimensionality reduction to protect user identities and sensitive features | -| Amount | double | Transaction amount | -| Class | int | 1 for fraudulent transactions, 0 otherwise | - -We split the data into training, validation, and test sets in an 8:1:1 ratio. Since the training process is not the focus. we won't go into much detail here. We treat the test set as new data appearing in the production process, and store it in MO. The DDL is as follows: - -```sql -create table credit_card_transaction( - id int auto_increment primary key, - time int, - features json, -- store V1 ~ V28, using json list - amount decimal(20,2) -); -``` - -### Inference - -After the model is trained, we can write the inference function. The core code is as follows: - -```python -import decimal -import os -from typing import List - -import joblib -import numpy as np - -# model path -model_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'model_with_scaler') - - -def detect(featuresList: List[List[int]], amountList: List[decimal.Decimal]) -> List[bool]: - # load model - model_with_scaler = joblib.load(model_path) - - columns_features = np.array(featuresList) - column_amount = np.array(amountList, dtype='float').reshape(-1, 1) - # normalize the amount - column_amount = model_with_scaler['amount_scaler'].transform(column_amount) - data = np.concatenate((columns_features, column_amount), axis=1) - # model inference - predictions = model_with_scaler['model'].predict(data) - return [pred == 1 for pred in predictions.tolist()] - -# enable vector option -detect.vector = True -``` - -Then write setup.py to build the wheel package: - -```python -from setuptools import setup, find_packages - -setup( - name="detect", - version="1.0.0", - packages=find_packages(), - package_data={ - 'credit': ['model_with_scaler'] # 模型 - }, -) -``` - -The project directory structure is as follows: - -``` -|-- demo/ - |-- credit/ - |-- __init__.py - |-- detection.py # inference function - |-- model_with_scaler # model - |-- setup.py -``` - -Build the wheel package detect-1.0.0-py3-none-any.whl with the command `python setup.py bdist_wheel`. - -Create the function: - -```sql -create or replace function py_detect(features json, amount decimal) returns bool language python import --- replace with the directory where the wheel package is located -'your_code_path/detect-1.0.0-py3-none-any.whl' --- the function detect in the module credit -handler 'credit.detect'; -``` - -Call the function: - -```sql -select id, py_detect(features, amount) as is_fraud from credit_card_transaction limit 10; -``` - -Output: - -``` -+---------+----------+ -| id | is_fraud | -+---------+----------+ -| 1 | false | -| 2 | false | -| 3 | true | -| 4 | false | -| 5 | false | -| 6 | false | -| 7 | false | -| 8 | true | -| 9 | false | -| 10 | false | -+---------+----------+ -``` - -Now, we have completed the inference of task credit card fraud detection in MO. - -From this example, it's clear that we can easily use Python UDFs to tackle tasks that SQL alone cannot handle. Python UDFs not only extend the semantics of SQL but also spare us from writing data movement and transformation programs manually, greatly enhancing the development efficiency. diff --git a/pkg/udf/pythonservice/demo/README_CN.md b/pkg/udf/pythonservice/demo/README_CN.md deleted file mode 100644 index 392c90c6d5b67..0000000000000 --- a/pkg/udf/pythonservice/demo/README_CN.md +++ /dev/null @@ -1,293 +0,0 @@ -# MO Python UDF Demo - -本文简述了 MO 中 python UDF 的使用方式,展示了 python UDF 的灵活与便捷。 - -## 单机快速部署 - -1. 在部署之前,我们需要确保本地拥有 [python3](https://www.python.org/downloads/) 环境,并在 python 环境下安装 grpc 相关的 package: - -``` -pip install protobuf -pip install grpcio -``` - -2. 按照[快速开始](https://docs.matrixorigin.cn/1.0.0-rc1/MatrixOne/Get-Started/install-standalone-matrixone/)中的步骤完成相关安装,在启动 MO 之前,执行以下命令修改 mo_ctl 的配置: - -```shell -mo_ctl set_conf MO_CONF_FILE="${MO_PATH}/matrixone/etc/launch-with-python-udf-server/launch.toml" -``` - -3. 启动并连接 MO。 - -## "Hello world" - -我们从一个简单的函数开始说起:用 python UDF 实现两数之和。 - -在客户端中输入以下 SQL 来创建函数: - -```sql -create or replace function py_add(a int, b int) returns int language python as -$$ -def add(a, b): - return a + b -$$ -handler 'add'; -``` - -这段 SQL 定义了一个名为 py_add 的函数,接收两个类型为 `int` 的参数,其功能是返回两个参数的和,具体逻辑在 `as` 后的 python 代码中,`handler` 表示调用的 python 函数名称。 - -> 注意: 当前版本 matrixone 不会在创建 UDF 时检查 python 语法,用户需要自行保证 python 语法的正确性,否则在执行后续执行函数时会报错。 - -现在便可以使用该函数了: - -```sql -select py_add(1,2); -``` - -输出: - -``` -+--------------+ -| py_add(1, 2) | -+--------------+ -| 3 | -+--------------+ -``` - -当我们不再需要该函数时,可以将其删除: - -```sql -drop function py_add(int, int); -``` - -至此,我们已经掌握了 python UDF 的基本用法。 - -## 进阶 - -本节主要介绍 python UDF 的一些进阶用法。 - -### 导入式 python UDF - -在上一节中,py_add 函数是直接写在 SQL 中的,python 代码写在 `as` 关键字之后,我们称这种形式为**嵌入式 UDF**。然而,如果函数逻辑十分复杂,直接写在 SQL 中并不是一个好的选择,这会让 SQL 语句膨胀而且不利于代码的维护。这时,我们可以选择另一种创建 python UDF 的方式:从外部文件中导入 python 代码,即**导入式 UDF**。支持导入的文件有两种:(1) 单个 python 文件,(2) wheel 包。我们仍旧以上一节的 py_add 函数为例,把 python 代码写到文件中。 - -./add_func.py 代码如下: - -```python -def add(a, b): - return a + b -``` - -在客户端中输入以下 SQL 来创建函数(使用 `mysql` 命令行工具连接 matrixone 时,需要添加 `--local-infile` 允许工具读取本地的 Python 文件): - -```sql -create or replace function py_add(a int, b int) returns int language python import -'./add_func.py' -handler 'add'; -``` - -其中,我们使用 `import` 关键字来导入当前工作目录下的 add_func.py 文件。 - -调用函数: - -```sql -select py_add(1,2); -``` - -仍旧可以得到与上一节相同的输出: - -``` -+--------------+ -| py_add(1, 2) | -+--------------+ -| 3 | -+--------------+ -``` - -导入 wheel 包与单个 python 文件具有相同的语法,这里不再赘述。在最后的案例中,我们将会以导入 wheel 包的形式来创建 python UDF。 - -### Vector 选项 - -在某些场景下,我们会希望 python 函数一次性接收多个元组来提高运行效率。如在模型推理时,我们通常是以一个 batch 为单位进行的,这里的 batch 即为元组的 vector。而 vector 选项正是用来处理这种情况的。我们仍旧以 py_add 函数为例,展示 vector 选项的用法。 - -在客户端中输入以下 SQL 来创建函数: - -```sql -create or replace function py_add(a int, b int) returns int language python as -$$ -def add(a, b): # a, b are list - return [a[i] + b[i] for i in range(len(a))] -add.vector = True -$$ -handler 'add'; -``` - -其中,我们使用 `add.vector = True` 来标记 python 函数 add 接收两个 int 列表(vector)而不是 int 值。 - -调用函数: - -```sql -select py_add(1,2); -``` - -仍旧可以得到与上一节相同的输出: - -``` -+--------------+ -| py_add(1, 2) | -+--------------+ -| 3 | -+--------------+ -``` - -有了 vector 选项,我们就可以自由地选择函数的处理形式:一次一元组,或者一次多元组。 - -### 类型映射 - -MO 类型与 python 类型的对应关系如下: - -| MO 类型 | Python 类型 | -| -------------------------------------------------------- | --------------------------- | -| bool | bool | -| int8, int16, int32, int64, uint8, uint16, uint32, uint64 | int | -| float32, float64 | float | -| char, varchar, text, uuid | str | -| json | str, int, float, list, dict | -| time | datetime.timedelta | -| date | datetime.date | -| datetime, timestamp | datetime.datetime | -| decimal64, decimal128 | decimal.Decimal | -| binary, varbinary, blob | bytes | - -### 函数重载与匹配 - -MO UDF 目前不支持重载,函数名在一个 matrixone 集群要求是唯一的。 - -## 案例:信用卡欺诈检测 - -本节以“信用卡欺诈检测”为例,讲述了 python UDF 在机器学习推理流水线中的应用。(相关代码详见 [github](https://github.com/matrixorigin/matrixone/tree/main/pkg/udf/pythonservice/demo)) - -在本节中,我们需要确保本地 python 环境已安装了 numpy 和 scikit-learn。 - -### 背景 - -信用卡公司需要识别欺诈交易,以防止客户的信用卡被他人恶意使用。(详见 kaggle [Credit Card Fraud Detection](https://www.kaggle.com/datasets/mlg-ulb/creditcardfraud)) - -### 数据 - -数据集包含了2013年9月欧洲持卡人使用信用卡进行的交易记录。数据格式如下: - -| 列名 | 类型 | 含义 | -| -------- | ------ | ----------------------------------------------- | -| Time | int | 此交易与数据集中的第一个交易之间经过的秒数 | -| V1 ~ V28 | double | 使用 PCA 提取的特征(以保护用户身份和敏感特征) | -| Amount | double | 交易金额 | -| Class | int | 1:欺诈交易,0:非欺诈交易 | - -我们把数据按照8: 1: 1的比例划分为训练集、验证集和测试集。由于训练过程不是本文的重点,不在此处进行过多的介绍。我们把测试集当作生产过程中新出现的数据存储到 MO 中,DDL 如下: - -```sql -create table credit_card_transaction( - id int auto_increment primary key, - time int, - features json, -- 对应 V1 ~ V28,使用 json list 存储 - amount decimal(20,2) -); -``` - -### 推理 - -训练好模型之后,我们就可以编写推理函数了。其核心代码如下: - -```python -import decimal -import os -from typing import List - -import joblib -import numpy as np - -# 模型路径 -model_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'model_with_scaler') - - -def detect(featuresList: List[List[int]], amountList: List[decimal.Decimal]) -> List[bool]: - # 加载模型 - model_with_scaler = joblib.load(model_path) - - columns_features = np.array(featuresList) - column_amount = np.array(amountList, dtype='float').reshape(-1, 1) - # 对金额进行归一化 - column_amount = model_with_scaler['amount_scaler'].transform(column_amount) - data = np.concatenate((columns_features, column_amount), axis=1) - # 模型推理 - predictions = model_with_scaler['model'].predict(data) - return [pred == 1 for pred in predictions.tolist()] - -# 开启 vector 选项 -detect.vector = True -``` - -然后编写 setup.py 用于构建 wheel 包: - -```python -from setuptools import setup, find_packages - -setup( - name="detect", - version="1.0.0", - packages=find_packages(), - package_data={ - 'credit': ['model_with_scaler'] # 模型 - }, -) -``` - -整个项目的目录结构如下: - -``` -|-- demo/ - |-- credit/ - |-- __init__.py - |-- detection.py # 推理函数 - |-- model_with_scaler # 模型 - |-- setup.py -``` - -使用命令 `python setup.py bdist_wheel` 构建 wheel 包 detect-1.0.0-py3-none-any.whl。 - -创建函数: - -```sql -create or replace function py_detect(features json, amount decimal) returns bool language python import -'your_code_path/detect-1.0.0-py3-none-any.whl' -- 替换为 wheel 包所在目录 -handler 'credit.detect'; -- credit module 下的 detect 函数 -``` - -调用函数: - -```sql -select id, py_detect(features, amount) as is_fraud from credit_card_transaction limit 10; -``` - -输出: - -``` -+---------+----------+ -| id | is_fraud | -+---------+----------+ -| 1 | false | -| 2 | false | -| 3 | true | -| 4 | false | -| 5 | false | -| 6 | false | -| 7 | false | -| 8 | true | -| 9 | false | -| 10 | false | -+---------+----------+ -``` - -至此,我们已经在 MO 中完成了信用卡欺诈检测任务的推理。 - -通过该案例可以看出,我们可以方便地使用 python UDF 来处理 SQL 解决不了的任务。Python UDF 既扩展了 SQL 的语义,又避免了我们手动编写数据移动和转换的程序,极大地提高了开发效率。 diff --git a/pkg/udf/pythonservice/demo/credit/__init__.py b/pkg/udf/pythonservice/demo/credit/__init__.py deleted file mode 100644 index f59e717ed6d0c..0000000000000 --- a/pkg/udf/pythonservice/demo/credit/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# coding = utf-8 -# -*- coding:utf-8 -*- -from .detection import detect diff --git a/pkg/udf/pythonservice/demo/credit/detection.py b/pkg/udf/pythonservice/demo/credit/detection.py deleted file mode 100644 index 4a027ec163dc1..0000000000000 --- a/pkg/udf/pythonservice/demo/credit/detection.py +++ /dev/null @@ -1,62 +0,0 @@ -# coding = utf-8 -# -*- coding:utf-8 -*- -import decimal -import os -from typing import List - -import joblib -import numpy as np - -model_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'model_with_scaler') - - -def detect(featuresList: List[List[int]], amountList: List[decimal.Decimal]) -> List[bool]: - model_with_scaler = joblib.load(model_path) - - columns_features = np.array(featuresList) - column_amount = np.array(amountList, dtype='float').reshape(-1, 1) - column_amount = model_with_scaler['amount_scaler'].transform(column_amount) - data = np.concatenate((columns_features, column_amount), axis=1) - predictions = model_with_scaler['model'].predict(data) - return [pred == 1 for pred in predictions.tolist()] - - -detect.vector = True - -if __name__ == '__main__': - ret = detect( - [ - [-1.39598357648026, 1.07394393065875, 0.213508735697434, -1.00551307370986, 1.187300373936, - -1.07111854041464, 0.753203638755905, 0.30971495602621, -0.983991867539784, -1.70071141514904, - 0.823426013946253, 0.755747784301563, 0.57208601947088, -0.493305378300063, -0.470447091684077, - 0.748161458746014, -0.0446257458090844, 1.15426779428755, -0.580978900127479, -0.04190738904369, - 0.313836892986802, 0.629705007512215, -0.702875042416293, -0.378664198371815, 1.17715716992152, - -0.0670218758532906, -0.108995491056784, -0.0807276510778096], - [-1.99458047217904, -1.63531939810522, 1.00669502032082, -1.43318273761075, 3.25919383016879, - 4.00823861971185, -1.66001967781548, 1.09946561236069, 1.91968533357403, -0.518543946411732, - -1.05471184392788, 0.446539472296582, -0.468234843104227, -1.40433618221015, -1.8103263742068, - -0.277012303056273, -0.290667580529318, -0.608743967003329, -0.218456639889371, -0.677311451910878, - -0.258971403019176, 0.0809710102853903, -0.579907932919128, 0.830053981653551, -0.462078172323048, - 0.437226392974709, -0.170400933244463, 0.0175635565102101], - [-3.0435406239976, -3.15730712090228, 1.08846277997285, 2.2886436183814, 1.35980512966107, - -1.06482252298131, 0.325574266158614, -0.0677936531906277, -0.270952836226548, -0.838586564582682, - -0.414575448285725, -0.503140859566824, 0.676501544635863, -1.69202893305906, 2.00063483909015, - 0.666779695901966, 0.599717413841732, 1.72532100745514, 0.283344830149495, 2.10233879259444, - 0.661695924845707, 0.435477208966341, 1.37596574254306, -0.293803152734021, 0.279798031841214, - -0.145361714815161, -0.252773122530705, 0.0357642251788156], - [-2.30334956758553, 1.759247460267, -0.359744743330052, 2.33024305053917, -0.821628328375422, - -0.0757875706194599, 0.562319782266954, -0.399146578487216, -0.238253367661746, -1.52541162656194, - 2.03291215755072, -6.56012429505962, 0.0229373234890961, -1.47010153611197, -0.698826068579047, - -2.28219382856251, -4.78183085597533, -2.61566494476124, -1.33444106667307, -0.430021867171611, - -0.294166317554753, -0.932391057274991, 0.172726295799422, -0.0873295379700724, -0.156114264651172, - -0.542627889040196, 0.0395659889264757, -0.153028796529788], - ], - [ - decimal.Decimal('2.35'), - decimal.Decimal('17.6'), - decimal.Decimal('529'), - decimal.Decimal('239.93'), - ] - ) - - print(ret) diff --git a/pkg/udf/pythonservice/demo/credit/model_with_scaler b/pkg/udf/pythonservice/demo/credit/model_with_scaler deleted file mode 100644 index ef63da8c1de5b..0000000000000 Binary files a/pkg/udf/pythonservice/demo/credit/model_with_scaler and /dev/null differ diff --git a/pkg/udf/pythonservice/demo/ddl.sql b/pkg/udf/pythonservice/demo/ddl.sql deleted file mode 100644 index a840f98c3d498..0000000000000 --- a/pkg/udf/pythonservice/demo/ddl.sql +++ /dev/null @@ -1,1006 +0,0 @@ -drop table if exists credit_card_transaction; -create table credit_card_transaction( - id int auto_increment primary key, - time int, - features json, -- 对应 V1 ~ V28,使用 json list 存储 - amount decimal(20,2) -); -insert into credit_card_transaction (time, features, amount) values (157638, '[-1.39598357648026, 1.07394393065875, 0.213508735697434, -1.00551307370986, 1.187300373936, -1.07111854041464, 0.753203638755905, 0.30971495602621, -0.983991867539784, -1.70071141514904, 0.823426013946253, 0.755747784301563, 0.57208601947088, -0.493305378300063, -0.470447091684077, 0.748161458746014, -0.0446257458090844, 1.15426779428755, -0.580978900127479, -0.04190738904369, 0.313836892986802, 0.629705007512215, -0.702875042416293, -0.378664198371815, 1.17715716992152, -0.0670218758532906, -0.108995491056784, -0.0807276510778096]', 2.35); -insert into credit_card_transaction (time, features, amount) values (157639, '[-1.99458047217904, -1.63531939810522, 1.00669502032082, -1.43318273761075, 3.25919383016879, 4.00823861971185, -1.66001967781548, 1.09946561236069, 1.91968533357403, -0.518543946411732, -1.05471184392788, 0.446539472296582, -0.468234843104227, -1.40433618221015, -1.8103263742068, -0.277012303056273, -0.290667580529318, -0.608743967003329, -0.218456639889371, -0.677311451910878, -0.258971403019176, 0.0809710102853903, -0.579907932919128, 0.830053981653551, -0.462078172323048, 0.437226392974709, -0.170400933244463, 0.0175635565102101]', 17.6); -insert into credit_card_transaction (time, features, amount) values (157639, '[1.91995030623265, -0.5295747029094, -0.291774125621835, 0.644989215446892, -0.76675678904966, -0.384374141379217, -0.616882341317413, -0.0303795762697624, 1.25072392843323, 0.0132744068850985, -1.10026154824521, 0.331734538658172, 0.193348358893277, -0.257782871763926, 0.390828644791368, 0.283302715730695, -0.504784359906921, 0.057997610280608, -0.378145951606318, -0.135899240310776, 0.239401040560321, 0.864998262232592, 0.0783537317280094, -0.109595024583041, -0.197548684246792, 0.455488380685572, -0.0082640199045086, -0.0414176548014362]', 41.94); -insert into credit_card_transaction (time, features, amount) values (157639, '[-0.356158491296727, 1.19140675503969, -0.437619198206388, 1.17389858526241, 0.525367907476951, -0.471524075492547, 0.19921791891019, 0.239205320969324, -0.757000018757229, -0.433462393457057, -0.626163240442246, -0.170415717117371, 0.289081031012259, -0.445256858118694, 1.38237075501963, -0.697927739044338, 1.61687269021561, 0.214470276102167, 2.76077271804357, 0.149752362112721, -0.182841920481592, -0.552937665163497, 0.0335953721199883, 0.614989258141114, -0.986867753602889, 0.524161795846751, -0.0198743916937031, 0.100141172352533]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157639, '[2.02583456089301, -0.0460704553298835, -1.24939316418736, 0.274412261852914, -0.0275606053390044, -1.09971415141943, 0.154687080161978, -0.263754573657412, 0.33531332049879, 0.185334849098208, 1.08210981362046, 1.00130451318474, -0.0654466963955989, 0.69565703650254, 0.0364246570962769, -0.0461271446812628, -0.718075126924868, 0.403463206316367, 0.0230679539589328, -0.241081814272209, 0.302147569082114, 1.00340980337905, -5.88882811997649e-05, 0.11396159664657, 0.224937903068446, -0.133708994176919, -0.0233532686686872, -0.0680550254990753]', 0.89); -insert into credit_card_transaction (time, features, amount) values (157640, '[-1.25788044139779, 0.577768020042278, 0.456236866366804, -1.01285260644017, -1.56884105409177, 0.939294972711302, -2.09066900408235, 1.69062535105188, -1.06172905614274, 0.10065118670415, -0.572698298175859, 0.112910775422312, 0.159424394271634, 0.623588180799913, 0.68303613010055, -0.309407447179201, -0.164418821746834, 2.86081287192568, 0.157059825067622, -0.736265048870775, 0.127880379623038, 0.390366351325565, 0.107342480466096, 0.0309931910367953, -1.12833104910195, 0.685512178738179, -0.39438011099865, -0.0225425710328445]', 7.31); -insert into credit_card_transaction (time, features, amount) values (157641, '[1.98510586726557, 0.398792922511515, -2.45150499127779, 1.46248689674201, 1.03546637873498, -0.846499564070512, 0.679494343853913, -0.305204032502528, 0.198211935930933, -0.363112191003191, -0.798523200163691, -0.274237040248291, -0.662816737354039, -0.917638619957321, -0.260083274524396, -0.145069895449114, 0.953649350221411, 0.156306942085275, -0.361630039377152, -0.184153341133051, -0.0386108447781726, 0.0084067645958914, -0.037845829943511, 0.383466256565816, 0.48272284915951, -0.5115343341548, -0.0099082407947613, -0.0198086265817112]', 38.17); -insert into credit_card_transaction (time, features, amount) values (157641, '[-0.374887370619266, -4.11729339378491, -4.1875224037996, 1.18373794632254, -0.310090131427654, -0.899450472361004, 2.7252532041357, -0.949894054704977, -0.171053824310508, -0.383950298690729, -1.43292386006332, -0.233954787781866, -0.173060967229491, 1.15579858379694, 0.0609922403369292, -0.437634662704189, -0.227380513674285, -0.285718698521211, -0.113894844752243, 2.46723269810961, 1.01510422331704, 0.0863033514135896, -1.42676810402777, -0.596595689077286, 0.204409984529966, 0.927533302336789, -0.39802548901435, 0.125554710154175]', 1336.0); -insert into credit_card_transaction (time, features, amount) values (157642, '[-0.0416732511933412, 0.71244420568974, 0.33535085867153, -0.670760190626758, 0.428872888558093, -0.811847554634009, 0.810955098031995, 0.0078032655071081, -0.190866214880937, -0.223122386109244, 0.766145047980819, 0.468258261730657, -0.861865139996295, 0.474579604584876, -0.976567712386884, 0.0548392794470782, -0.527432188772319, -0.274295661265464, 0.107782136692494, -0.0774532911198698, -0.203471813529004, -0.485264248271819, 0.0890083834450539, -0.0100748971629493, -0.570358006667116, 0.123357366885259, 0.240495687692584, 0.0866455092013529]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157643, '[-0.832503466188826, 0.682723784631944, 1.02218856923446, -0.717397382886135, 0.427838532191477, 1.58550406037139, -0.335734551790415, 1.11338845257033, 0.019252243360449, -1.05141052489124, 0.457362240420781, 0.342512098801101, -1.10803892260668, 0.693400052583313, 0.766083459291204, -0.356980260432214, 0.172193840621312, -0.434130513898625, -0.166894804664431, -0.309253450215673, 1.02093015277999e-05, -0.0325676095011079, -0.0331243170780324, -1.69920795655913, -0.504059406166493, -0.412186968702842, 0.0735610937939236, 0.0523765924198769]', 3.99); -insert into credit_card_transaction (time, features, amount) values (157643, '[2.25420752750295, -1.24481322779075, -1.72863974578842, -1.68526914781163, -0.633272382837569, -1.07473988257085, -0.382061279894191, -0.511529894450943, -1.84369298764842, 1.61314870246791, -1.20851073789814, -0.580659560773602, 1.46325147523553, -0.196419847373187, 0.0428856326032823, -0.486149866833118, 0.160598658923804, -0.303179983132317, 0.137190343227818, -0.223003202600284, -0.303673405745144, -0.567555864976534, 0.138123576608639, -0.671257746323221, -0.0802396437891242, -0.282735378147483, -0.0305796850857915, -0.0499709148950415]', 85.0); -insert into credit_card_transaction (time, features, amount) values (157643, '[0.177244382040837, 0.917210791001869, -0.688700744979568, -0.679315255223694, 1.12326209092676, -0.432961532866439, 0.867039513116872, 0.0248384990656834, 0.182589944278121, -0.806064057014407, -1.40091161071351, -0.968885386690624, -1.14843099452001, -0.797624886028567, -0.0091049245692412, 0.510401354176316, 0.272376089211884, 0.0492453250291156, -0.0623830038520425, -0.0452201113723892, -0.389600056638222, -1.02675925702742, 0.0450413635222858, -0.113254034570941, -0.396547137570523, 0.159356219756419, 0.216028690279438, 0.0750202864404438]', 4.49); -insert into credit_card_transaction (time, features, amount) values (157644, '[-0.897403215679839, 0.699772862540808, 0.80409201072632, 0.635410858336631, 1.05363675650451, -0.818910252944362, 0.802695333475396, -0.150121994229663, -0.428486343256276, -1.06826373992494, -0.46973288624574, 0.347080934734465, 1.04875667172493, -1.46560256644374, 0.0509824543224673, 0.340349019538857, 0.362220016825516, 0.273746339761634, -0.704288412154429, 0.0121626544218576, -0.0603507325616821, -0.173919888747679, -0.323116082374684, -0.18831404209253, 0.984769914817444, -0.556450923893259, -0.202612462787745, -0.0024301912341971]', 50.0); -insert into credit_card_transaction (time, features, amount) values (157644, '[-1.32028971061182, -0.0967140071443226, 2.75444126359053, -2.10382883379794, -1.08911993985864, 1.17039076965806, -0.951504207644949, 0.442544482316705, 0.951322010621573, -0.0946106074903396, -2.0514309395451, -0.348748182659254, 0.446338569120425, -2.25011118237956, -2.33194561730455, 0.865589675341509, 0.291234687426737, -1.0016284014087, 0.454522241322133, 0.193914179861337, 0.200579799638371, 1.10369423135335, -0.545784798376071, 0.557538500117808, 0.706163403205832, -0.0325177396845115, -0.511315211437245, -0.383131262714821]', 9.6); -insert into credit_card_transaction (time, features, amount) values (157644, '[-0.839236815165994, 0.772772938354519, 0.896315790067565, -0.291204774756721, 1.10995788514525, -0.259922685295173, 1.02692579501918, -0.194909979465381, -0.707221666850287, -0.610249324986453, -1.00473075743882, 0.317539398659417, 1.0162701878275, -0.0636537611734492, 0.0062630658661567, -0.576085456788288, -0.0627513392625493, -0.614960936410469, 1.22269613107285, 0.165602349613131, -0.232444304473928, -0.666007271329866, -0.301846328581569, 0.531258279316342, 0.585379090020058, 0.507216145949509, -0.166378809200635, 0.101108142387477]', 31.39); -insert into credit_card_transaction (time, features, amount) values (157645, '[2.03473237043037, -0.438923466039102, -0.666964426144476, -0.0249050094282948, -0.215106953813965, 0.175390728144177, -0.646125813386846, 0.130326350894405, 0.919428287998534, 0.168865611671255, -0.074021206703936, 0.689784879203225, 0.146746265738576, 0.0419583431391672, -0.0793888274891199, 0.956846855573017, -1.14999454649998, 0.431947350122071, 0.623283175304275, -0.152084909882827, -0.237369120539355, -0.598430501807229, 0.278486347413146, -1.10562331840212, -0.526518996006121, 0.32141927610625, -0.0401344861298193, -0.0641254152450784]', 6.99); -insert into credit_card_transaction (time, features, amount) values (157645, '[-0.183479931137426, 0.857937614653596, 0.0807566218636643, 0.412551185793813, 1.03282928618833, -1.07274869321084, 1.40937765576693, -0.266740689201988, -0.487884963951038, -0.508335397186214, -1.26858618466222, -0.427358127869716, -1.09741794115717, 0.547713652967518, -0.825632826803471, -0.661245769623629, -0.181485880516096, -0.438938108956117, -0.425318700589288, -0.215632752764924, 0.0889922590906744, 0.283658660084031, -0.323451201392851, -0.0356676340499028, 0.706606250660853, -0.481030364345376, -0.0327263043071444, -0.035265296126595]', 21.56); -insert into credit_card_transaction (time, features, amount) values (157646, '[-1.03994732344747, 1.97440929932459, -1.4413951020941, -0.296659217416401, 0.5776944419145, -1.75100214096989, 0.51803695000682, 0.561321718994645, -0.47425509408744, -2.33512697140002, -0.445701875227705, -0.728294232624045, -0.884311269891526, -1.84691675181435, 0.60350717072587, 1.00089348707433, 2.06025981589296, 1.50450712172025, -1.01934337751317, -0.399906552122338, 0.299071601393581, 0.626380461177943, -0.295862513568879, -0.250576327442362, -0.0798821861819715, -0.202848250235844, -0.18622360787109, 0.0927429477928861]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157646, '[-2.69353886870738, 3.10044368971283, -2.55889744137267, -0.673985560453876, -0.9599197741292, -1.05020493531582, -0.847844018299585, 2.02481930629227, -0.231623935584156, 0.295327097438162, -0.106038118675719, 1.6857008031583, 0.900093210603649, 1.70460318180633, -0.407768316490628, 0.338110148596447, -0.101297811120048, 0.816532937868269, 0.294764224236611, 0.136757173994931, 0.466567982537171, 1.26862048621514, 0.127235361448291, -0.374555932835656, -0.371099953601298, -0.182618771753876, 0.409186278840597, 0.297486784826629]', 2.69); -insert into credit_card_transaction (time, features, amount) values (157647, '[2.05260047957892, -0.110828707060066, -1.24252955680428, 0.188362507635046, 0.149966334997958, -0.615491388148278, 0.0749179612326886, -0.16005763276635, 0.307527691571433, 0.241426971185178, 0.539575444856533, 0.994490117937812, 0.108495817934143, 0.434396258110717, -0.63063017978852, 0.227930779482464, -0.714481796968903, -0.224519558391214, 0.614696884032326, -0.194597509214057, -0.268227892903336, -0.670642669547294, 0.268215499852199, -0.491410166198354, -0.263485465875815, 0.20782111444266, -0.0749112758380428, -0.0748118791225046]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157647, '[-1.27199882743545, 0.170024393750088, -0.088251722094101, -2.11291307127448, 2.75153062500867, 3.66687082623167, -0.146953385279325, 0.950536072153524, 0.489146197127268, -0.622995755433168, -0.196149436731275, 0.0707399586978106, -0.203820118487718, -0.0268143762172014, 0.719533000167805, 0.41010495628507, -1.06715197027243, -0.140932915582162, -0.918224341480068, -0.253938392801881, -0.0269174966606696, -0.300689448818157, 0.213908698152699, 0.641920715206624, -0.40112906350585, -0.76218027414501, -0.467643723395709, 0.418321624672595]', 1.18); -insert into credit_card_transaction (time, features, amount) values (157648, '[2.11751020965837, 0.0235774478087018, -1.9870043554948, 0.293039239050815, 0.557169624192171, -0.579877938926374, 0.0576564317318973, -0.102645605597837, 0.789471792393416, -0.327531662600769, -1.388329399547, -0.944194688986781, -1.51183387023545, -0.545963751991944, 0.433139290855922, 0.569220418192005, 0.352482971760458, 0.0930677139455327, 0.289491593096733, -0.246063991259267, -0.423721871213864, -1.19176114420418, 0.286955353814581, -0.108455477801213, -0.234985090743966, 0.214397040406983, -0.0743007330473323, -0.0402667266075482]', 0.89); -insert into credit_card_transaction (time, features, amount) values (157648, '[1.2256294168653, -2.05483045588278, 0.581187780359728, 0.992412322822088, -1.98712886707541, 0.801471953821846, -1.23315068801493, 0.387753146721514, 2.27265675996996, -0.326349517961391, 0.0448312599642679, 1.58334135387118, 0.0022237043746793, -1.08403078522063, -2.18352446960988, 0.0524856989296345, -0.103699713770269, 0.410027617945241, 0.385379033868296, 0.447661826986291, 0.322247458766696, 0.750138445722837, -0.10597983595467, 0.19113939238615, -0.548493821296221, 0.679922959833611, -0.0208893379416632, 0.0102587672514416]', 328.0); -insert into credit_card_transaction (time, features, amount) values (157648, '[-0.248509726495573, 1.07946868252229, -0.393704058864527, -0.717591356587321, 0.433266436288412, -0.742173056932365, 0.650636809594189, 0.271991343687211, -0.147823288876947, -0.634919406057096, -1.7640334565014, -0.0047852664362168, 0.104355478852626, 0.40333711619458, -0.376267347676382, 0.253744161776144, -0.508267605605149, -0.450619902765913, 0.194131536965775, -0.11870850845706, -0.265742678361742, -0.729147274943867, 0.0467918131182337, -0.727072224534445, -0.365658411742183, 0.187573122607184, 0.118165813854475, 0.02770642473007]', 9.42); -insert into credit_card_transaction (time, features, amount) values (157649, '[1.97557156420932, 0.257052006508714, -2.30602086566742, 0.710884424036468, 0.692095080411303, -0.652265232920129, 0.0815479580842565, -0.0723374784955656, 0.434517554214779, -0.909660163633121, 1.46953564433281, 0.606872423893538, -0.252219110287855, -2.46321159652085, -1.01268702234767, 0.489980229475144, 1.82543420356317, 1.04599683077151, -0.0550521360391502, -0.103584896278749, 0.0385742696680821, 0.372966181302742, -0.0156695797948929, 0.567601948187327, 0.176486311786696, 0.675621228331706, -0.0423392384959142, -0.0146088068254063]', 12.31); -insert into credit_card_transaction (time, features, amount) values (157649, '[-0.923490195175723, -0.411541403361359, 1.31870999103651, -0.807033963370218, 1.07094881607993, -0.566722373692538, 0.130075177826392, 0.0337314567968639, 0.252200442683106, -0.169607973034594, 0.363178350489606, 0.547406517051136, 0.0437651361614005, -0.180551484396432, -0.560353267086069, 0.613677406482808, -1.12055820949404, 0.304506409314633, 0.26068587480448, 0.416315140021198, -0.149954952111745, -0.454977516408151, 0.243535026473874, -0.512818109939499, -0.825786410745404, 0.153323797882963, 0.164884187285001, 0.0275399485708718]', 40.47); -insert into credit_card_transaction (time, features, amount) values (157649, '[2.00855016015528, -1.00830627696618, -0.317348840213955, -0.0696998055948962, -1.27863546083863, -0.576883570660935, -0.886241531559988, -0.056933909460289, 0.116562119974472, 0.8426102410503, -1.31226379337613, -0.339061579495805, -0.313155831453531, -0.0866695618949391, 0.456310113353515, -0.995510666165627, -0.300401516461393, 1.13850279602969, -0.884743665061387, -0.551588310312965, -0.55429928472897, -1.15899745384567, 0.436957785315452, -0.193691591275635, -0.70936766810153, -0.0159983045075576, -0.0008288727590658, -0.0275011483844943]', 59.4); -insert into credit_card_transaction (time, features, amount) values (157649, '[0.223594544683996, 0.715958414102107, -2.13564557647109, -1.97535185861463, 0.496395482356357, -0.490560608050714, -0.5226307455962, -3.43752318061339, -1.01490684402817, 0.166872296900074, 1.04629208304285, -0.22376177865544, -0.96001081019648, -0.647368337467912, -1.84529756839946, 1.16804781165731, 1.16554201444276, -0.814668252428307, -0.271418265558344, -0.788696677113423, 3.36872714339997, -0.180131599083971, 0.0633492381088427, 0.604496607271027, 0.817962052808668, -0.0646537278128118, 0.223178530922308, 0.20813541732301]', 19.46); -insert into credit_card_transaction (time, features, amount) values (157650, '[2.04260022801273, -0.132571727934578, -1.20797226400629, 0.421332838027051, 0.015662256932516, -0.290900369965955, -0.469889792653869, -0.0631863606594573, 1.33273001135079, -0.642606146036098, -1.42330911291295, 0.0776184721728813, 0.686817593859346, -1.50219536621149, 0.824119868486107, 0.801319377845985, -0.0140382552155231, 1.12448350938074, -0.123450200949616, -0.115296834771437, 0.151440034559825, 0.709881626237922, -0.0839973191934584, -1.06186213184746, 0.120787015914271, -0.0784249578623302, 0.0525212587573732, -0.0203316678171085]', 12.58); -insert into credit_card_transaction (time, features, amount) values (157651, '[-0.131054840467345, 0.892623535809587, -0.482924297493091, -0.186360677836607, 0.803878161265486, -1.23191087867137, 0.751297125173002, -0.231255815536925, -0.138538859354719, -0.574688901380832, 1.20122831247042, 0.147984564660915, -0.69271123910182, -0.666342460960936, 0.0723310883844761, 0.24150976314228, 0.320811665517914, 1.25279506457288, 0.0952951751238245, -0.242764588140141, 0.366922538820285, 1.090995504712, -0.259874269506971, -0.0006046999046569, -0.486225886870085, -0.203213961396791, -0.0903803670810949, 0.105680510684779]', 7.37); -insert into credit_card_transaction (time, features, amount) values (157651, '[-0.210002232493935, 1.50789103972255, -1.86428166573953, -0.51623060411041, 0.751880968406418, -0.638984108486165, -0.126320115866028, -2.58409084090286, -0.819442409091646, -1.07986480071802, -1.32333628597076, 0.640977040282002, 0.257433530731629, 1.03499701651991, -1.00783228749532, -0.263062714568735, -0.0569792761702533, -0.582582294663413, -0.311308997111532, 0.326594219796808, -1.01533216687948, 1.11474741796973, 0.167665203226668, 0.729468154695518, -0.331569304619855, 0.499900829983917, -0.198667100462482, -0.0346444636175124]', 0.76); -insert into credit_card_transaction (time, features, amount) values (157651, '[-2.30131222984748, 1.47011403271157, 0.969135997155183, 2.18320065748936, -0.863390844215648, 1.15195530858573, -2.29451663092486, -4.7762607704627, -1.40541108966046, -1.25200599328173, -0.779001242062094, 0.913414366964245, 0.839656714002994, 1.09018386793027, 1.96595047392444, -0.184044207837079, 0.71272603988305, 0.379455125264061, 1.89719409549571, 1.28788467912956, -2.64102324260032, 0.663854666086816, 0.358991144686073, -0.0392489078526365, -0.024862449689254, -0.377762483156487, 0.213168112797435, -0.199975925427775]', 51.0); -insert into credit_card_transaction (time, features, amount) values (157652, '[0.884763508441952, -3.8156762988978, -1.39965199924788, -1.07414994019818, -2.11764507211758, 0.0562262021216791, -0.575881512021307, -0.240249343504635, -1.02828758751354, 1.22542348314424, -1.22168488615554, -0.845611984500319, 0.992455838261884, -0.533670049811058, 0.559956335227874, 0.0766888284180032, 0.109772507881296, 0.650536918075264, -0.591966248606822, 1.11981291980484, 0.456787832968756, 0.143628838729152, -0.434296991619562, 0.509650570790717, -0.515992421348443, -0.160519556864417, -0.100654882997993, 0.0925007709077297]', 746.5); -insert into credit_card_transaction (time, features, amount) values (157653, '[0.731815773882491, 0.543391502795749, -0.0859453295498783, 1.26866038121961, -0.159981828861613, -0.619255064874644, 0.283255994615255, -0.108725800739492, 0.169950171490531, 0.451790719569398, -1.15817984538723, -1.3323848087332, -2.39520068200804, 0.75274975621883, 1.3251194281676, -1.19737871621193, 0.904446729970673, -0.209928873922578, 2.71798863286453, -0.0391638608249803, -0.193578426863593, -0.480362852922719, 0.168862959676893, -0.115902546091977, -0.827008953700782, 0.651625087736028, -0.154819440325894, -0.0656439642523445]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157653, '[-0.242040291626059, 1.54914595234036, 1.47683333183473, 4.33927115234629, 0.308702290845302, 1.41422764612945, -0.188777403569096, 0.404470258555776, -1.56737273147991, 1.47564283478422, -1.46080551454826, -0.0466398267479782, 1.70359273145409, -0.393949877881024, 0.521185486043533, 0.150451806218905, -0.105424504585828, 0.513143478221745, 1.09606425914925, 0.215796943394874, 0.293115506032373, 1.05999152274052, -0.0976773042211085, 0.523527300220911, -0.89178463188075, 0.329421726372358, -0.133824701440268, -0.0581249766516207]', 0.76); -insert into credit_card_transaction (time, features, amount) values (157654, '[2.02864556574127, 0.390124397604779, -2.51097464221226, 1.26910008229917, 1.16460309329568, -0.417938470651313, 0.460249755768631, -0.0804069495275281, 0.0999638743893789, -0.149746806899267, 0.524412944037156, -0.16077415109147, -1.63969292573602, -0.559080106857778, -0.845525001405328, 0.160838401458979, 0.666700429762474, 0.837262194107146, 0.0371473224590694, -0.298526703002147, -0.035499392468754, 0.0193301415358212, -0.0371677287624363, 0.0600083711771599, 0.466886186083478, -0.506978598611515, -0.0132610376470388, -0.0407528843936862]', 1.91); -insert into credit_card_transaction (time, features, amount) values (157654, '[2.14415001735535, 0.0323729942785834, -2.48038703801522, -0.305775718260858, 1.01461584760383, -0.736586782691403, 0.61602968093617, -0.316018599242666, 0.0389752158700674, 0.196791265489431, 0.416213235107388, 0.469909539025883, -0.478685155427874, 1.04357831397847, -0.192120689854796, -0.216764594182215, -0.732967431993865, 0.241137805611009, 0.648505448182082, -0.209892287114361, 0.147317831783046, 0.482182665992543, -0.0922224335220843, 0.137528052007268, 0.498098720879354, 0.227611828144205, -0.0983984352723302, -0.0892664175038227]', 3.78); -insert into credit_card_transaction (time, features, amount) values (157654, '[-0.139570481420866, 0.986570540500794, -0.352421192173833, -0.623364626928538, 0.618639655181002, -0.691549848922661, 0.879960407436095, -0.0403334258719745, 0.105569639449889, 0.218615667103726, 0.350883965660528, -0.0448306532287092, -1.16732851369709, 0.76285829516748, -0.0341861611004669, -0.177702251619848, -0.731183949857996, 0.79652734944385, 0.356429851713179, 0.04708212875973, 0.362065348150772, 1.30296761613408, -0.156491362883465, -0.390287934492053, -0.779148194860942, -0.20579303693408, 0.608550201729674, 0.365622820007491]', 4.49); -insert into credit_card_transaction (time, features, amount) values (157655, '[-0.130650298013811, 0.391344166392019, -0.331644691033737, -0.914679131632785, 1.38356940698963, 0.893025265018253, 0.479004213082131, 0.316064292401913, -0.0094241345888292, -0.23071615668249, 0.687518444925768, 0.480511468523812, -0.773674725661566, 0.471457820690428, -0.245536895411608, -0.545160760336742, -0.0637737445794801, -1.30513596786077, -0.627754983305407, -0.368571775583073, -0.0781987507884595, -0.1947205650754, 0.231814152107424, -1.6599896006415, -1.05404526517416, 0.155443787188482, -0.207936416520938, 0.0409139679759314]', 1.29); -insert into credit_card_transaction (time, features, amount) values (157656, '[-0.714511714551263, 1.50830994194155, 0.50711822904093, -1.24805680461767, 1.35371701530256, -0.603719964734428, 2.51880797015708, -2.86665068532995, 2.14978087024674, 3.01726208671731, 0.50966761251635, 0.149514548378927, 1.03636642956818, -2.0082960794986, 0.497353337135643, -1.09386434323394, -1.42678343693498, -0.499209413042881, -0.75665693577444, 1.00438014445258, 0.514784736124527, 0.930591811787739, -0.342807675489497, 1.17927051560503, 0.164575056265144, -0.450424307262987, -0.71880343224745, -1.41543862183007]', 42.99); -insert into credit_card_transaction (time, features, amount) values (157656, '[-1.93162261550149, 2.59026458697747, -1.8635646963847, -0.78332639978214, 0.379243940523466, 2.01992521624267, -3.01241825666795, -9.30458305757629, -0.787083562192785, -1.46885648770044, -0.365148521542741, 0.89438014400985, -1.14325014731445, 1.92977715679965, -0.307119593585105, 0.528734748496315, -0.448653051895754, 1.11454285856003, 0.0767803133493333, 1.5493102077872, -1.89057320899291, 1.90035699107097, 0.694374997983098, -0.27225631246636, -0.88546484624186, -0.248580812580304, 0.487251246055333, 0.420299091534414]', 38.64); -insert into credit_card_transaction (time, features, amount) values (157656, '[-0.800762106912369, 0.641563618170274, -0.0542473432852957, -1.0353570227287, 1.05592140175839, 1.07685907759499, 0.404842864611541, 0.770551737727229, -0.309806663592078, -1.19832613584598, 0.703326066909501, 1.38521700403863, 0.259350543174613, 0.504158091478425, -0.868675618133526, -1.34371022300666, 0.571809780605375, -1.10482893317612, -0.515841706785354, -0.249907083791907, 0.423954505602875, 1.39683331985651, -0.270520166105858, -1.32386067169, -0.0799291067324985, 0.330705686921022, 0.0522321466482027, 0.0515707723195421]', 25.0); -insert into credit_card_transaction (time, features, amount) values (157656, '[-1.17972115342466, -0.715127721335505, 1.67847011483334, -2.51098657441316, -1.24320788858571, -0.355373467080695, -0.864014438483664, 0.602989356914037, -2.47130798944278, 0.449604051744373, 0.489932842914422, -0.54730730063812, -0.184492950366788, -0.0405632074931372, -0.789191100339196, -0.0462904298812544, 0.440081558068594, 0.507653898408722, 0.0981222104587931, -0.197840306613389, -0.239980636750593, -0.751914143143501, 0.0160181820558147, -0.0663703562011932, 0.148629349059861, -0.368713114256337, -0.0730746117330672, -0.0699371961925373]', 59.96); -insert into credit_card_transaction (time, features, amount) values (157656, '[-0.69925598832763, -0.352236464281865, 0.0057390750347395, -0.983922604023834, -1.47290368141819, 1.60438496397337, 2.14727671584301, -0.127730161743354, 0.423111261231837, -1.01599018293627, 0.0893037300841674, 0.644260363278789, 0.508249572525891, -0.286350822451644, -0.631106400047552, 0.628145055706801, -1.18271140508126, 1.00884901354628, 0.124126316280315, -0.0118866067613299, 0.328426207501013, 1.15568876565384, 0.358355812487624, 0.254846543156037, -0.809282201023793, -0.0674812107974641, 0.309106848985119, 0.128859987728555]', 500.0); -insert into credit_card_transaction (time, features, amount) values (157657, '[2.06065529120707, 0.0967682056317964, -1.84226514689002, 0.211719824847831, 0.655903660553579, -0.339267947329515, 0.0699097157998885, -0.0619455045999982, 0.26813553873579, -0.20688200725904, 0.780746407568512, 0.682695415456113, -0.0034561093824345, -0.661007033492326, -0.461955681876083, 0.626440722693654, 0.0867145742532093, 0.318225520469863, 0.486963768605476, -0.137470281028489, -0.339135124586196, -0.906144506841237, 0.281518992263576, 0.0982559045615988, -0.238615132433342, 0.178137055100331, -0.0671767366379961, -0.0447616832511111]', 0.89); -insert into credit_card_transaction (time, features, amount) values (157657, '[2.18818042484161, -0.773103238611821, -1.4501833660093, -1.08207684948781, -0.368355221346198, -0.728290645915194, -0.492612969549987, -0.168127631239908, -0.736081705459052, 1.05511923991411, 1.00837446023667, -0.210900880556817, -0.338492584560634, 0.306743550511566, -0.28171069360509, 1.11616365402975, -0.0865683066920131, -0.726171215691844, 0.714158081883484, -0.0217439467718453, 0.476267341474473, 1.2971038383396, 0.0191471334909879, 0.81171806437714, 0.171883774885656, 0.014216218174642, -0.0510154264298121, -0.0691723278268449]', 15.0); -insert into credit_card_transaction (time, features, amount) values (157657, '[2.02442612169502, -0.0457922137781754, -1.43728460562818, 0.137082080800018, 0.335117866082995, -0.54306817915896, 0.117418943478694, -0.164191461024606, 0.256384714142543, 0.154148678368035, 1.1322321838556, 1.19917839679656, 0.41896394774377, 0.592872046790169, 0.0837148882758289, -0.0782461678256967, -0.736411751248883, 0.317841249329, -0.0158626041352688, -0.176989447382873, 0.305489566640198, 0.992712047650541, 0.0251382007297824, 0.75248129260826, 0.251567520522297, -0.160579805414128, -0.0230530651597679, -0.0605606285556164]', 4.99); -insert into credit_card_transaction (time, features, amount) values (157658, '[1.40377169825774, -2.6309976417531, -3.06950406574649, -1.31511593176869, -0.653294210746356, -1.02472723679102, 0.537218955237356, -0.577322920377267, -2.30212136312151, 1.70686405080516, 0.619954822557503, -0.781639459350143, -0.720345309229526, 0.76773377284444, -1.18999428159289, -1.12709492309739, 0.617054629765677, 0.311603378387027, 0.12207349892807, 0.520588679292731, 0.45710051518232, 0.622242865329314, -0.550089665267033, 0.823799289029333, 0.42325250167685, 0.195507946667961, -0.178863067156689, -0.0056633826135274]', 513.5); -insert into credit_card_transaction (time, features, amount) values (157659, '[-0.766915012176013, 1.65810941095098, -2.20100292491025, -0.246884619046052, -0.472517200427092, -1.45627254343434, -0.223736534089503, 1.00315110200219, 0.611621497164623, -2.36505638695177, -0.979797925932203, 0.0818948713568789, -0.879830170176104, -1.30539038393444, -0.136204243327807, -0.0487513144691142, 2.40772721663277, 1.061014723443, 0.24995414382334, -0.575533528285327, 0.21957818327074, 0.50324071851885, 0.015525413458478, -0.202375052408002, -0.150324880057374, -0.607555815736408, -0.503800295003373, -0.176655700919763]', 25.0); -insert into credit_card_transaction (time, features, amount) values (157659, '[-2.86729243066438, 0.607702172395742, -1.54311656498544, 0.71970488741748, -0.482233181388535, 0.204499494885432, -0.430172239036267, 1.67406922039689, -0.969590970810925, -0.853290717655412, -0.292248510897408, 0.987725504776081, -0.0283780201316124, 1.72683865118839, -0.275243807120314, 0.961481825249245, -0.315459373695069, 0.446754440883145, 0.458406229556622, -0.5483134616846, -0.0799156665710331, -1.11372449678703, -0.101893504982621, 0.0705310890160139, -1.16127275795735, -1.30826306705791, -0.541450426343595, -0.253504882654566]', 102.6); -insert into credit_card_transaction (time, features, amount) values (157659, '[-0.538717496528732, 0.497037247301723, 0.678574861145991, -1.66156672531294, 1.35582470242373, -0.824378382058554, 1.54588846887594, -0.533860218763007, 0.114142222333549, -0.413710109051273, 0.410442320047211, -0.232262754628378, -1.35256320792588, 0.275493423859727, -0.801663455465844, 0.310926579720657, -1.49093744802186, 0.552536599983858, -1.12831386911552, -0.255665169044622, 0.252038677323505, 0.99794654015748, -0.408265262271822, -0.403829516815616, 0.231246814594198, -0.387908191550835, -0.363963138761858, -0.33481089709042]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157659, '[1.28868138797952, -1.87745285398862, -0.89979356052631, -0.373122036184729, -1.39458052839306, -0.91918362589843, -0.119944597218343, -0.24001131761432, 1.57950648194834, -0.542047035919234, -0.734635500763708, 0.214412021312011, -0.168677256237429, 0.105188736301048, 1.26772220691624, 0.302431217392923, -0.47286451385324, 0.201804213817699, -0.0565754042736389, 0.608199921604214, 0.411625477866091, 0.45787862405848, -0.159463773342714, 0.127795983631398, -0.498388019500921, 0.661999777707197, -0.114554399600257, 0.0156815597426271]', 400.0); -insert into credit_card_transaction (time, features, amount) values (157659, '[-0.399494835410856, 1.03678213917812, 0.0958452793138646, -0.919340951160011, 1.53262179125972, -0.123531537012885, 1.03494485214295, 0.0125673649789998, -0.777497152791399, -1.09231360828425, 0.581234860664014, 0.565161806922879, 0.520946612139756, -0.879500423824476, -0.928242724237109, 0.596289782032917, -0.0575109390421886, 0.437489196465249, 0.424729097397431, 0.026485214028216, -0.264700237411464, -0.788094069292817, -0.189154496819594, 0.0151889061197037, -0.116856695569056, 0.174762746705519, 0.0539158967715802, 0.140703700454984]', 1.29); -insert into credit_card_transaction (time, features, amount) values (157660, '[-1.9567996593669, -2.61014489166794, 1.33272373896791, -1.01638194532143, 0.49053715865399, -0.609377767688863, 0.071716736356296, -0.0261187425380272, -0.688233454409254, -0.0174830023455464, 0.197270848481793, 0.135105988862823, 0.135958540287801, -0.110333294172564, -0.0261327986481843, -1.13032240766272, -0.934574881359157, 2.64977752159329, -0.839338093193207, 0.677501031001426, 0.229884723910273, 0.29604673555042, 0.724878431810796, -0.426134003251837, 0.142261361839809, -0.597141874309556, -0.142115960786366, -0.0299325237997882]', 321.78); -insert into credit_card_transaction (time, features, amount) values (157660, '[2.09192847571684, -0.0946758072668112, -2.45451002739755, -0.173259692153288, 1.01942073652235, -0.483378422047769, 0.548368189548462, -0.264754665359746, -0.128042967414441, 0.37405293739716, 0.190773391424566, 0.269543868715931, -0.427628256181308, 0.957051225445838, -0.257671975956153, 0.163545488271148, -0.855595560493752, 0.169884936741724, 0.624972171863987, -0.116971736899008, 0.0759643734215985, 0.158294087591208, -0.0657696186901157, -0.0926934922241813, 0.289969275434798, 0.727969117192366, -0.143462014620172, -0.0896026228280068]', 36.7); -insert into credit_card_transaction (time, features, amount) values (157661, '[1.92496176830725, 0.308673497576981, -2.72488000282893, 1.20478745318954, 1.49367033156339, -0.0970418316058132, 0.688096346803086, -0.191729105711688, -0.20027895445151, -0.244098815822883, 0.504211207165045, 0.829453155235187, 0.570107064376773, -0.991268285938651, -1.03823497603221, 0.1954577888838, 0.39177616380819, 0.73100188100781, 0.161882074282815, -0.0059346452102432, 0.0032070607362702, 0.0772601889936939, -0.177371312751213, -0.3073120609512, 0.570127314194052, -0.495001888391882, -0.0131919231316632, -0.0283351288818505]', 72.0); -insert into credit_card_transaction (time, features, amount) values (157661, '[2.04310396825651, -0.0859443838594674, -1.17091417962632, 0.222069200560359, 0.097185342511995, -0.699205323107439, 0.0946682806176633, -0.184407289503525, 0.258221620067478, 0.234019295341422, 0.723036001459005, 1.18190212787914, 0.336335850770012, 0.392804210203451, -0.670174007828493, 0.170237327831798, -0.672222852365139, -0.30703095874152, 0.55423090260773, -0.184710890802614, -0.25542417995737, -0.620554894896932, 0.285097165097284, -0.327772411360968, -0.27546984721082, 0.19733769485619, -0.0729064908898449, -0.0727970843061939]', 1.29); -insert into credit_card_transaction (time, features, amount) values (157662, '[-0.678902755094102, 0.592388492368539, 0.100561205962415, -1.40332108804488, 1.67898871739388, 1.74566201609404, 0.740599839331643, 0.13396285679591, 0.499064022339229, -0.289074302162002, 0.483023610141462, 0.606980436560739, -0.44042658430394, -0.118821931598012, -0.649106157094929, -1.26494395650635, 0.0453481753827441, -0.895894269254039, -0.310048242709214, -0.221182325284272, 0.277358447755035, 1.06572393103763, -0.302255594341194, -0.888293840164624, -0.354553976096486, 0.121208274405332, -0.521254557947981, -0.0645931583109889]', 10.44); -insert into credit_card_transaction (time, features, amount) values (157662, '[-0.155784861380603, -0.014453524776931, 0.648109446414884, -1.04630158196848, 0.514031585861522, 0.298764243143644, 0.345469986911851, 0.210707596451789, 0.199614419128464, -0.809836977320697, 0.537598149506386, 1.20320406735625, 0.933408419800931, -0.153402823057145, -0.448885976553377, 0.512858151528217, -1.05614175203572, 0.273370542841903, 0.176577032873555, 0.149488999169619, -0.0969845931346009, -0.448259430882757, 0.302062651944207, 0.193430129736736, -0.442036587431237, -0.402538634393625, -0.0214182072052525, -0.0131542618320503]', 77.7); -insert into credit_card_transaction (time, features, amount) values (157662, '[2.14364255916549, -0.893865129537971, -0.655476327481577, -0.463836586080127, -0.841514151023904, -0.178681944358383, -0.957572075390224, -0.0693714184127005, -0.0008757656583835, 0.833030353579198, -1.28500043797636, 0.103234640521625, 0.93938707092135, -0.403614458875594, 0.334883657485709, -1.16486027280389, -0.362283847780942, 1.46161290714914, -0.996949775731555, -0.522496056978568, -0.073605417022869, 0.455536053520713, 0.148188823555128, 0.632236642007225, -0.178765618853877, 0.813242635002735, -0.0171298894691852, -0.0436872684495654]', 12.1); -insert into credit_card_transaction (time, features, amount) values (157662, '[-1.90736565426464, 0.67384060201129, -0.152918028105094, -1.5241369471231, 1.68595396552452, 4.28649383843176, -0.03899793397186, 1.26990047620504, 0.0201745479735995, -0.687288009662468, -0.130267154798492, 0.0665532139980587, -0.0349481760360964, 0.274178499755284, 1.47977466989759, 0.163948001003363, -0.460332045625155, 0.0050472781613322, 0.244590625448951, -0.335402788979408, -0.106067870886694, -0.494800653404582, 0.0607691121906984, 0.667957103302721, 0.36208419408435, -0.438986051355533, -0.706788421465791, 0.205657311481346]', 109.22); -insert into credit_card_transaction (time, features, amount) values (157664, '[-0.862387024902042, 1.78470367281811, -1.38775787378779, -1.66026708473102, 1.70641506304972, -0.95413573763879, 1.98703979262836, -0.727195563587107, 0.94144518719367, 1.4911580478853, -1.37360420398336, -0.763227897888498, -0.602794546296498, -0.0215747263190106, 0.0963476394298945, -0.675334286704451, -0.922752038319437, -0.187712852635465, 0.0172104283533561, 0.737292715221469, -0.0642561715728267, 0.642652554241579, -0.31861455430985, 0.0531787821033688, 0.0001807567220916, 0.0656196875104861, 0.585735804463068, 0.121318387442835]', 2.16); -insert into credit_card_transaction (time, features, amount) values (157665, '[2.04817471547879, 0.160891509841538, -1.75975319561615, 0.240847031281068, 0.656705375413303, -0.407588627071841, 0.134090819475397, -0.121984321631118, 0.124731830243019, -0.233330753248871, 1.06997705824216, 1.19995800815063, 0.844771627467875, -0.825597786123648, -0.569307935069556, 0.53989580273333, 0.0935927474354178, 0.160003637859814, 0.42174281232985, -0.0842305360986474, -0.318123549525181, -0.806213849790965, 0.289389090640184, 0.278961984560853, -0.230272669700398, 0.165385894702223, -0.0614547261018728, -0.0411052472494336]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157665, '[1.85870279773918, 0.396051041629609, -0.455366911681645, 3.86098983917909, 0.208507579286698, 0.126162728018291, 0.0131965552961598, 0.0489802730795498, -0.845638070131801, 1.55991100586878, 0.22577243084112, 0.414947272421794, -0.580585720132935, 0.266577297786502, -2.19883837974612, 0.631700207118974, -0.702440354452217, -0.0189354878139345, -1.08856866097233, -0.323787309691886, 0.130189017963616, 0.504362094254044, 0.0845574433770186, 0.0639351766871012, 0.0776383528141651, 0.0730375839484188, -0.032659310900174, -0.0604215347892459]', 7.58); -insert into credit_card_transaction (time, features, amount) values (157666, '[1.95279101351902, -0.443646680213216, -1.64373558608181, 0.157513597855708, 0.319796654027065, -0.200328722480518, 0.0958716466424794, -0.0623234262433549, 0.543482715761223, 0.219799115017581, -0.178400816130077, 0.261489094592664, -0.953867646087732, 0.608799293077844, -0.678692386227105, 0.233118444711131, -0.69303495574473, -0.0104506235005991, 0.797291024078636, -0.123507591532171, -0.231262239014541, -0.717605279304208, 0.104836156578914, -1.10714070345973, -0.161960492044155, 0.322044482786744, -0.0946842408649669, -0.0750659926959481]', 69.64); -insert into credit_card_transaction (time, features, amount) values (157666, '[0.0666260477973693, 0.593815427888797, -0.522878691313413, -0.679975879636316, 0.732897383075077, -1.21219306455882, 1.49501223350433, -0.289458227392707, -0.631534221749399, -0.361204025767523, 0.557276348023702, 0.0202015857971261, -1.46658320951785, 0.895822663843126, -1.35555825630229, -0.392276220018851, -0.342557203264131, -0.0493754067049264, 0.215628991956632, -0.15331249096827, 0.246035914963297, 0.660660434964352, -0.173448608693566, 0.126564700747486, 0.0360134286035453, 0.729353876823891, -0.0760040018886952, 0.0011735561200836]', 49.95); -insert into credit_card_transaction (time, features, amount) values (157667, '[-2.33353507264481, 2.46354962218188, 0.0941195136921072, 4.46483394314277, -0.265535547392461, 0.319256387897496, -0.208615935390274, 0.155277515285382, -2.95938211453577, 1.04504589444477, -1.22265002761061, 0.160343713770289, 1.54656272337205, 1.12680738289013, 0.894257121352872, 0.134212690824433, 0.585336201924697, 0.247568522109529, 1.11462971591331, -0.37267298666156, 1.13845278449457, 0.492590933528634, -0.374825397091449, 0.0436122629170256, 0.633610686193592, 0.67739750885263, -0.582974717540913, -0.165175977580806]', 55.38); -insert into credit_card_transaction (time, features, amount) values (157668, '[2.03804669121107, 0.149228928096936, -1.49356362147525, 0.541991577091293, 0.136141242468747, -1.18376465959481, 0.175941280497561, -0.252148730657828, 0.505357460827131, -0.369960062729377, -0.159077562004647, 0.152705745134623, -0.334666217716109, -0.751982994863708, 0.20138899583308, 0.180483677724108, 0.67865827130496, -0.438075952430741, -0.139525195530629, -0.192007415169572, -0.334124293304863, -0.875054160258706, 0.407086197716554, 1.04365772082047, -0.337475787869709, 0.140677126123062, -0.0640799319838407, -0.0258456228731323]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157669, '[2.30348772822127, -1.1003422751185, -2.6773253235167, -1.63428927304118, -0.0076793156786795, -1.2481723022086, 0.128023315710728, -0.643828712842836, -2.17526438795832, 1.6953077447938, -1.03249807539356, -0.848094200122647, 0.647195121863868, 0.199617782777387, -0.624026683784342, -1.42910298247797, 0.744921928840637, -0.443190944165041, -0.0141116922689533, -0.297007244682514, 0.144357919686483, 0.82706600686136, -0.191150560531695, 0.590109588043703, 0.677329811589187, 0.275917322692467, -0.0807080346350161, -0.0720901555637475]', 75.0); -insert into credit_card_transaction (time, features, amount) values (157669, '[1.91473786768401, -0.0493338141702305, -1.89540357698028, 0.0689704013070788, 1.23065499278398, 1.13876055425523, -0.172044228191091, 0.374879112286872, 0.231875454738994, -0.353585847129736, 1.59432167700619, 1.05129269147745, 0.0388187267979768, -0.588217656042168, 0.334877726145528, -0.351687516401723, 1.01270899353266, -1.17906725069728, -0.707203197243012, -0.235150494224008, -0.242574615962248, -0.509926924150119, 0.386134956007147, -0.821519981542935, -0.481882566963798, 0.268681463861382, -0.0128784758553372, -0.0546758025084535]', 0.99); -insert into credit_card_transaction (time, features, amount) values (157669, '[1.87446856530342, -0.46441843689523, -0.472121973473791, 0.18103869914988, -0.494605836015767, -0.237281592565409, -0.480886140400147, 0.0672599443036567, 1.05899007418193, -0.0889467223184553, 0.75020210451754, 1.14212531307948, 0.124141605150623, 0.263727736684343, 0.425507127067417, 0.449210717218909, -0.967536247730269, 0.509108683604654, 0.187854309406977, -0.126026761734618, -0.0618707295394016, -0.177110991339604, 0.266813923131493, -0.451860693176587, -0.386324119133951, -0.932109986929829, 0.0484066610755568, -0.0323440170864113]', 50.95); -insert into credit_card_transaction (time, features, amount) values (157670, '[2.12279133771394, -1.18741824192205, -0.916483921875039, -1.09236487905358, -0.727711739679387, 0.0764459281895712, -1.08103442973963, 0.0659246517250018, 0.0032208902291789, 0.906362620330379, -0.156255400131866, -0.344783537242717, -0.0507919872810802, -0.270931078890298, -0.405206919807005, 1.68154856766522, -0.483672636320703, -0.25218225156518, 1.13003290229964, 0.0654318639110971, 0.322088813490681, 0.887408335253001, -0.0388214523566199, -1.06834387231041, -0.0628157073385791, -0.0430772833385128, -0.0042268595413406, -0.063204173508402]', 49.99); -insert into credit_card_transaction (time, features, amount) values (157670, '[-2.59576480783823, 2.8840239391573, -2.3126776019042, -0.760320433945951, 0.213651620948756, 1.81649581536989, -3.55896540541555, -8.85262475130317, -0.741416240269013, -1.35215352304068, -0.489738719913259, 1.08574992463212, -1.07560466846554, 2.18203764850392, -0.321870391369415, 0.628842473016798, -0.284181179852542, 1.1275605561027, 0.0483897622914708, 1.53518079653712, -1.88674720866848, 1.85104279840616, 0.664449259513719, -0.268815204921672, -0.831607600369412, -0.242287134379948, 0.498574656340234, 0.372368425344521]', 15.45); -insert into credit_card_transaction (time, features, amount) values (157671, '[-0.0956813316911167, -0.367757271273178, 0.236132981001182, -2.65804257142269, -1.20649595496618, -1.13068285237342, -0.446167242708761, 0.301906524881184, 0.247123113323113, -0.877548922001801, -1.25464054481686, 0.148066269919556, 0.0053011356888609, 0.219864998355756, 0.828511274946982, -1.89657531109896, 0.180259751140201, 1.42362583442616, 0.304961802426908, -0.527425357706104, -0.408399754013747, -0.791635121453671, 0.403884811673834, -0.0966960227895864, -1.13719124258596, -0.610808696584691, 0.0634683348824682, 0.0389644225985704]', 41.06); -insert into credit_card_transaction (time, features, amount) values (157671, '[-1.86488219894914, 1.23613748194336, 1.55203146229971, -0.277503018029693, -1.68020467427744, 0.414109989733868, -1.35741923537803, 1.58293596192924, 0.899501508123272, -1.56880333199636, -1.95541618155083, 1.6023183750899, 1.2427244222821, -0.717529357684178, -2.16123285093702, -0.101621920209923, 0.64694513014031, -0.503990163032675, 0.207679299806106, -0.259278542066298, -0.025948886346506, 0.030922895620315, -0.177984159200742, 0.0824577060844309, 0.612711713176754, 0.696564590661485, -0.432156230597208, -0.188617923395142]', 3.71); -insert into credit_card_transaction (time, features, amount) values (157672, '[2.00553228161842, 0.0070868966527725, -3.65259548241003, -0.203742162034209, 2.88371007913055, 3.06387126009357, -0.407470730758041, 0.787168176369652, 0.573959954868234, -1.0425561174637, 0.458201855114249, -0.123987721389439, -0.470081890499791, -2.42916601060841, 0.0321352652214023, 0.266431399506244, 1.95537235613427, 0.506609128807379, -0.398342592881336, -0.067841254193996, -0.018586847672948, 0.151813633128278, -0.0081306451001703, 0.562138291560673, 0.239086126042579, 0.747061487131281, -0.0184026193243048, -0.0180547635727395]', 12.31); -insert into credit_card_transaction (time, features, amount) values (157672, '[-0.501119701945683, 0.631898598931087, 0.261426345840006, 0.81898535891173, 0.807476569727662, 0.0163751766080137, 1.50818509883941, -0.212048811020143, -0.99179495398615, -0.347735979589194, -0.93995294639717, -0.006084666561543, 0.869016128406528, 0.337219881241216, 0.817204393257627, -0.484879958652308, -0.36580688516666, 0.283787894216577, 0.41421824194594, 0.429927128156805, 0.437560512581943, 1.05161420378429, -0.0122425995554489, 0.54232587914934, 0.293018758630902, -0.293144286742353, 0.112615866328799, 0.173152642655114]', 158.5); -insert into credit_card_transaction (time, features, amount) values (157672, '[0.177812185476632, 1.46402086483703, -2.41533855299721, 0.548454242435985, 0.907647046294263, -1.94616322869331, 0.766631154276994, 0.116071532794883, -0.0094249948102138, -1.75700434669279, 0.0036210606576855, -0.506859554160035, -0.593178329700087, -2.49446747850741, 0.79627149882876, 0.313731670138587, 2.66063662293421, 1.3602437645134, -0.0683051398364217, 0.0029849606116793, 0.0188340227238714, 0.156009308911535, -0.0128163986020703, -0.306026483328676, -0.138182011250051, -0.492175744525951, 0.168295228347058, -0.0357874469552025]', 20.0); -insert into credit_card_transaction (time, features, amount) values (157672, '[-0.984714008596551, 1.56751031976119, -1.34659360423239, 0.932186496465468, 1.5619731259302, -0.202129516421906, 0.964876317929437, 0.303446779651333, -0.989685608936685, -0.441089866550192, 0.537792017461151, 0.349048521469868, -0.0945585411994336, -0.662439489588188, -0.801901696895235, -0.261812157806986, 1.04597684216332, 0.9804587818583, 1.03748134356874, -0.0838336144950998, 0.081395669810669, 0.447138350637323, -0.0206412258029941, 0.108025054320145, 0.155234851373501, -0.407761236733805, 0.0995427684657036, 0.201292004298201]', 16.1); -insert into credit_card_transaction (time, features, amount) values (157673, '[-0.271252199321979, 0.803480528970401, 0.339312365067873, -0.993036392768877, 0.779804591946232, -0.390229098889444, 0.9326941083428, -0.0824337036130174, 0.342150121047779, -0.811070527239764, -1.41191358715847, 0.304282769781088, 0.299826531694597, -0.190595085177309, -0.910852500493808, -0.6199802179378, -0.283804840994717, -0.246043401456233, 0.174958196440685, 0.0212521699194917, 0.120213411956863, 0.712492547992129, -0.301738269516433, 0.649183995098063, -0.0077483684214828, 0.102924365930774, 0.391400113145998, 0.236470496907201]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157673, '[-0.308966639631638, -1.40872178095524, -0.521433406405505, -1.96452516548817, -0.564035272006543, 1.19137991184367, -1.24775422064385, -2.53898718407234, -0.930550087548313, -0.584813358832481, -0.144109497073928, 0.354564613694285, 0.816924593463184, -0.0839757171361925, -1.08355086812859, 2.24730058482718, -0.76715329599421, -0.355362415127438, -0.141825512813973, 1.49539640097667, -0.788734400135575, 0.784697714610051, -0.592602136549449, -0.293926035081469, 1.1089170315443, -0.111220282199828, -0.146147083718468, 0.108102173061073]', 399.0); -insert into credit_card_transaction (time, features, amount) values (157673, '[-0.2383175921796, 0.551722978569067, -0.721888519755237, -2.40560801327523, 0.323621573194478, -0.943134115400195, 0.328054953996721, 0.138674382541974, -1.3751938628724, 0.0109708633360267, -1.20412977253443, -0.24642176715472, 1.40941626022518, -0.0655490438594682, -0.685958598166706, 1.24115934821103, -0.257649430141542, -1.18147828205379, -0.251127628843804, 0.0673948514172616, 0.582465253570036, 1.64412188320386, -0.107894123892428, 0.555038375233325, -0.581955127130999, -0.227846664554553, 0.337196233986138, 0.239471066939677]', 10.0); -insert into credit_card_transaction (time, features, amount) values (157673, '[2.02733083232336, 0.472540119973513, -2.49909513199218, 0.595279769559177, 0.670424724319215, -1.32398899994942, 0.21240769510333, -0.198721762173749, 0.391219659381951, -1.0064326585289, 1.47347467682044, -0.0723978308964411, -0.848235290020886, -2.19794608656666, 0.480786051529934, 1.09826616855598, 1.44843783671005, 1.96794307367733, -0.283040482073196, -0.183546836461205, 0.118972959031012, 0.473359732833711, -0.0899100621352102, -0.572288530117652, 0.243524799222156, -0.0976006654556805, 0.0106651446114544, -0.0072909786351266]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157674, '[-0.309060267470029, 1.40998804346571, -0.674802194830392, -0.826464566512148, 1.27308883545268, -0.444900952041377, 1.22664047897167, -0.357044211671821, 0.416302982399144, 0.0606290087698471, -0.727247656947094, 0.239219136408626, 1.12149426481706, -1.63690077262252, -0.205240668057125, 0.224180893099813, 0.0642954790335486, -0.352067182983902, -0.186528397092605, 0.396806760393592, -0.452377650507409, -0.826049342792934, 0.0277310671309127, 0.0917732201887042, -0.271723828858603, 0.110899403364912, 0.149591080916801, -0.0226316518603748]', 10.76); -insert into credit_card_transaction (time, features, amount) values (157674, '[1.79012266278276, -0.676921329244653, -1.40738218221979, -0.10049693190564, 0.537654789886719, 1.07062950945947, -0.264393915983108, 0.340203741043811, 0.930112260600053, -0.189151878545155, 0.739739623780943, 1.06863004378843, -0.564679386284994, 0.442783800471179, -0.117090281782435, -0.975382654142485, 0.273966009506599, -1.2301065076826, -0.203450383688819, -0.203481730838543, -0.0408136794039017, 0.0483738927955093, 0.157158489169186, -1.62587796029627, -0.264068945587754, 0.0179205357942158, 0.0054895478935852, -0.072756306716618]', 70.0); -insert into credit_card_transaction (time, features, amount) values (157675, '[-0.999120757496684, 0.33152744973671, 2.37847185055143, -0.704231858794303, -0.137632522636944, 1.35792088902069, -0.245055118411236, 0.484115233576339, 1.36945492230933, -1.06648172069811, -2.4246690433919, 0.33485920584977, 0.397434948615654, -1.49925829613848, -1.9101083786839, -0.156274875845579, -0.141511411827937, -0.110376653386028, 0.675050143296975, 0.112131386868392, -0.219962073864621, -0.145418099079366, -0.446534467167365, 0.116279437710557, 0.563633592063988, 0.70855665509494, 0.175310618175618, 0.109633450314114]', 23.27); -insert into credit_card_transaction (time, features, amount) values (157675, '[2.0304377142877, -1.41477713947346, -0.25903707134831, -1.17903472604184, -0.946317219385446, 1.00061424458798, -1.66715848128407, 0.29955333760075, 0.254010524064565, 0.781880588790689, 0.0481709786595812, 0.474727259731515, 1.72594701531832, -0.984881838997233, -0.0765731306232688, 2.14774777302976, -0.833583330444377, 0.0676312102237355, 0.858257028127041, 0.272345802905228, 0.454295899969593, 1.25694910062995, 0.0132059006657339, -0.280174883787165, -0.270952807161646, -0.0892141912019501, 0.0415328397080597, -0.0311625185996005]', 76.0); -insert into credit_card_transaction (time, features, amount) values (157675, '[2.12264482184131, -0.678740227022123, -1.05568228588984, -0.534485241748948, -0.897008993793866, -1.04365353618049, -0.895160818776703, -0.145750317348732, 0.0778511248864166, 0.0763734628989035, -0.303660247551544, -0.791394485163903, 0.0689112455356252, -2.08011692844464, 0.388627944326622, 1.60905088018795, 1.43918498708263, -0.529993883680797, 0.128261484400098, 0.0239760026349763, 0.246097426609964, 0.800440812696472, 0.109213635295877, -0.113855335450338, -0.169836820298458, -0.0848353024173462, 0.030943893607115, -0.0114638765188567]', 21.99); -insert into credit_card_transaction (time, features, amount) values (157675, '[1.25738607770783, -1.29260115196379, -3.22749020870842, 0.315520354300516, 0.671152232786627, -1.1507446947082, 1.68824376778646, -0.777889908238491, -0.0868015817041932, -0.231069023926174, -0.855760992723037, 0.676351025069804, 0.982964320579347, 0.742552658332368, -0.0877854130292076, -0.890234187740606, -0.236943864219838, -0.501607557726412, 0.167703332569304, 0.825103607664235, 0.55628119504328, 0.750961721329793, -0.642426748823071, 0.624327789779637, 0.673763407883049, 0.388715763678561, -0.191759113813372, -0.0007451054957198]', 484.0); -insert into credit_card_transaction (time, features, amount) values (157677, '[2.20105339451337, -0.963279089455179, -2.79248687914929, -1.93965348419363, 1.97958446680884, 3.13262435263015, -0.844146857732279, 0.695954207281895, -0.634243222529645, 0.808695051449459, 0.0648416225096195, -0.413990889130083, -0.0847463254003369, 0.170565689831317, 0.101520462835394, 0.550523496552585, 0.307036072719545, -1.9955337740532, 0.700393138125186, 0.0301484386094088, 0.0261588158206121, -0.0075976667386555, 0.229173154036864, 0.712063278795965, 0.0236787144634407, -0.258540944938817, -0.0213502786505819, -0.0692189199705032]', 15.27); -insert into credit_card_transaction (time, features, amount) values (157677, '[-1.03468314179644, 1.12458635099361, 0.18547384505549, -0.65481970320812, 0.605563910604064, -1.04087157747382, 1.42362613744374, -1.06360088065318, 1.48186258006072, 1.53581185157729, -0.909805106781413, -1.62689023797206, -2.49061273132976, -0.114108911533506, 1.04740100412106, -0.715824957737676, -0.643625714952924, 0.245933609089612, 0.0205159220166089, 0.0044864241323308, 0.25961802057698, 1.14778729624083, -0.206160246789341, -0.0459455336265481, -0.620283460249351, -0.314296758864627, -1.04463567602418, -0.26698846629468]', 5.35); -insert into credit_card_transaction (time, features, amount) values (157677, '[-2.46602084188543, 0.365723836271079, -2.30764260745798, -0.674368364383094, 1.01115842968562, -0.81897883400823, 1.80355231398438, 0.0620849442454661, -1.22065163483867, -0.79602351024818, -1.66869247696958, 0.349921892681564, 1.18920821934105, 0.988393454596161, -0.559883289196942, -0.203888976718025, -0.217321788687955, -0.440729857765989, 0.264828423235882, -0.525086575607077, 0.176500837880444, 0.733180271609274, -1.25388318491376, 0.276956931686362, 0.852186166428873, 1.02716117049555, 0.227956062865521, -0.532015077707887]', 272.06); -insert into credit_card_transaction (time, features, amount) values (157678, '[1.82186028194341, -0.475662654961392, -2.22583472408642, 0.181785080811274, 0.639870312294077, -0.573706321453177, 0.664033577364905, -0.383928673782837, 0.604239078891329, -0.202434955872931, -1.37575162360916, 0.28451823716913, 0.383417799546334, 0.508343291916738, 0.472608268238342, -0.358855882877338, -0.6248861321501, -0.023829956158792, 0.284247492490685, 0.142566118194225, 0.154674094376264, 0.244923812684508, -0.190888394420315, 0.059833210715731, 0.441620969366864, -0.527119234872603, -0.0433197593798314, -0.0300237462207368]', 169.43); -insert into credit_card_transaction (time, features, amount) values (157678, '[2.31202561817784, -1.43008187190908, -1.20891062947418, -1.61985678933988, -1.07513640536755, -0.531039007752024, -1.10615124517161, -0.13871647842916, -1.05917680067469, 1.60326176406705, -1.48243248764555, -1.51490719220309, -0.643148729886864, -0.196704397908706, -0.0335873360107412, -0.461923055781142, 0.45428201030941, 0.118643480079771, -0.0006470356543341, -0.458251153374536, -0.201594624709316, -0.163630838616283, 0.232024347937327, 0.425256114582135, -0.149498661972579, -0.175277515428491, -0.0056173654975395, -0.048045932013292]', 25.0); -insert into credit_card_transaction (time, features, amount) values (157679, '[2.20112909336745, -0.671994779399452, -1.56060650598055, -1.02066990214565, -0.165324456280594, -0.861499661758035, -0.233625889151165, -0.413477930348158, -0.748462267577397, 0.819564035196897, -0.583569100220292, 0.0252543571183071, 1.67915136623939, -0.274034906742261, 0.232529082197224, 0.904766285315661, -0.0303924449195594, -1.36931320807433, 0.494652766574586, 0.146747338706366, 0.445574837917572, 1.2815932381753, -0.0428471427190114, 0.676814548688191, 0.288769753895877, 0.0376195241325399, -0.0399049520300122, -0.0530318451753298]', 40.0); -insert into credit_card_transaction (time, features, amount) values (157679, '[-0.406861632704899, 1.10220169200469, -0.163043851415343, -0.661329325297498, 1.02786186290888, -0.968687671861143, 0.954720798735252, -0.158791795883965, -0.249384945471057, -0.781910763051732, -0.592107956210078, -0.6143390453661, -0.278095878217383, -0.957396974501664, 0.508244372519525, 0.481660377253925, 0.308440184253551, 0.499830392681288, -0.577671483960768, 0.059481737552085, 0.155641381215255, 0.498982403643476, -0.32859453268426, 0.688342290723948, 0.404862498063351, 0.673761844550901, 0.0536463672545795, 0.10084281463515]', 1.5); -insert into credit_card_transaction (time, features, amount) values (157680, '[-0.365258778754858, 1.09728199885184, -0.372540084111885, -1.06162026009461, 0.797928615474386, -0.200416513681132, 0.868955043094719, 0.0573705218747252, 0.238613491055849, 0.385692613538063, -0.251298058189558, 0.162960457538497, -0.489465178570015, 0.222562619918289, -0.927959870474759, 0.408291156254974, -1.0368217693522, 0.141706729388943, 0.555428694950459, 0.220457608847449, -0.34902776292063, -0.750426240223662, -0.0470001451392357, -1.12898625261378, -0.292612186439175, 0.199217963684531, 0.454366054245722, 0.193341298948532]', 11.99); -insert into credit_card_transaction (time, features, amount) values (157680, '[1.98748459885835, -0.434937303357228, -0.43341360311259, -0.0383420335854398, -0.523485718247296, -0.192562136340337, -0.637596396099461, 0.115756207070385, 1.14372335228563, -0.0343432858817313, 0.562351696642149, 0.929150227432415, -0.238828896944658, 0.18321496789006, 0.0899702366987793, 0.480247175915945, -0.821162619106004, 0.299516950287604, 0.403448718212386, -0.226331055578317, -0.169646031086914, -0.366638281020488, 0.342715598198295, -0.501028277311011, -0.502246487965202, -0.271937122006483, 0.0073283650548859, -0.0524708628887952]', 0.85); -insert into credit_card_transaction (time, features, amount) values (157681, '[2.08335683194978, -0.760338518270083, -0.371132090587612, -0.630822813589613, -1.3671809627947, -1.70339374271083, -0.508651960074439, -0.336673061775539, -0.365120189346657, 0.747818588413896, 0.260146545325104, -0.0770551286316976, 0.0642745890328091, -0.0940110683821129, 0.212964182981821, 0.90547226398528, 0.465813899807659, -2.16925578439858, 0.412732159942784, -0.0241646354436584, -0.185053891904558, -0.649661538271287, 0.579829694705514, 0.87068513905863, -0.681755054997547, -0.748243257534186, -0.0151101008788047, -0.0312777487143151]', 31.95); -insert into credit_card_transaction (time, features, amount) values (157682, '[0.0548147668971734, 0.825636497730477, 0.221687065106836, -0.61480115061977, 0.43311391019309, -1.05478616463575, 0.971882266465343, -0.168226855354062, 0.0452097219706133, -0.394859199061759, -1.14789246664647, -0.18925791226864, -0.487394675747123, 0.207573131665409, -0.33511851176873, -0.0257877595878572, -0.432272753596909, -0.636294099209896, -0.0246573610170176, -0.0684436629534681, -0.276508015776315, -0.641373787315523, 0.0566548487015433, -0.131552031704074, -0.487460608298759, 0.149207347522262, 0.243716617644422, 0.094767943885897]', 2.69); -insert into credit_card_transaction (time, features, amount) values (157682, '[1.97815112277616, -0.24728564812647, -2.13688593485985, 0.0920593681792395, 0.891761011954678, -0.0849775237016036, 0.444558484459444, -0.197438271892641, 0.0650292261484287, 0.216567992098539, 0.237830701218962, 1.06522121128682, 0.540828413389754, 0.450929826651405, -1.05398962261634, -0.192009139397746, -0.608695084413949, -0.205417182587548, 0.701731255892005, -0.0079903924132831, 0.0105629178345177, 0.0626463306121614, -0.0546621656227497, -0.034918420975161, 0.253965989808443, 0.552405424313774, -0.11182523678573, -0.0759104676085585]', 69.95); -insert into credit_card_transaction (time, features, amount) values (157682, '[1.98583259518274, -0.259051352902079, -0.692348311932495, 0.361386052723655, -0.430187227578805, -0.941094018329212, -0.108181136733131, -0.291570204601908, 0.69826882035104, 0.0005145104525627, -0.626561186482978, 0.969559024312258, 1.25942662543269, -0.181713860593075, 0.175809847585325, 0.0772102693876024, -0.46290452188066, -0.531296305237457, -0.100887214246555, -0.0762455840461724, 0.0250749381393894, 0.243929235310853, 0.184098376326277, 0.123152522278537, -0.233393907004938, 0.548058544265512, -0.0537910669822665, -0.0496008488653154]', 31.35); -insert into credit_card_transaction (time, features, amount) values (157683, '[-3.16328184013955, 3.30039052844423, -2.77108528214923, -0.774925331364977, -0.12228461688672, 1.72993972423332, -3.94206270118423, -8.40276042188811, -0.722225194451139, -1.26939693037988, -0.617674334146216, 1.25513464917228, -1.01420387800534, 2.42874856807674, -0.349008499899204, 0.725585693395977, -0.123937983598227, 1.15485998360559, 0.0138188905995267, 1.58077264938073, -1.86600751904257, 1.82392818504639, 0.800225135943605, -0.27872286542676, -0.740382785431581, -0.235398596748473, 0.458054920068973, 0.375028578541356]', 0.77); -insert into credit_card_transaction (time, features, amount) values (157683, '[2.15141771776466, -0.572687933540587, -2.19490001110557, -2.27449752038785, 0.235487027659246, -1.14793810822466, 0.205527924172439, -0.407403624405586, 1.92451536766178, -1.18073467514183, -1.01956015373171, 0.645776862256435, 0.38041217529306, 0.484741927744875, 1.63248818661826, -0.892661783497144, -0.497274476588846, 0.385455342637485, 1.12514563405842, -0.092617328475195, 0.241415021656626, 0.884928358638999, -0.14581791913272, 0.147068591709136, 0.552138765196511, -0.605838871616567, 0.0136012174868917, -0.0527951405655972]', 33.54); -insert into credit_card_transaction (time, features, amount) values (157684, '[-0.768054680867553, 0.0544425442061756, 1.11236705232835, -2.31840678155671, -0.717744301700017, -0.0757738689131079, -0.35279141220918, 0.115016295618592, -2.66113341120407, 1.18682487069941, 0.425232653218657, -0.414970093981548, 0.759419015772579, -0.301353667246672, -0.647906344331232, -0.785350288542679, 0.565545413217258, 0.56250487331489, 1.10099706167775, -0.231786203981882, -0.102711243122863, 0.100135871623601, -0.428667642712239, -0.386025736665794, 0.501307542474657, 0.0559295274635997, -0.497363476696936, -0.240561050421874]', 10.0); -insert into credit_card_transaction (time, features, amount) values (157684, '[-0.831138228215365, 1.14852007511413, 0.571786141489337, 0.178836874627494, 1.57174575602333, -1.24903023653625, 1.66338741423807, -0.366841436620378, -1.29988414641891, -0.607598854896702, -0.897159907506269, -0.239456854267468, -0.104188317524345, 0.698709530477251, -0.004005074812894, -0.532818716750015, -0.390070859711166, -0.327872503534486, -0.357254136361973, -0.0332765109940069, 0.153395034330664, 0.343013699027422, -0.597100448017311, -0.076525364097104, 1.27645122145004, -0.342032665942805, -0.0129367764806701, 0.0433930007748864]', 9.9); -insert into credit_card_transaction (time, features, amount) values (157684, '[-0.0250774700344481, 0.851425305288206, -0.946901059815186, -0.0645370016103051, 0.335786276738546, -0.541042636445767, 0.29537895482137, 0.48269266514075, -0.0008526268067678, -0.953783465388788, -0.0052319131367756, -0.472561116629127, -2.14555664892262, -0.375987891069494, -1.20760673911253, 0.179255438421801, 0.894662839785164, 0.994980110131881, 0.567165265951081, -0.326458078516148, 0.21987387570077, 0.666558953715943, -0.152096474022838, -0.535522341965088, -0.444908437928033, 0.69131410042931, -0.0687392946558427, 0.0064094603276568]', 12.36); -insert into credit_card_transaction (time, features, amount) values (157687, '[-0.370194207833387, 1.27909213989218, 0.945288137363863, 2.83067592394674, 1.37941087888421, 1.16744982708709, 0.857187084483609, 0.27411306059047, -1.79202538449822, 0.861824140274844, -0.528946980317489, -0.26900603137309, -0.522116760445392, 0.164956595912568, -2.2372637814448, 0.613902617378961, -0.844956908419263, 0.454526026728535, -0.429974301437446, -0.087295194272989, 0.179749206194917, 0.520532003388364, -0.304826470346445, 0.18575176099613, 0.0110417580682294, 0.118954084264323, 0.117320690806495, 0.151824908667014]', 18.9); -insert into credit_card_transaction (time, features, amount) values (157688, '[1.90351822823552, -0.174347941074012, -1.9565640939925, 0.403944756157283, 0.281224002868475, -0.787302383100343, 0.139341069407735, -0.175846993248174, 1.0817296429073, -0.922491702073184, -0.718960420910587, -0.0596976599110652, -0.529626021162883, -1.51300169992354, -8.66407752302123e-05, 0.141296953794059, 1.12224317650492, 0.246586305806003, 0.171273375756559, -0.0253883487909423, -0.234627900521977, -0.632259699414274, 0.135908874516382, 0.438758782112635, -0.0597170130518357, -0.11831946976014, -0.0267978184381739, -0.0013352219699531]', 82.61); -insert into credit_card_transaction (time, features, amount) values (157688, '[1.87799654523266, -0.473803808836681, -0.66857116800568, 0.298629813234874, -0.278078652370265, -0.121642974434615, -0.373670479726424, -0.102155331636264, 1.03035871665514, -0.184689214484112, -0.848368220097319, 1.0418687554502, 1.76631717017878, -0.331297315294243, 0.901283988764296, 0.337129265866278, -0.89284775594053, 0.251560821698716, -0.28689677835906, 0.0758677742036345, 0.252609760104486, 0.769788906716097, 0.0535174484528977, 0.531526164267654, -0.0583329769790265, -0.274533806722435, 0.0240981308406351, -0.0156128519274166]', 84.25); -insert into credit_card_transaction (time, features, amount) values (157688, '[-0.497431419039788, 0.678158594150144, -1.52093761765639, -1.00057109348182, -0.741601751122412, -0.8880497645695, 0.653593600814509, 0.429175601746033, -2.04751794857141, 0.220195098849719, 0.198467265200732, 0.287960706676123, -0.505580363749793, 1.28022325503367, -1.34127503651789, -1.89669886757904, 0.413207003209608, 1.27917851518974, -0.162331104460548, -0.813198949777903, -0.0048115234563083, 0.276262681274769, 0.0646805409594056, 0.0510604957659754, -0.429059736311705, 0.750026861225639, -0.282958609902457, -0.101002720882118]', 126.0); -insert into credit_card_transaction (time, features, amount) values (157690, '[2.10569868219245, -0.0967341893236175, -1.64637823073991, -0.0712262205681997, 0.753233496880488, 0.162771060999685, 0.0411018812322155, -0.055833507931254, 0.254505475721204, 0.21895283587267, 0.0753605084485017, 1.04057323138976, 0.77393034560624, 0.276187834182368, -0.601383565555542, 0.405819598685524, -0.988483696543147, -0.0579625329510764, 0.84989447180861, -0.109865865366591, -0.30743447433671, -0.794361214071003, 0.223205182004414, -0.335628695742678, -0.146090365282371, 0.209131844522297, -0.0771602400682416, -0.0727125420356728]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157691, '[-3.30902736815795, -0.953121412523735, -0.448618081451785, 3.5023951721798, 2.14139189337699, -1.37620845509008, 0.488301380445685, -0.265554628402911, -0.939523909408261, 1.80528296431614, -1.43812541897342, -0.492360425384969, -0.255901876217212, 0.161015764691412, -1.2096456937157, 0.788597852789847, -0.889976251973906, -0.704400025320373, -1.42680914839219, -1.07671823617417, -0.281753058007557, -0.158238551218931, -0.379411208693719, 0.0446265889886949, -1.26913373260076, -0.572879453061116, -1.16291772745959, -0.0036116114707116]', 13.25); -insert into credit_card_transaction (time, features, amount) values (157691, '[-0.0126004838572641, 0.73265898823155, 0.277481257823411, -0.555236383221767, 0.386345733850758, -1.18033219686887, 0.940785865562634, -0.165603213793502, 0.0611968178410471, -0.390086281953597, -1.03551882213013, -0.217852090642622, -0.669022442977876, 0.251836072596179, -0.326387728710055, -0.0642738287234888, -0.365673685253362, -0.663584046836528, -0.0835716088750195, -0.0525552170138068, -0.258908609117544, -0.629871016249881, 0.105406562237157, 0.019805478196573, -0.508187704649129, 0.139853899653454, 0.238327664123373, 0.0977955842172623]', 8.99); -insert into credit_card_transaction (time, features, amount) values (157691, '[0.0072074549137557, 0.506412857381131, -1.187777952089, -1.7201221079315, 2.95558446318271, 3.384701432179, 0.323179659950747, 0.927407014119902, -0.163996549189058, -0.386041544504147, -0.199912764343157, 0.0340563096040058, -0.373073285963966, 0.355618969599158, 0.0425347460166415, -0.155055439291267, -0.482053766676739, -0.840693748107076, -0.206669805212565, 0.0358000410316673, -0.26221323015063, -0.718377299056042, 0.119794752199664, 0.688138959149158, -0.457919325901241, 0.161878548498329, 0.26346451928513, 0.0910398510019692]', 3.99); -insert into credit_card_transaction (time, features, amount) values (157692, '[-0.183148622511039, 0.422058503815131, -0.516862849799115, -0.383962158478075, 0.151738777463743, -0.822269913840261, 1.65138899283605, -0.276715199828938, 0.211899129402947, -1.75552713758327, -0.737879873289243, -0.0095584536728181, 0.0745717919974543, -1.75412351984956, -0.570204375017391, 0.116325118786952, 0.993393888293093, 0.300789476296047, -0.0874035566704642, 0.294071528076684, -0.073486376957242, -0.332171784408773, 0.354501767760105, -0.25990384183988, -0.208296139769667, -0.162983285771797, 0.0041081635285877, 0.0895003573280478]', 199.84); -insert into credit_card_transaction (time, features, amount) values (157693, '[1.91233520948932, -0.324378484828003, 0.164227910469996, 0.734400107600484, -1.19095366311683, -1.11349783853967, -0.524113727540421, -0.167828630380022, 1.2869620015841, -0.190254858100758, -0.0525446793200477, 1.20689500909608, 0.759856854735814, -0.303850812650683, 0.320556360171216, -0.225328133898422, -0.218471042023068, -0.193916287281662, -0.575815821194575, -0.199342982001773, 0.261943335858652, 1.04885485994248, 0.21988385835477, 0.978375380296514, -0.189089862695267, -0.273237983507367, 0.0481668651611472, -0.0254678895942394]', 9.99); -insert into credit_card_transaction (time, features, amount) values (157693, '[0.125100991330419, 0.950423596874578, -1.17866956423642, -0.172309894546629, 0.327005313828198, -0.908479920173051, 0.537657262722291, 0.304716455930898, -0.292246357853814, -0.95961065030589, 0.625694749541833, 0.0958006427745616, -0.765713934822204, -0.186833306118324, 0.0565127869880954, 0.539591403875453, 0.262691903845127, 1.419044357893, 0.155611662665759, -0.199875566720641, 0.369074488441783, 0.935643468552348, -0.0567391482100247, -0.430663423295707, -0.269341650630469, -0.148048808969989, -0.0892946229079656, -0.0593834545086696]', 42.81); -insert into credit_card_transaction (time, features, amount) values (157694, '[1.8824171634852, 0.28181077542448, -0.658378959822149, 3.77873271941921, 0.289269831813546, 0.33174689991353, -0.0824723599738074, 0.150085705177846, -0.617053992964987, 1.59836123512556, -0.36930754539064, -0.42565261984391, -1.83244552615348, 0.50593257542553, -2.02303895760946, 0.814524675848935, -0.776755179203492, 0.278722612394197, -0.924761156263669, -0.390652969232265, 0.0891931321422175, 0.318661261565337, 0.0474246692619383, -0.385665076256504, 0.0870804730004726, 0.102833912486932, -0.0422883043322641, -0.0670574842254138]', 9.85); -insert into credit_card_transaction (time, features, amount) values (157695, '[-2.80215418212591, -2.7869047683594, 3.05095292866455, 5.77386384485884, 0.543900927419285, 0.991193080329851, -1.06331364091894, 0.337127485308067, 0.211592026075768, 1.36870691945478, -2.00112935232413, -0.515544643619281, -0.163465836607423, -1.43403075730352, -0.880210876288146, -0.35056250383487, 0.518871086612674, 0.574731152620137, 1.63838276079299, 0.25950095398015, 0.0675068180942435, 1.0299061746425, 1.43175029691381, 0.0626079452730134, -0.145390386130068, 0.560129173734992, 0.116706439391599, 0.0672966499526748]', 225.11); -insert into credit_card_transaction (time, features, amount) values (157695, '[-1.20052857055263, 2.06956117066816, 1.54249848003991, 4.06951578807093, 1.25860204261309, 2.03720406920658, 0.552052338677142, -3.01239496262701, -1.31567440802053, 2.3349350253327, -1.34324328146888, -0.645751421787565, 0.628918275042762, -0.762605829356297, -0.0092085669427935, -0.861022299008366, 0.22885864455477, -0.0800248266179748, 1.61102522817546, -0.17411614573861, 2.20908849297382, -0.27551614012747, -0.186757237077152, 0.280788458678256, 0.6167612575981, 0.569937993867196, -0.631744374284451, -0.61848721961052]', 26.47); -insert into credit_card_transaction (time, features, amount) values (157695, '[-0.747566889023111, -0.295613044590678, 0.882569257490564, -0.706035712156273, 0.821425378758939, -0.590230373512158, -0.114434501357268, 0.112892588435563, 0.234506406967808, -0.313818526216938, 0.403412207573683, 0.695627020972726, -0.0336128745771185, 0.0433901711592438, -0.62721702731617, 0.63183043531218, -0.967881890778821, 0.163616578316934, 0.129621126114372, -0.23752482801854, -0.08164455039653, -0.216467221982534, 0.174573672927888, -0.390367704142342, -1.56236256646698, 0.0477902022226219, 0.153212355226033, 0.238237867403128]', 28.98); -insert into credit_card_transaction (time, features, amount) values (157696, '[2.06417245105617, 0.0262741413560445, -1.03884773307114, 0.4079913068747, -0.057143436448956, -1.19535537979282, 0.25232488558759, -0.392823157803556, 0.387873931111568, 0.0440001964101087, -0.560664490661123, 0.979468251405491, 1.07381064942554, 0.0744500547386839, -0.0717344300594716, -0.155365494320654, -0.34265608761729, -0.996828203769396, 0.136225708011739, -0.161735394712951, -0.277599973794466, -0.61413263534856, 0.329974491975154, 0.0739573445065143, -0.265017247208815, 0.192089639971415, -0.0639380514763603, -0.0578317776844607]', 0.89); -insert into credit_card_transaction (time, features, amount) values (157696, '[2.18011199902051, -0.967724081051841, -0.748450150433237, -0.480115308871446, -1.02003401418616, -0.78621548538612, -0.702128549715161, -0.149157424291228, 0.460352447510598, 0.570241443648345, -1.39586858789816, -0.45004450292577, -0.878760249058134, -0.570342484716198, -1.87734640083947, 0.102914335800314, 0.981895667468984, -2.11510668706233, 1.34123896003801, -0.156751045388834, -0.180766077125796, -0.228780803673372, 0.253092159972917, 0.0459570283641028, -0.0770882699502772, -0.322389684373911, -0.0041442743389422, -0.0617400328564477]', 0.2); -insert into credit_card_transaction (time, features, amount) values (157696, '[-1.29366289121131, 0.587144129527716, -1.35042368691883, 0.648442940807596, 1.89618071818851, -1.08198367652383, 1.63132894798224, -0.346551603364527, -0.14479418821806, -0.39343575126975, -0.791160942723461, -0.358248354941365, -0.315744544147362, -1.28862979086232, -0.746758716501068, -0.26220060990532, 0.764263179280418, 0.208719689162283, -0.547925953517981, -0.124505503733382, -0.0166214136605226, 0.540370064764475, 0.357230254063475, 0.540021236971326, -0.25432266022078, -0.741160901511905, -0.23563190886077, -0.0223299672875634]', 63.63); -insert into credit_card_transaction (time, features, amount) values (157696, '[1.93841191654503, -0.0320575662446708, -1.67337056033162, 1.45690097664205, 0.202849628664248, -1.25844508173853, 0.621296659079062, -0.371486643161649, 0.430576415026785, 0.288463450609331, -1.27738247303727, -0.511866166776465, -1.79594635881729, 0.847395927243455, -0.390959755352812, -0.604372103063895, -0.0900317558060284, -0.374819511558848, -0.160802636804536, -0.292130069530574, 0.0574357532573195, 0.1992480283501, -0.0333390889117323, 0.0121749010430797, 0.401185168579891, -0.495352328221495, -0.0374353128509507, -0.0559118612493898]', 59.0); -insert into credit_card_transaction (time, features, amount) values (157696, '[1.33473632275155, -1.58763016713364, -1.02569410650842, 0.25379149555934, -0.60670918266514, 0.418695737500983, -0.323887159554186, 0.112219099472646, 0.830097954281041, 0.0616573781019407, 0.485783072472291, 0.63753336878135, 0.0017892716595311, 0.206937164805428, 0.370246493890324, 0.887087221608036, -1.00079171386902, 0.749801976115915, -0.0851027861020506, 0.552745197711853, 0.405513593254625, 0.450194208084305, -0.134891957970788, 0.283332471483262, -0.451711809042609, 0.595549365392638, -0.10862618303707, 0.0028521698388558]', 352.32); -insert into credit_card_transaction (time, features, amount) values (157696, '[2.04927003795927, 0.0645459871560661, -1.78718097904547, 0.253351380515144, 0.534806548058547, -0.440764642262327, 0.0391582806908901, -0.0434188425893922, 0.333500167462273, -0.19235193646676, 0.834973459983887, 0.467074741710023, -0.533356824572028, -0.551618580822264, -0.418262060509893, 0.604388127883473, 0.172301639328543, 0.328836269841847, 0.431394192637855, -0.174735227201026, -0.334626914625222, -0.918488216701021, 0.306889095554294, 0.241179411844752, -0.27649559602302, 0.170119700673963, -0.070256665391431, -0.0442543947274936]', 0.89); -insert into credit_card_transaction (time, features, amount) values (157697, '[2.24170373812058, -1.52863710501241, -3.4612833931453, -2.5600712995897, 1.81676128890144, 2.91799989848321, -0.781818025309443, 0.494429218049466, -1.97660239439925, 1.66089819522385, -0.231850586381931, -0.820594427585329, 0.104303441874373, 0.250024620372057, -0.353087035685302, -1.36766811713977, 0.720521730222131, -0.58281455413751, -0.089708244745716, -0.271189305390558, -0.0092914716432653, 0.291892348510361, -0.0199695342571815, 0.73671683485852, 0.402799228519784, 0.125049499438836, -0.0375678278414892, -0.0730665772868435]', 73.98); -insert into credit_card_transaction (time, features, amount) values (157697, '[1.86144855003728, -0.501020929125723, 0.0549596879548766, 1.40273427561333, -0.999425755305492, -0.268013523351534, -0.820440233388664, 0.164347168969064, 1.48562432407977, 0.188318603823692, -1.46196729472281, -0.727340119860169, -1.79644608778964, 0.170632510266604, 0.871014666036483, 0.704854834050186, -0.709423486621322, 0.556651276208876, -0.612475852108047, -0.29092200430964, 0.0433333602301394, 0.114506287833258, 0.249650990037826, -0.207080312716461, -0.400872871230871, -0.745224754823563, 0.0580520191097033, -0.018903233862605]', 45.0); -insert into credit_card_transaction (time, features, amount) values (157699, '[2.06595479339357, 0.0258352306608864, -1.04936762856547, 0.402022192854845, -0.0445321214318404, -1.18081073680204, 0.252006807035553, -0.391389697539309, 0.389111429711548, 0.043941196376033, -0.58271399489019, 0.972864564057108, 1.08150507818577, 0.0722835449537861, -0.0702447135701681, -0.148147453356016, -0.352031438005429, -0.98898269971448, 0.145730000014999, -0.160706986392169, -0.27922424291845, -0.618519771489969, 0.326810791699705, 0.0487322437381688, -0.261533481723199, 0.193646095162812, -0.0639498189254104, -0.0580810858959237]', 0.89); -insert into credit_card_transaction (time, features, amount) values (157699, '[-0.961170410577063, 1.46309028803722, 1.55268031820307, 0.706805935270864, 0.0646371213022817, 0.387172836699019, 0.112217299785725, 0.612269678541625, -0.534185124288492, -0.56721604421424, -1.15682279530021, 0.301710940783101, 0.835034758440593, 0.0899018287136239, 0.778124678165192, 0.0454175960602848, -0.207433175509048, 0.161854416392188, 0.750948178679016, 0.135036325322671, -0.207667716509745, -0.553304877168348, -0.190083724179341, 0.531734095918253, 0.422462340667078, -0.663253222126027, 0.234961328071738, 0.0923940242556723]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157699, '[-0.279928388173511, 0.619999449424073, 1.0263955819205, -0.774108084310589, 0.755108665204555, 0.163028610367474, 0.838642625359413, -0.290017832467131, 0.653121895901266, -0.718816860546924, -2.02594691432994, 0.208482450565325, 0.984389432875468, -0.768979064259398, -0.574619970502369, -0.229136135852393, -0.855672775632481, 0.332483267000258, 0.299359255306081, -0.0113001160687074, 0.18462568676788, 0.976093228855646, -0.540673687770616, -0.927323527217863, 0.144865132719321, -0.128357957598767, -0.116259451364477, -0.0727088097768788]', 11.85); -insert into credit_card_transaction (time, features, amount) values (157699, '[2.09160914546749, -1.00995910849633, 0.170358701536119, -0.511143276446138, -1.31283938833623, 0.213132734141014, -1.50670033281606, 0.123578973573852, 0.236397032186797, 0.774325899300191, -0.952294583534851, 0.487494504679989, 1.7394447803671, -0.766720773362034, 1.05419985509144, -0.617592834846138, -0.644177350116239, 1.58405288384592, -1.34422109876055, -0.474510581153769, -0.134397849745711, 0.250838889663636, 0.355760431002774, 0.633134365127095, -0.643505559237741, 0.587137754355221, 0.030688734760933, -0.0222320919878286]', 7.42); -insert into credit_card_transaction (time, features, amount) values (157699, '[0.445502455063417, 0.441206899343513, -1.79335577647796, -1.40354797680064, 2.47354163318364, 3.91100368654346, -1.21346890922391, -1.76790562414076, -0.302014202034587, -0.970749621933665, -0.16486069812016, 0.467767686109843, -0.577183678525144, 0.919730943022661, 0.101808491480805, 0.139439772650569, -0.379625121407643, -0.955146047631811, -0.578596722466404, 0.512102064758497, -1.57179172519841, -0.594307856310312, 0.221080387498554, 0.683637229979168, 0.444506583525832, 0.240451151026066, -0.0241958254843618, 0.132578177675354]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157700, '[-0.778314826642336, 1.72993024502851, -0.258396338933288, -0.194311254990339, -0.235396433746089, -1.46162203083859, 0.280118106071631, -1.5696202959191, -0.292711537286667, -0.400571359085391, -0.0960459829911923, 1.16535437263189, 1.05619839496666, 0.609733662953219, 0.185129994042777, -0.6273019192378, 0.0783806681844065, -0.212377280792267, -0.342990248790862, -0.413938503064859, 2.01081816497982, 1.07253788522846, 0.245392046393652, 0.974014134536094, -0.806681699383522, -0.266518540670567, 0.463797042020522, 0.28760665923028]', 3.98); -insert into credit_card_transaction (time, features, amount) values (157700, '[-0.78919879993444, -0.416736346487244, -0.198520979218314, 0.295601470193659, 1.62379745452543, -1.43349595465227, 0.838249395999532, -0.295617070261255, -0.400770095019371, -0.528221660735976, -0.391921175426066, 0.687325631876845, 0.908058193895269, 0.466426331278157, 0.520970267329246, -1.262946574866, 0.0951342866481577, -0.213945184783983, 0.795968265045825, 0.515790162774528, 0.439677766775589, 0.966468728902323, 0.33650485198642, 1.12358219507074, -0.408354231592567, -0.547478581691296, 0.181221703758972, 0.269179293032383]', 107.82); -insert into credit_card_transaction (time, features, amount) values (157700, '[0.0011514535944527, 0.818830970460008, -0.519976151425248, -0.699751825899174, 1.47175169238694, 0.677274378599747, 0.67065343686339, 0.380221061881251, 0.0491134954626667, -0.956094893359527, -0.116736608730502, -0.224154958305256, -0.757007880549536, -0.786365964447261, 0.656533441434471, -0.575715704100711, 1.29931824790608, -1.57553761614036, -1.37576763279459, -0.125113324344339, -0.260968811700973, -0.527005321306448, 0.199131813851019, -0.46956343661467, -0.676830470551731, 0.21234956953088, 0.270672353221625, 0.0717518660745382]', 3.58); -insert into credit_card_transaction (time, features, amount) values (157702, '[1.43561776429555, -1.3229850129845, -0.755773567009584, 0.581365373818886, -1.03826421150534, -0.639218106554318, -0.17035808527814, -0.133353080917126, 1.49274302682945, -0.311605000441295, -1.08763506331906, -0.0711767339866791, -0.66714000262842, 0.248882390087451, 1.21212917781835, 0.281200129825784, -0.662662353415927, 0.587721112530432, -0.363962529740911, 0.314137403959905, 0.385398648755634, 0.600442790365861, -0.143226882583135, -0.117903415977569, -0.182467443650411, -0.583288776218958, -0.002304274966521, 0.0153667326756732]', 300.0); -insert into credit_card_transaction (time, features, amount) values (157704, '[1.7385205854353, -0.892089846408635, -0.61171539902473, 0.214020009687275, -0.64809072813626, -0.130109607815714, -0.459933969339803, -0.0454743695308479, 1.40011554525562, -0.302020291231469, -0.966504956944146, 0.74423598986218, 0.829572661663642, -0.337060700238174, 0.50280920824159, 0.143860563204753, -0.555491381748058, 0.14197372420986, -0.118810916136672, 0.156232377859632, 0.25915801212865, 0.676207405921907, 0.0247114373201877, 0.730089253803407, -0.16529347165433, 0.0790929660675291, -0.0114539596994003, -0.0099156687582736]', 150.0); -insert into credit_card_transaction (time, features, amount) values (157704, '[1.99804907676376, -0.416684210336494, -0.365259376344715, 0.377805253207431, -0.534316282093149, -0.144293305533666, -0.665363366175666, 0.0025426026534573, 1.16150414882564, -0.0183673557570947, -0.93648091444336, 0.635485381423196, 0.79948513793616, -0.402962625971965, 0.3256125017865, 0.328423299664652, -0.558640380306779, -0.0319153926594563, -0.242588483289539, -0.116674521623804, 0.160746311744555, 0.676485992930321, 0.185419554057296, 0.807383586807175, -0.235660871090008, 0.533024124211108, -0.0203608390533247, -0.0384520533541354]', 11.5); -insert into credit_card_transaction (time, features, amount) values (157704, '[-0.426755527272792, 0.87375703451161, -0.370965525053918, -0.589003899281591, 0.724109827828868, -0.723269029563194, 0.874320693865869, -0.13848863585707, 0.182387427672555, 0.343861184576477, 0.391221322670837, -0.0387654246370595, -1.08177341278863, 0.641555855325174, -0.0087081119607021, -0.22147022619051, -0.783225973136488, 0.773809334859463, 0.412408848820866, -0.125923283487632, 0.34690611903494, 1.38592177108063, -0.0552657054979906, -0.38776313500652, -0.846908272920435, -0.283997506332344, -0.19544936037924, -0.220173256802794]', 0.74); -insert into credit_card_transaction (time, features, amount) values (157704, '[2.0651932618778, -1.1133051640027, -0.758239557258063, -0.603335436981097, -0.83828658474467, 0.201902871002653, -1.10136637624334, 0.181306293096023, -0.0379267757307635, 1.02569626044458, 0.0044176153622693, -0.121250948052904, -0.808075289134137, 0.158309806432348, -0.172617925133499, -0.800373864732649, -0.578523463849313, 2.01955161007762, -0.521029078351097, -0.565877911842106, -0.236844112114906, -0.226516812459746, 0.238495073906172, 0.302224807766046, -0.417963928207025, 0.604016645213068, -0.0377025351992958, -0.0518885790613157]', 36.0); -insert into credit_card_transaction (time, features, amount) values (157704, '[-0.103933265119944, 1.209354932723, -0.184922929079553, -0.372333131208527, 0.459848115677374, -1.58685114955114, 1.19871437637383, -0.450368832499871, -0.0750559885514598, -0.958610109709599, -0.0902023786748899, 0.0879390448586052, 0.259108626471398, -0.98088058817972, 0.389091016453283, 0.0617705455616881, 0.393985628250334, 0.429674156855048, -0.787203815563598, -0.186923315765165, 0.337512051836843, 0.999047912364985, -0.236832940804817, 0.402073846782658, -0.0679695428062781, -0.231883308856569, -0.190325710529559, 0.0610671054534179]', 18.0); -insert into credit_card_transaction (time, features, amount) values (157705, '[-4.31903759961312, -4.70952140601699, 1.12861385827668, 0.165809424471442, 4.34356761635449, -1.10312534185627, -1.32330525494534, 0.129066260018699, 1.13256615166833, -0.750491642893958, -0.29813060910041, 0.0749898227300266, -0.394691095355937, -2.08329138349009, -1.57193690191482, 0.601866778905089, -0.100920505177039, 1.28916411282091, 0.0480174010419019, 0.7866861825676, 0.196861701589146, 0.36435493800736, 0.0714996313938601, -0.362333540144417, 1.1795929661975, 0.7653815873745, -0.79849911820282, 0.471025790525291]', 207.2); -insert into credit_card_transaction (time, features, amount) values (157706, '[-0.172747946874229, -0.686847233914274, 1.0979329031162, -2.7476623710753, -0.710979464903696, 0.0741178072164428, -0.409460945238638, 0.174863203750307, -2.10976277740161, 0.867873859150692, 0.361301831485438, -0.93862112277913, -0.549630150619263, -0.276569335761426, -1.03611097637925, -0.265241679910156, 0.187724736737298, 0.717054061915971, -0.126908933986245, -0.298806242899799, 0.0046350612985474, 0.292609682787268, 0.0099350907963515, 0.657560582393858, -0.425619050528873, -0.266950985248151, 0.147780630978695, 0.157570204601165]', 43.0); -insert into credit_card_transaction (time, features, amount) values (157707, '[-1.15127124158764, 1.66458167394539, 0.0036623437285402, 0.281059733350196, 0.766176110074641, -0.974487004641719, 1.3108231084057, -0.110230358770562, -0.34067950817555, 0.0981539401246805, -1.04580893562627, 0.0807023459056578, -0.177251947197928, 0.279813333502844, -0.71955623944703, -0.741838638083559, -0.106741312707914, -0.592163145852269, -0.330201816277138, -0.0049480675168586, -0.0506040216688384, 0.10542159431311, -0.590988271766406, -0.0094311608269884, 1.4745663927463, -0.377401698361993, -0.309128908701368, -0.324334208567247]', 8.97); -insert into credit_card_transaction (time, features, amount) values (157708, '[1.97527625198455, -0.846033656631418, 0.384854217421799, 0.461664204970547, -1.1624911894556, 0.570286567300143, -1.42871781139834, 0.311990905828702, 2.22191319028075, -0.210037546057482, -1.99492577390665, 0.343047323309382, 0.12381058831076, -0.997185684025171, -0.364299356008724, 0.405655211477404, -0.437684380170837, 0.226548018695815, 0.126005918082996, -0.201311797992715, 0.0826914072643253, 0.677138702809898, 0.136258248725671, -0.641000214449053, -0.389197549764031, 0.738866747537939, 0.0292859102214093, -0.0447056383655524]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157708, '[2.06184246253878, -0.307976232912722, -2.78654770060288, -0.777438171502785, 2.49992452962194, 3.16343650481725, -0.400265931460217, 0.715920455141033, 0.448457069112648, 0.0332289061611847, 0.0620942339066804, 0.284944315835478, -0.144093725987975, 0.69457080684155, 1.16583098500761, -0.286162234455405, -0.586906588784058, -0.180099963058657, -0.35555288268917, -0.171442519139442, 0.241950060121122, 0.745452959879616, 0.0403287392996927, 0.737381238667803, 0.30397657803223, -0.0875596152439227, -0.0006145205229113, -0.0654411548550868]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157709, '[1.39734563916074, -1.49666653917257, -0.926199928524948, 0.525728520799198, -0.850909798735179, -0.138555206704582, -0.26685816855018, -0.023938809782132, 1.17816731927994, -0.0525822713403886, -1.18375816544728, -0.402384860858606, -0.74122517503701, 0.178581124984375, 1.07883934888212, 0.703397934828545, -0.685042233601466, 0.380328547428183, -0.42274061021906, 0.447771864063222, 0.349256391843608, 0.319950582970188, -0.0783430406347819, 0.61035570287275, -0.435303728163138, 0.482615948332673, -0.100702291734328, 0.0131511758867353]', 334.6); -insert into credit_card_transaction (time, features, amount) values (157710, '[2.23340713356783, -1.37192147951363, -0.662185960901715, -1.44407956818064, -1.43500442015814, -0.859502029018155, -1.07227743807364, -0.290630911200932, -1.25809865207345, 1.51204896355531, -0.784033967454927, -0.179726731694636, 1.4968017288422, -0.69797890293753, -0.1939576162424, -0.609519131014492, 0.469094690059027, -0.267291828769043, -0.27401873807399, -0.335068902867859, -0.126926224341511, 0.177992740497453, 0.229271651581459, -0.0028900285861614, -0.240273710372358, -0.180751787218209, 0.0272440540426017, -0.0408419406325964]', 37.5); -insert into credit_card_transaction (time, features, amount) values (157710, '[1.85452083383711, -0.367229672173789, -0.558217212120127, 1.33917841078138, -0.283128657092972, 0.139370569410365, -0.424068366305265, 0.106446578742232, 0.858487586130464, 0.280552945921937, 0.182855318680134, 0.944450381959201, -0.22312532242186, 0.0478652831009078, -0.996492409062232, 0.0758328868565778, -0.663522768999519, 0.576392185708508, -0.0762727275393594, -0.191770733428559, 0.262117485114304, 0.95653564613792, -0.0491150454648378, -0.379492678973047, 0.157120066641214, -0.42739859258935, 0.042324453427808, -0.04737974698263]', 44.9); -insert into credit_card_transaction (time, features, amount) values (157710, '[-0.608063721908058, 0.912658989359966, -1.68698466830791, -0.564921834768725, -0.637321632710033, 0.243791128636799, 2.74647743630849, -0.469374315370517, -0.086448018987414, -1.28725128196881, -1.36157896621658, -0.483980069363268, 0.610044103662388, -1.12179091923494, 0.582617926322752, 0.755898538812674, -0.0710757460065687, 0.987920106520247, -0.260664740090848, -0.413269369007386, 0.0956233176669785, 0.768612521503877, -0.166612682928383, -1.04555472127441, 0.197047268656897, -0.14606771205411, -0.195285666404242, -0.383768351332183]', 413.35); -insert into credit_card_transaction (time, features, amount) values (157711, '[1.79060927605258, -0.824626627039168, -0.865917190186543, 0.0593884655954448, -0.27868277420771, 0.315084217011918, -0.505078132646384, 0.179579729708479, 0.892411692830389, 0.129949155600898, 0.222490317106021, 0.466814111042066, -0.534066282682201, 0.2575576340882, -0.0028567739821765, 0.868357420215412, -0.958437692105656, 0.34433087643255, 0.473005535827133, 0.0623647849020547, -0.196232031434245, -0.834103924999991, 0.292884659055228, 0.0641609509919477, -0.641114450737523, 0.208286826622184, -0.0757212673419488, -0.0342823253482439]', 125.0); -insert into credit_card_transaction (time, features, amount) values (157711, '[1.74875641304087, -0.246317377803323, -1.68177109880674, 1.39865404499842, 0.265813314546957, -0.846160902738432, 0.65625034802818, -0.270986067387164, 0.0234580983533103, 0.390881552808123, 0.689536727549109, 0.690268603022208, -1.00964229258842, 0.895489604908673, -1.13696356557025, -0.520512204403745, -0.304995946477436, -0.0862909072981619, 0.0004766380394439, -0.0932346926990085, 0.171824048462299, 0.384562417920369, -0.101023210021308, 0.0113124810225169, 0.350266467128189, -0.522651514896705, -0.0452836003006522, -0.051998269987168]', 127.95); -insert into credit_card_transaction (time, features, amount) values (157711, '[2.06290940705931, -0.0985073059880559, -1.0746602463899, 0.424728512536093, -0.21086073160664, -1.23633508011534, 0.135467223548292, -0.294969951159633, 0.648673869006551, 0.0945891140263695, -0.854399467747339, 0.063420287986235, -0.648607000104597, 0.417232525936087, 0.117244314898733, -0.0745703815737302, -0.244229578582521, -0.785508254889115, 0.147854764196914, -0.27209158146865, -0.297403599398062, -0.755194705224479, 0.350648591297059, 0.026799041861862, -0.323296181699123, 0.197861583694769, -0.0751979158080538, -0.0615309766170867]', 0.89); -insert into credit_card_transaction (time, features, amount) values (157711, '[2.01469705680187, -0.0822841976412569, -2.06152853530467, -0.0010730450306624, 0.357811866172648, -1.48654202579575, 0.68098509760149, -0.412160117626251, 0.0728540232536272, 0.195227874227898, 1.04494421308875, 0.504948037007703, -1.12521918830388, 1.21392985109342, -0.183097468845714, -0.485913916504491, -0.360351800404257, -0.0518389907986588, 0.286273256842784, -0.240041823051097, 0.219247260541673, 0.638572335051831, -0.0531043384039009, 0.0536513585829779, 0.339733673069798, 0.220614263234906, -0.0983463906170769, -0.0853045674918219]', 34.36); -insert into credit_card_transaction (time, features, amount) values (157711, '[-3.41224398629134, -1.15634281487342, -1.1205957337612, -0.69389202939277, -1.773805847031, -0.94935266737923, -1.32371444761529, 1.38071046304581, -0.953248914776966, -0.547431335206752, -1.68187956043691, -0.267408074185896, -0.191121431983989, 0.778995155445901, -0.452838870960759, 1.36880023809223, 1.15791831104715, -1.5421865482288, 1.23568931295594, -0.801838038511645, -0.0341809209545198, -0.545396052728094, -0.713613503038132, -0.0061310096297611, -1.23002879473872, -0.636972710381375, -0.197637834622837, -0.651053013080145]', 171.88); -insert into credit_card_transaction (time, features, amount) values (157712, '[0.0989804200521075, 0.853935639147031, -0.236748881500504, -1.03244010873371, 1.22347408047963, 0.0052854001696519, 0.947374030212105, -0.0304612684121577, -0.364118609574942, -0.269466042620061, -0.278048124214595, 0.916028378088138, 1.18237770942887, 0.0243347766881615, -1.1153730129135, 0.454286229560289, -1.21473713886705, 0.0682362047219116, 0.714442535680621, 0.0808983492522834, -0.287335225251765, -0.627481003337142, -0.125146296898898, -1.36496809782038, -0.302565519024166, 0.202264965204935, 0.248370739635226, 0.0755224212851905]', 2.69); -insert into credit_card_transaction (time, features, amount) values (157714, '[0.799779680799791, -3.23074821302674, -2.28827118797305, -0.432111858440381, -0.93011288573827, 0.0287034662815749, 0.372309467041956, -0.42399801937249, -0.322418073218563, 0.413262899668769, -1.37974737180012, -0.267197050486103, 1.46891159565811, -0.39543282007967, -0.0222218945499173, 1.07631048062601, -0.0624082406389561, -0.798928566142645, 0.47905229608856, 1.62047576291256, 0.993055037648376, 1.30520536588664, -0.845388765729923, 0.193618863485148, 0.171818739730658, 0.176384445243742, -0.15874447596759, 0.069465861141501]', 770.0); -insert into credit_card_transaction (time, features, amount) values (157715, '[-1.15151070369599, -0.261184827920678, -0.54378669207494, -0.949367828432265, -0.220211373747866, -0.457553307770774, 0.392175117118435, 0.212560057251552, -1.38168995534741, 0.37997212568231, 0.149402385483674, 0.591435861213132, 0.678457976847136, 0.549668547885028, -0.476683180184847, -1.62122837242952, -0.295232680743798, 2.08670492351661, -0.327476871922351, -0.426557273072765, 0.129674271633178, 0.897669401514398, -0.283329037528044, -0.345531298927138, -0.412491704871043, -0.0617587000550677, 0.371075362656271, 0.0273624101654262]', 153.0); -insert into credit_card_transaction (time, features, amount) values (157716, '[2.13960676437663, 0.116314882509173, -2.2819265844949, -0.0810395758204253, 0.780268441848252, -1.2559407469731, 0.748974820294992, -0.496697118637002, 0.191627186788527, 0.0042763925631347, -0.697814341080745, 0.216595363613753, -0.0213330778164765, 0.790909074054887, 0.467679897828941, -0.641676011049803, -0.267535820278356, -0.565824539282567, 0.0917940032598002, -0.210624964856565, 0.141256955030142, 0.524243514598024, -0.017205946916704, 0.662285358564918, 0.460442001483553, 0.216937072860783, -0.0880022269442688, -0.0732120136568121]', 5.39); -insert into credit_card_transaction (time, features, amount) values (157716, '[-0.687395606131064, -0.811675380751586, 1.96335985136443, -2.49551595277461, -1.08395152683164, -0.558470787697042, -0.319757055166589, 0.0239113583875154, -1.9842499166027, 0.514947782574436, -1.30669011925027, -1.68552629451437, -0.523964589558547, -0.502899145340056, -0.0520431138770475, -0.248509036206257, 0.429806543402249, 0.160811730261178, -0.0538654149151179, -0.129093071018592, -0.359877068987999, -0.912692432213343, 0.0477705694209291, -0.125178925383502, 0.199419520983958, -0.344678143816341, 0.0272673024529501, 0.0726550050875739]', 77.58); -insert into credit_card_transaction (time, features, amount) values (157717, '[2.05486050579718, 0.608076882322144, -3.17165341934081, 0.607542320367241, 1.27546110085412, -1.27431158894089, 0.676767124479248, -0.28872995640852, -0.16685232294003, -0.87156134900345, 1.7361261023187, 0.143819087736308, -0.795832813327849, -2.11951531861391, -0.603184155860302, 0.478242839221899, 2.02264315294918, 1.00410596120624, -0.0943829193737678, -0.153632704118881, -0.015600559170337, 0.109013569114515, -0.0383344695606118, 0.521952099439397, 0.335767226064341, 0.666045537228504, -0.085322148836183, -0.0242474384588215]', 0.76); -insert into credit_card_transaction (time, features, amount) values (157718, '[2.16196377374032, -1.4400880269279, -1.32130950188601, -1.6702221988234, -0.979168406378975, -0.725135505574236, -0.744821420680758, -0.218022576862253, -1.76248322081587, 1.74926473957811, 0.609433797135966, -0.245613014986551, 0.21860596828053, 0.0800327582767899, -0.684628808297289, -0.374112064338889, 0.201473937162067, 0.0517300210665242, 0.307962485896333, -0.307618793782886, -0.345554440726133, -0.743668220021808, 0.275319264420758, -0.458215897296709, -0.35406018325631, -0.42570115101492, -0.0229948358790974, -0.0541570166511318]', 81.5); -insert into credit_card_transaction (time, features, amount) values (157719, '[-1.74480963314594, 1.12726528430504, 1.09339226637976, -0.836972192575929, 0.0770859331943493, 0.72414609078766, -0.575297902802208, 0.0673251672315034, 0.0064165241038514, -1.17401423913389, 0.525389633115017, 0.412649204532315, 0.0773802499643181, -1.16002150261714, 0.00369476765225, 1.38484404901185, 0.120386476087222, 1.30701852894999, -0.11005286556072, -0.127813990336697, 0.729634494678331, -0.427830768772551, -0.26300066131953, 0.133098437885287, 0.336508329003728, 0.469959801403511, 0.0852398532309527, 0.0573786524842632]', 27.02); -insert into credit_card_transaction (time, features, amount) values (157719, '[-0.621228353327562, 0.624285992459337, 1.40357257893024, -0.188062673974394, 0.762374543008539, -0.598681506226526, 0.460633794708798, -0.25527526139679, 0.0129298142927818, -0.863764865688883, 0.0524628174940379, 0.547316935854133, 1.42623370880741, -1.87387754478618, 0.453129739791528, 0.343257295132107, 0.427527456785175, 0.0390628398482318, 0.0294508887580651, 0.138188538767803, -0.213793104385074, -0.382271377209789, -0.02378105518954, 1.08981290907663, -0.663834862340947, 0.125313910780929, -0.134568347558121, -0.0230695956062728]', 7.5); -insert into credit_card_transaction (time, features, amount) values (157720, '[1.87534467196814, -0.386283525782356, -1.73251581845083, 0.564615543003386, 0.00078828664008, -1.38584969024051, 0.616833862423922, -0.462968354299756, 0.456580455626643, 0.0760778997072881, -0.976862974506888, 0.0399588558403184, -0.698534820557059, 0.555526913628406, -0.369302212248358, -0.530012881497882, -0.0303145275859608, -0.756133405018857, 0.163803364331775, -0.0529892035259458, 0.0252536741780427, 0.0110866789883752, -0.01139968605374, 0.0974125841804097, 0.117138482703166, 0.548415462399308, -0.121336716684905, -0.0587772356392768]', 114.99); -insert into credit_card_transaction (time, features, amount) values (157720, '[-0.137070397494505, 1.25698306906897, -0.822171092975724, -0.0507160720804286, 0.498625466200844, -1.40223614741898, 0.839519597149465, 0.0057310439489969, -0.53563836934527, -1.30220621077778, -0.376733780561397, 0.71488289694574, 1.6049256330661, -0.89988367398027, 0.478850845857217, 0.114826762717223, 0.600108245416873, 0.598087809678427, -0.207522455345316, -0.0461676360383316, 0.385814581558305, 1.13069404737389, -0.112240056504673, 0.015275852447655, -0.303029101762543, -0.163807832594741, 0.0242145500945038, 0.0630719288032126]', 31.35); -insert into credit_card_transaction (time, features, amount) values (157721, '[-1.63625299258691, 0.18503739257352, 0.630537397018246, 0.342683922397841, 3.05213921295319, 0.944062070973113, 2.13470692271031, -1.04603666123174, -0.232853622191206, 1.65431531065051, 1.40933146862519, -0.429179045224098, -0.88915230197759, -0.164246412962473, 1.04559726919722, -1.76384070132233, -0.232887162383348, -0.885468461010331, 0.323687933577685, -0.0809489242731169, -0.172936767851691, 0.869627246708934, -0.280258508832121, -1.63249946894961, 0.986196885860962, -0.225896634445978, -1.20041479355825, -0.69416222803821]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157721, '[2.35224064673288, -1.24037467615084, -1.3148670520734, -1.75256118002705, -0.621643905937809, -0.16410659540082, -0.976440352585635, -0.223861532002158, -1.40291655909312, 1.52811722297215, -1.37001896173841, -0.324703648573353, 1.86838678825219, -0.704246399702155, -0.226962866015586, -0.520779340370145, 0.226069139015708, -0.143013760719467, 0.0638645446621194, -0.315189119534527, -0.199750330303654, -0.0074321677632379, 0.169072197896752, 0.043259563711516, -0.0250523177470883, -0.152650500287121, 0.0149259061887248, -0.0491188837030023]', 15.0); -insert into credit_card_transaction (time, features, amount) values (157722, '[1.96612703219513, -0.253117465158608, -0.900693154517135, 0.138114281612753, -0.351624445304147, -0.32944868351956, -0.677134280490194, 0.212898699560324, 1.21981683998678, -0.502937296029852, 1.06255855136034, 0.194328068382722, -1.45382274336648, -0.827850694646634, 0.300911725673378, 0.886717056639332, 0.269383643435912, 0.95683251264678, 0.147620682377368, -0.237755602273712, -0.232869634876307, -0.639475941132792, 0.419241966330101, 0.592417743229822, -0.562535830679615, -0.333907151781833, 0.0074331860198138, -0.0157852338409259]', 0.69); -insert into credit_card_transaction (time, features, amount) values (157722, '[1.95375607836766, 0.208453312769648, -1.38612953073745, 0.762022764930532, -0.226580458208283, -1.95441439845862, 0.316022890373539, -0.440065071390843, 0.501610081971117, -0.535540136948992, 0.546542253716424, 0.431528432416829, -0.0236207837854936, -0.798231176974282, 0.877639497850422, -0.0849552462026133, 0.84652490413895, 0.153834193265087, -0.859052061640282, -0.195836123234694, 0.265465312759295, 0.915349515684248, 0.0776750935802523, 0.803664389673934, 0.119128893702822, -0.155292044684752, 0.001039654412365, -0.0172745351522763]', 19.89); -insert into credit_card_transaction (time, features, amount) values (157723, '[1.88306046955227, -0.142990985836102, -0.24634313570694, 1.18354323212451, -0.287394228437906, 0.0042976561488086, -0.405181766596472, 0.0493816253524111, 0.509614968574173, 0.284344795506559, 0.686133511252082, 1.60096000434168, 1.18420653539479, -0.067904883853454, -0.365663834377753, 0.609023892298469, -1.09161337575391, 0.325901154568324, -0.0634538563040106, -0.115409496495687, -0.111626716315311, -0.221475587175289, 0.282086983367242, -0.377408422015035, -0.333193008279494, -0.945847537368155, 0.0569227736079488, -0.0309590263476874]', 30.0); -insert into credit_card_transaction (time, features, amount) values (157724, '[-2.60358387513266, -0.169809858854303, -2.33526433253578, 0.090731200255946, -0.0903069094103162, -0.620193663359932, 2.24707625757752, -0.460744914136078, -0.492196569237174, 0.81591512685564, 1.03441930448471, 0.732297276928022, 0.657380500257113, 0.896921654903982, 0.856432775557493, -1.67446008643761, 0.68919577795076, 0.169969270707623, 3.69560303475718, -0.464350760990591, -0.0381503117327855, 1.50279391273233, 0.416231898221532, -0.183821737121722, 0.64549520214581, 1.53625234150466, 0.154956667416565, 0.851587915478829]', 291.85); -insert into credit_card_transaction (time, features, amount) values (157724, '[0.723360752807003, -2.5006202500231, -1.1272152166997, 0.906035703967983, -1.25003730663717, -0.0107589032435551, 0.154625195446812, -0.0647829644728568, 0.817117518756416, -0.0127280791944832, 0.482318179552464, 0.511091711191271, -0.391017689336516, 0.391254497037432, 0.325454421233024, 0.918887684982675, -0.98758000000924, 0.937779728883236, -0.264996163739257, 1.10162581431703, 0.605630955457955, 0.352784547002129, -0.436919060781049, -0.283796328404269, -0.534874213647396, 0.289655548216429, -0.144085425228715, 0.0543768383394672]', 656.0); -insert into credit_card_transaction (time, features, amount) values (157725, '[1.97245874637588, -0.311235658811216, -1.13765858487174, 0.385527717274655, -0.246557106389888, -0.875436518945476, -0.004623364600778, -0.0730387120821265, 0.599334852411939, 0.266414118645752, 0.674123090070554, 0.183700143770359, -1.99069223219973, 0.829735061147462, -0.675110329327211, -0.0590788516441056, -0.242419820694527, -0.281789626339758, 0.399815628301293, -0.316908337738648, -0.198612595258991, -0.553933597218353, 0.29739483161382, -0.0180660779202193, -0.319900024206561, 0.261274573246603, -0.0890224826893526, -0.074460103514258]', 18.58); -insert into credit_card_transaction (time, features, amount) values (157725, '[-0.363514016478533, 0.177053591125749, 0.0119787509115585, -0.654651934101109, 1.74636972698075, -0.577205226160921, 0.732924569627344, -0.147999997205572, -0.328573023544414, -0.678551327187185, -1.4310647524126, 0.634034242041797, 1.50822815607622, -0.188387541197768, -0.684226452633179, -0.102837961548682, -0.634986148957864, -0.644916980359248, 0.312134555344841, 0.170493961997501, -0.15719425672895, -0.537560578490608, 0.0416626985177572, 0.129975425106479, -0.113123378375355, 0.231346216192709, -0.0254380704660875, 0.0552388238530175]', 19.24); -insert into credit_card_transaction (time, features, amount) values (157726, '[0.878917111334939, -2.03105550284133, -1.0214159002434, 1.84564504009851, -0.889114340972146, 0.367653194121688, 0.220444743696283, 0.125665856615481, 1.1612700663397, -0.0401190716268564, -0.163421181559374, 0.358867873321331, -2.02238933237572, 0.408486005834388, -1.57356771772049, -0.0353815386718897, -0.238734131927209, -0.0330241836447003, 0.396363947137648, 0.681179274924865, -0.188443387922137, -1.56621113018766, -0.0531936586490342, -0.504442290001158, -0.578608602432217, -1.1495294333512, -0.0588114995148, 0.0441367849168055]', 538.34); -insert into credit_card_transaction (time, features, amount) values (157726, '[1.91326975684577, 0.380030166067447, -0.015331785212037, 3.68769972344405, 0.218804311904375, 0.820744149532908, -0.46075938563668, 0.130471223516256, -0.480682277600088, 1.33704065314851, -1.47307500188708, 0.354497904649734, 1.46298044027489, -0.542150052295379, -0.699154114868896, 1.20037593508322, -1.10887513397289, 0.0158273540369675, -1.6223648785, -0.170714747967421, 0.192106576834552, 0.719308000405804, 0.142393587394244, 0.491913339925366, -0.0711378521400837, 0.0524469483587269, 0.0172914589640989, -0.0272715204093887]', 0.0); -insert into credit_card_transaction (time, features, amount) values (157729, '[-0.135079150460308, -0.312016260053282, 0.32433692486917, -1.99219567343341, 0.0253562877594597, -0.638739490716042, -0.304824885852845, 0.217916859014027, -0.58002394823955, -0.592081314606204, 0.413093287112477, -1.47092519501279, -1.71797833081587, -1.76140179604005, -0.844481461544482, 2.33758961879167, 0.749342245065009, 0.477205584569342, -0.0770147909790259, 0.0236968959713333, 0.291533244084363, 0.60327816471401, -0.204558674856077, -0.656885219622128, 0.127082276128294, -0.160031518660253, -0.0348545419555524, -0.0287506589618432]', 29.95); -insert into credit_card_transaction (time, features, amount) values (157729, '[-1.18220190362248, -0.0257817403316293, 3.18345036000015, 0.534384530963497, -1.40506692714005, 1.40711225131491, -0.93655540513724, 0.490005511322857, 0.903806171820324, 0.991590472112133, -1.8486838999968, -0.628378535219499, -1.10835989254774, -1.5796298923857, -1.08481573031768, -2.40679428713002, 0.737113749818529, 1.72873040730758, -0.0377727446071612, -0.0096650774240008, -0.401191505256539, 0.195966139211129, -0.298086923915537, 1.04636675893324, 0.477508551473099, -0.21721721020614, 0.502342147650274, 0.114366489452585]', 33.0); -insert into credit_card_transaction (time, features, amount) values (157729, '[1.86066292512071, -0.060755652031458, -1.15116404660628, 1.10595588795016, 0.597370028072106, 0.484111521979414, -0.0562541298916691, 0.148761300708121, 0.350064269840274, 0.176097055722756, -0.174499668337228, 0.316006448366575, -0.260018955524417, 0.587528898130697, 1.46145696582153, -0.837498533998299, 0.232027835375126, -1.41997535424651, -1.75208375550648, -0.358817633771942, 0.267541085459971, 0.964837804430686, 0.149570845986861, -1.04992465275647, -0.061440261679628, -0.434968541876182, 0.0604239207426233, -0.0565229157493051]', 16.5); -insert into credit_card_transaction (time, features, amount) values (157729, '[0.0430874744276437, 0.539609416337611, -0.206477371587916, 0.626103030723981, 0.0535734494235362, 0.420719466519524, 0.0194679208874651, 0.667442584700973, 0.375197638166617, -0.537318696250242, -0.240778798205031, 0.886039532380885, -0.736713495098328, 0.139043945391565, -2.53904541056196, -0.364136969855616, -0.175893336013086, 0.483131627821184, -0.234845531635576, -0.363992028753882, 0.460313492158909, 1.49047034113996, -0.0307372184666412, 0.733725597282153, -0.251439728448248, -0.461292835372154, -0.0205447788505751, -0.0465251563198618]', 33.72); -insert into credit_card_transaction (time, features, amount) values (157729, '[2.05392096730951, -0.485047366996594, -0.421359083552135, -0.567622981936313, -0.788849048074937, -0.850626070675346, -0.576219174661075, -0.17757858193835, 1.27368729638622, -0.286011765480416, -0.534563377854391, 0.894949803577948, 1.21925877666629, -0.290118178572024, 1.027042043393, 0.262284908789234, -0.557635011113767, -0.176165265043644, -0.0678702266938465, -0.111311705226173, 0.17856957630193, 0.755374978682321, 0.18581094850823, 0.021985553249536, -0.358174437579049, 0.905651567245641, -0.0422885503453461, -0.0541647381111306]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157729, '[1.99046452117127, -1.55935315707384, 0.700413255597818, 0.039152107808816, -1.93450523802281, 0.909402373194253, -2.03394680766219, 0.429783747591807, 1.56562500166477, 0.458970546925944, -2.09209777217274, 0.311779096581483, 0.023306107902371, -1.45718615019637, -1.58093429602757, -1.60340142061484, 0.337737270295003, 1.32106370468724, -0.499558191726185, -0.579002925987237, -0.296019127949799, 0.11348467052891, 0.280493054138748, 0.776709265077171, -0.49041054453738, 0.70745646506897, 0.0592593016328184, -0.0231873729001059]', 22.5); -insert into credit_card_transaction (time, features, amount) values (157729, '[-1.25454842323468, 0.941880830428566, 1.52544457153431, -0.455663961649055, 0.160774639369195, -0.0194390053972152, 0.0742802108485071, 0.461239401103857, -0.212571015686181, -1.17288418247576, -0.94364535973804, 0.829411037380491, 1.4691697707377, -0.112771398277907, 0.565695675474951, 0.0660019687455348, -0.338204514221051, -0.031531892366414, 0.493315191054204, 0.0066155181174142, -0.110423117219574, -0.45272172129073, -0.159572853270231, 0.664744134165357, 0.406529115273121, -0.460189311363227, -0.178883034994962, 0.0134448350286316]', 5.0); -insert into credit_card_transaction (time, features, amount) values (157730, '[0.0839327239416598, 0.683834233418001, -1.67189102298397, -0.699370715900215, 3.44092275887205, 3.45003343802652, 0.91268547303285, 0.752580964206175, -0.657073893458826, -0.417852972972361, -0.474010861608173, -0.0497824462278548, -0.56034955603052, 0.616863925698081, -0.586137546968355, -0.723522687660101, -0.385048316612948, -0.542379653671504, -0.477242003478422, -0.132839107203323, 0.129922194016745, 0.366524131873971, -0.176436163791804, 0.697153406778408, 0.265947243636046, -0.546936375418111, 0.067196823917898, 0.0282515202634015]', 30.0); -insert into credit_card_transaction (time, features, amount) values (157731, '[0.1995078300392, 0.0481512741523652, 1.17324213839455, -0.54029192338214, -0.648228375847309, 0.0184542537667365, -0.56417786027129, -0.578783758329997, 0.638947251460841, -0.454726480564647, 0.500445620656671, 0.203219858451849, -1.46238988012587, 0.275061180240275, -0.469610560114083, 0.590888191075948, -0.619956271325532, 0.584559796668071, -0.451570470637419, -0.345685919619283, 1.0168020784624, 0.493985120670883, -0.240630898609875, 0.0554064859293341, 0.523822333637476, 0.791519563884681, 0.140001719244784, 0.226700364449408]', 17.95); -insert into credit_card_transaction (time, features, amount) values (157731, '[2.0507343376702, -0.364009836098765, -2.54284268573131, -0.729357245980242, 2.38845513580892, 3.318014826674, -0.479137991434965, 0.791558699015965, 0.403373925785878, 0.0932322962383584, 0.0043906366679776, 0.390166351524176, -0.212555237880757, 0.495543631087541, 0.472633049946723, -0.171594983536925, -0.368260801549244, -0.9765716778526, 0.0228694906165437, -0.154977952804284, -0.293362990419633, -0.834801882577702, 0.3817404029926, 0.698179490919462, -0.264798455762679, 0.219274980948542, -0.0521311602761514, -0.0669400159437571]', 0.89); -insert into credit_card_transaction (time, features, amount) values (157731, '[1.53136924224897, -0.310048806894437, -0.287028298184486, 4.1018803345775, -0.276467100656946, 0.477880622857202, -0.137269115972041, 0.177404812366639, -0.360909919670694, 1.42106600905119, -0.111357941324161, 0.128795464003687, -1.33697038752733, 0.135516083601316, -2.5196368719342, 0.616586085476324, -0.534845988771062, 0.159013162523121, -1.05393044119171, -0.0651423817638953, 0.224870428483919, 0.487209990936455, -0.0476636286017667, 0.0621805674558569, -0.0352279747441221, 0.0960941777092523, -0.0439263310190957, -0.0308992979487691]', 160.55); -insert into credit_card_transaction (time, features, amount) values (157734, '[1.53265689060905, -0.835334625878746, -1.33941998281553, 0.773041324756797, -0.302611341229472, -0.98896900195442, 0.569470538780951, -0.39708183007438, 0.41550962555782, -0.047659427057156, -0.62971105879701, 0.709196057718519, 0.547269389829577, 0.26434253095437, 0.0567838681342358, -0.160474675874906, -0.27168188006874, -0.916221387420979, -0.070981231542146, 0.329230836593397, -0.110218889804579, -0.756679478084036, 0.0992391241467011, 0.0024401347059051, -0.356666846853665, -0.0099416276904652, -0.101002089506618, -0.0104919701237508]', 267.32); -insert into credit_card_transaction (time, features, amount) values (157735, '[1.63444532898914, -0.0197332889722868, -3.12483542444803, 0.685038292748997, 0.896015232235635, -1.19555554770097, 0.753084895225058, -0.32752091878664, -0.192446738558224, -1.15091655004252, 2.06903756625235, 0.543792983936332, 0.276692563921989, -2.71468245230332, -0.161956353283861, 1.0419110466672, 1.98903855929372, 1.33303264881618, -0.279098148144303, 0.375653482384625, 0.0550718321301796, -0.188810866533899, -0.129843576750681, 0.568200212000063, 0.0150531596875646, 0.616775933946625, -0.107157415777995, 0.0326259473521055]', 212.5); -insert into credit_card_transaction (time, features, amount) values (157735, '[1.96109203223554, -0.528540137753307, -0.325544351035125, 0.224395381762427, -0.652669097723302, -0.106513722314842, -0.744279728802693, 0.0757925003794997, 0.99019154416596, 0.151985502949062, 0.49836346179682, 1.14690496931221, 0.532910843380806, -0.178796555657022, -0.366146632611469, 0.581938741253262, -0.857587282177263, 0.573283930199769, 0.144008717332649, -0.126042543165891, 0.251555975560306, 0.932609360914507, 0.0708070497223712, -0.249851283209036, -0.232101252490165, 0.739863104208191, -0.0305572209268441, -0.0609666562208546]', 15.99); -insert into credit_card_transaction (time, features, amount) values (157735, '[-0.235250554447461, 0.906977219661731, -1.94102702441792, -1.48449225641093, 2.75372616762362, 3.22248526596363, 0.0538252946420797, 1.24510812037575, -0.325851713944973, -0.483693641675058, -0.331382826136371, 0.0763572678096864, -0.191125772385029, 0.955619825184088, 0.846018111597045, -0.390388122008495, -0.386121326856718, 0.0868194108651453, -0.0898286001610832, -0.0660120592086755, 0.406731389793851, 1.19745494433062, -0.0439231917210208, 0.738458428989925, -0.73324634393742, -0.196474887371765, 0.404481030693308, 0.253279151880028]', 0.81); -insert into credit_card_transaction (time, features, amount) values (157736, '[1.81312385735221, -0.323789478825606, -0.609382898331711, 1.06485127359648, 0.0294101757378602, 0.533087326374859, -0.394093458833934, 0.18524075531703, 0.541328562945295, 0.274353850807245, 0.499172146392197, 1.16182872490071, 0.510330714660039, 0.117324054018575, -0.199994186427157, 0.625323067452073, -1.052620444365, 0.333366185066629, -0.0426189679779955, -0.0432900869287134, -0.148302521511433, -0.508033618773403, 0.29720407996019, 0.153994711429784, -0.360920244871966, -1.00971462654726, 0.0371480590935368, -0.0205512077274272]', 74.4); -insert into credit_card_transaction (time, features, amount) values (157737, '[2.34191332652484, -1.29235434188819, -1.1663059791641, -1.64409219156798, -0.949666254165145, -0.506931627177632, -1.04191844161893, -0.20527747904874, -1.24518596371226, 1.57382420240768, -1.27115821133562, -0.855970489346708, 0.594317678474899, -0.446903717398437, -0.17153902421874, -0.522073955042361, 0.382970217363685, -0.0365801921350226, -0.0042291025315354, -0.409341603008864, -0.196424976896256, -0.0541493273329784, 0.230359988947385, 0.458440405325111, -0.102030196988762, -0.177833530601189, 0.0053239410753613, -0.0479942748179367]', 10.0); -insert into credit_card_transaction (time, features, amount) values (157738, '[0.0418645194958908, 0.92642488095757, 0.312047533160246, -0.602698595487112, 0.514088007938104, -1.02275759922992, 1.04823208390876, -0.227917837461599, -0.16951620507941, -0.441848430369793, -0.73626984921396, 0.594195376622629, 0.826146092782206, -0.0456577888195562, -0.446203737272811, -0.190700467636849, -0.39897925379227, -0.938995428517715, -0.160833898722656, 0.0019267572841458, -0.246776039875847, -0.48019386356188, 0.0607875512709743, 0.0026076814316677, -0.477604907738661, 0.140735178967626, 0.256590546370483, 0.0983938085356448]', 0.99); -insert into credit_card_transaction (time, features, amount) values (157738, '[2.11420225937483, -2.18804432139882, 0.603545538263212, -1.10575212867619, -2.36094882925138, 0.946849439520807, -2.49509350836066, 0.387735712267693, 0.580118177842292, 1.15042903272111, -2.11858105612205, -0.342310050588501, 0.507294307432643, -1.92203685311568, -1.90383067304198, -0.725858196270718, 0.882391049995452, 0.322210072266206, 0.206341972051273, -0.352456535827324, -0.0707520365150876, 0.646794956511348, 0.183200136361677, 0.615049630458998, -0.316643784242375, -0.00382870027308, 0.109398590620118, -0.0168357117620624]', 46.2); -insert into credit_card_transaction (time, features, amount) values (157739, '[-0.345947018532829, 0.221689609855178, 1.68866949367616, -0.881681084033478, -0.0193693793565869, -0.0021479558732642, 0.240629369384862, -0.0974860189554045, 0.852488363208922, -0.479817384954774, -1.65483960293721, -0.586081860084165, -0.293989674328486, -0.597674819896937, 0.433662931191321, 0.753257698300604, -1.05143706003626, 0.411892847152629, -0.207315148877616, -0.0697681503251412, 0.0502553219555294, 0.342093796755629, -0.117140651695368, -0.566784186775397, -0.868227067863053, 0.401627715456505, -0.131879961206479, -0.0371630755784455]', 27.99); -insert into credit_card_transaction (time, features, amount) values (157739, '[1.90355890908553, -1.72086079221897, 0.139063963238674, -0.194423737837215, -1.66098100337126, 0.760001538073809, -1.71104921299269, 0.283424192302374, 1.23407901022462, 0.566179019715467, -2.63631122614157, -0.266874356715388, 0.149689695445292, -1.08147333397146, -0.486787168481125, -0.91032676753664, -0.338034134929352, 1.83555613708758, -0.468569836431988, -0.385395594783029, -0.24407481846269, -0.0703035333086816, 0.0756449551659965, -0.977724624414079, -0.492004296135284, 0.745733241340718, 0.0283172755923351, -0.0241675265688537]', 112.74); -insert into credit_card_transaction (time, features, amount) values (157740, '[1.83846371707358, -1.00789570371663, -0.475508888942729, -1.32241750189768, -1.3575364935935, -1.28861338371384, -0.537460563976151, -0.027337566127183, 2.03862295720513, -0.773385130811969, 1.3799174976278, 0.917158064264836, -1.62565139490795, 0.592932743942844, 0.617070516813047, -0.273747394990348, -0.245000707848843, 0.267194762712138, 0.852888653005438, -0.155358878853214, -0.11243721178139, -0.384967829765341, 0.384549492012338, 0.495076451362179, -0.599735008164689, -0.617085396006646, -0.0001982873753459, -0.0335827192839419]', 77.73); -insert into credit_card_transaction (time, features, amount) values (157740, '[2.06304902165685, -0.687040539353543, -1.07566541064391, -0.541476227587332, -0.783895137294314, -0.882228198054091, -0.82677879116441, -0.161548779248274, -0.109924804690685, 0.0350148975111852, 0.120669987063703, -0.210782213372381, 1.01565898594868, -2.26763046041853, 0.254984057925325, 1.5469928679413, 1.43530834125397, -0.637877975337297, 0.0596527698877201, 0.168821729448001, 0.286460219525427, 0.852281711381202, 0.146902166622929, 1.07279124793666, -0.161508660978008, -0.152964826764879, 0.0243990126920294, 0.0067917277746852]', 49.9); -insert into credit_card_transaction (time, features, amount) values (157740, '[2.03203087028484, -0.484093814216839, -0.646584353768229, 0.174146147077712, -0.308441001330428, 0.001793199991257, -0.592710224077965, -0.068557470292307, 1.19057544389679, -0.0422091194455687, -1.72321280829425, 0.597794654617644, 1.45394737054517, -0.556781851323801, 0.31076062538391, 0.563820111399627, -0.908643305742023, 0.228343469943537, 0.11718609565058, -0.043987799920069, 0.167939082254307, 0.739235374817959, -0.024812900116628, -0.897527829394105, -0.0863666409083893, 0.798311927228787, -0.0253205952498289, -0.0544788653764115]', 27.99); -insert into credit_card_transaction (time, features, amount) values (157740, '[1.87981862142844, -0.535896887213884, -1.70839444438536, 0.217682555348215, 1.90809314874955, 3.98317403315355, -1.07652420881567, 1.04053296138806, 0.738002701842881, 0.224059767541061, -0.153416613926394, 0.291789101906111, 0.019368121995729, 0.195937671029803, 1.19368443162048, 0.389562242192401, -0.878161575454054, 0.223283119984314, -0.898038370048889, -0.0993954220481979, 0.243559039895981, 0.667075332234168, 0.14697623583966, 0.689132283677662, -0.0623642465308243, -0.54464459981507, 0.0701932712231592, -0.0303286742065872]', 40.0); -insert into credit_card_transaction (time, features, amount) values (157742, '[2.12849030125647, -0.747185954583879, -1.5447927961167, -0.615499644492191, -0.193327180236505, -0.270710002960345, -0.43820758834029, -0.0812152822731884, -0.30877312042114, 0.861168178256535, 0.183825371984796, 0.227208364690515, -0.413833453052153, 0.53995742891835, -0.112469672186877, -1.5536603858097, -0.541578198005987, 2.17722981763222, -0.481800030352361, -0.619650883567572, -0.0148642805005191, 0.515364471776275, -0.0201613311500474, 0.32885944613271, 0.304806248191858, -0.366445790617166, 0.0211505264380046, -0.0553336098042886]', 21.4); -insert into credit_card_transaction (time, features, amount) values (157742, '[2.01273222402779, -0.322355556749874, -1.5004392466741, 0.24660282704128, 0.344595674329681, -0.0243476754177271, -0.0361029272935881, -0.0626035717793579, 0.551757787173089, 0.18236156449223, 0.218477613311911, 1.01743034484664, 0.131678020318633, 0.170105776722132, -1.31341047544094, -0.180723904964872, -0.485994215597178, 0.0982299926297986, 0.590988472091311, -0.124208750743618, 0.158227865516044, 0.664813434578162, -0.0520136886658377, 0.377909825948252, 0.253263259708681, 0.696729598701705, -0.0800659004959113, -0.0752443898421573]', 25.75); -insert into credit_card_transaction (time, features, amount) values (157742, '[-0.318071742166367, 1.02745601434487, -0.260435051717774, -0.766340115013417, 0.355795791655387, -0.572323874948388, 0.56294197477809, 0.398685457019097, -0.432997936487005, -0.469724666742441, 0.187955940265917, 0.794956120303546, 0.0102613143156877, 0.609379768082371, -1.10074059300705, 0.368434422171477, -0.66099246645221, -0.0488361268993704, 0.378681775893287, -0.107260525079444, -0.193564244582984, -0.56329531031382, 0.0740159009143445, -0.503168842407909, -0.43029942841597, 0.152743046722348, 0.114140563149223, 0.0199384851920048]', 11.99); -insert into credit_card_transaction (time, features, amount) values (157742, '[2.31429888671426, -1.04338614715792, -2.50423600176869, -1.67635179225787, -0.150439713563213, -1.37344964681271, 0.0752761681906443, -0.616690509065882, -2.43981859914671, 1.88616946629869, 0.572240577176754, -0.0706863960929765, 0.751883137816819, 0.355195051253356, -1.43279667251668, -1.18345696329319, 0.412356820601461, 0.110319025292818, 0.381389523170668, -0.344839579464768, 0.17638753114187, 0.982407266486812, -0.239708766846984, -0.257360899172639, 0.673004377785231, 0.296020567106736, -0.0769356247549224, -0.0936969434992459]', 50.34); -insert into credit_card_transaction (time, features, amount) values (157742, '[2.14277774795616, -0.802705307196821, -1.2032447205099, -0.32762349364375, -0.5009994773843, -0.475825533194848, -0.452286890513846, -0.206864593196201, -0.168463323362039, 0.795645060166528, -1.36769074191324, 0.117501342180503, 0.356005512597422, -0.19190146490817, -0.700827462347246, -1.8838364574366, 0.14223679111842, 0.798231714167276, -0.560141462893536, -0.558892578312831, -0.304805987842465, -0.178735935872318, 0.161754724574926, 0.750326714511842, -0.0197054230873036, 0.719905494998099, -0.0515041600611123, -0.054912525315581]', 22.45); -insert into credit_card_transaction (time, features, amount) values (157743, '[1.90915326979068, 0.381884263482279, -0.653980010932487, 3.85651108274668, 0.15046036460817, -0.250349935297848, 0.0488580822050828, -0.0409825875221328, -0.579401823091845, 1.51659745039793, -1.56805619390379, -1.18557838785057, -1.75435392553198, 0.523729864223883, -0.608844395046113, 0.730330343856242, -0.592790372678641, -0.0777003608436466, -1.70337045808353, -0.405359719438246, 0.275231998581727, 0.822341964597943, 0.0188386894419778, -0.0471152062090989, 0.141006773457772, 0.252459225232092, -0.0425743072171133, -0.0557621330041325]', 10.62); -insert into credit_card_transaction (time, features, amount) values (157743, '[2.04610332332394, -0.0437500638027864, -1.81848571745892, 0.268296048565753, 0.404609011354702, -0.474795335600776, -0.057555746269053, 0.0384949372649159, 0.55244372839079, -0.150364928358203, 0.588251695820762, -0.302360651856953, -1.97999331776155, -0.263434533359907, -0.2593827933381, 0.672399787638286, 0.255012222252439, 0.506568354023475, 0.440814464473537, -0.265214682377994, -0.350601495515078, -1.03755564438747, 0.323294613528108, 0.201622368223623, -0.325850122264503, 0.174851882408524, -0.0799209036058502, -0.0471719334989403]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157743, '[2.06831161827872, 0.0853584659959945, -2.02475176147264, 0.433383049421526, 0.497033458408612, -1.51080109726167, 0.826759722503537, -0.585385438752121, 0.314635194859999, -0.0249038755415932, -0.90372178264667, 0.54142026658436, 0.255035024111003, 0.568638993545291, -0.242669668034902, -0.868153447529269, -0.178154155510276, -0.573743017275659, 0.204830288816604, -0.193983325283011, 0.141583871185518, 0.617302731362218, -0.121423998512596, -0.0467513421837677, 0.585775550442182, -0.0652624726304511, -0.0545523497600951, -0.0708393278458775]', 27.49); -insert into credit_card_transaction (time, features, amount) values (157744, '[2.23571001383584, -0.68403269277342, -1.83367914028272, -0.784598653319528, 0.130118073020245, -0.195954773585233, -0.278490618770863, -0.138349075822692, -0.654243278575267, 1.08316924183954, -0.622011388178176, -0.0526806265667618, -0.248988782715607, 0.457074860284552, -0.700035079331822, -1.10200788540102, -0.680950159881122, 1.50283359586339, 0.218872242457627, -0.60917267879173, -0.601706295127028, -1.19060008887046, 0.158435948878832, -1.42170496138364, -0.140845673410488, 0.508018611708571, -0.0755261717006566, -0.087813075060984]', 7.45); -insert into credit_card_transaction (time, features, amount) values (157745, '[1.65313779544536, -0.711007814982481, -0.925334352603764, 0.743301747943678, -0.498871318330668, -0.87424547442454, 0.200317409990387, -0.337106866934903, 0.604324757490942, -0.0317452379676312, -0.663058534302706, 0.914893511293375, 1.1222509992426, -0.0550347603174709, 0.145678065297836, 0.0492930673370552, -0.463805890579845, -0.49597221845402, -0.20153375313579, 0.23840996740054, 0.0868596244520178, 0.02814092313606, 0.0459056113483164, 0.104573206944879, -0.246952123497116, 0.192894233459285, -0.0680055170817587, -0.0169334563682491]', 198.85); -insert into credit_card_transaction (time, features, amount) values (157746, '[-1.19625512501413, 0.361336493557756, 0.35012187229708, 1.01481725243179, 0.368568691551676, -0.0962190287971712, 0.290258812587897, 0.511279692890145, -0.25481046823163, -0.386163197926171, -1.94513134037998, -0.495976845991979, -0.395877064916596, 0.530389354663688, 0.627041179194693, -0.0819567498954667, -0.210200150495589, 0.522374627354505, 0.730362671711535, 0.373691561757597, 0.182057884893051, 0.252754667651089, -0.0223804859044217, -0.811654668692753, 0.0046797607188867, -0.439189007326529, 0.298907045272588, 0.0684735103026787]', 104.5); -insert into credit_card_transaction (time, features, amount) values (157746, '[-1.55640515826511, 0.277250057131305, 0.279203818863053, -0.905677045540747, -1.83503504320863, 0.792850091318565, -0.485137799379526, -2.26993589950136, -1.62601845120763, -0.699273926701926, 0.0544874981189315, -0.473159046831929, -1.5860735720041, 0.551110079544066, -1.73441789430872, 0.251688377314208, 1.31969700769844, -0.494231562168939, 2.10783667253359, 0.689377165749752, -0.729807312383886, 2.0054679590148, -0.370282168801813, 0.170553984741293, 1.01876690359243, 0.566498491287749, 0.0116801819572213, -0.11427870154068]', 253.0); -insert into credit_card_transaction (time, features, amount) values (157747, '[2.06080364938134, -0.101986941177864, -1.0758824736156, 0.425613927831132, -0.211935740378031, -1.23594282518287, 0.13691363270136, -0.29525286488622, 0.648545482103282, 0.0940814313372673, -0.854383851158043, 0.0634651836914334, -0.648412667688802, 0.417479297592626, 0.117381436305634, -0.0744266165263341, -0.244197263247831, -0.785284927766923, 0.147506628837049, -0.269871839770831, -0.296743134780897, -0.755769994215157, 0.349687865840473, 0.0268549724622407, -0.323696402968748, 0.197745332701712, -0.0754038679838504, -0.0613411882851275]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157748, '[2.00351548108285, 1.29863412519987, -4.31527728207764, 1.97602283621219, 1.75293830820954, -2.24497222694047, 1.11766605069805, -0.36313840741697, -0.348439676032932, -1.56998016249089, 2.0778789671457, -1.63681061226303, -3.43617789447646, -3.77640102690597, -0.14803122963879, 1.12250281454358, 3.97354020868844, 2.62459597355864, -0.894324918438769, -0.328026190143838, 0.0362068634765769, 0.203869854082124, -0.270469316503627, -0.47223785876609, 0.73443359963732, -0.202782516800411, -0.006616185819499, 0.0244298732988913]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157748, '[-0.650930709532351, 0.263964467540254, 3.55770916797245, 4.76773434963167, -0.202304811467762, 2.49383079864348, -0.8192891254114, 0.592894380813968, -0.123213243627121, 1.06620638546009, -2.38147616099625, -0.989561898628565, -0.695760441119307, -1.3300913954694, -0.859409667122229, -0.346072323192032, 0.529398058632442, 0.692845154870888, 1.70370316356604, 0.451397341056591, 0.0709598979063375, 0.612585293657667, -0.250158348977302, 0.491312935145328, 0.13995672748693, 0.613300895030037, -0.0029253736821857, -0.101570815095981]', 50.12); -insert into credit_card_transaction (time, features, amount) values (157748, '[-0.757335255177685, 1.0909000225444, 0.624266126570755, 0.103105894843957, 1.19497463887191, -0.294548440388125, 1.64648205753637, -0.108406552708409, -1.12908028458702, -0.584121598872455, 0.202519779350007, 0.146319758312773, -0.902308278626179, 0.709994096310675, -1.37243994011026, -0.486067169112586, -0.4523417540132, 0.184860614880998, 0.256269589668875, -0.0601424907495721, 0.100984605028546, 0.255919320168421, -0.59146646132216, -0.403009601270806, 1.26426042679079, -0.35045354357559, -0.0092566107235634, 0.0278198448265206]', 46.0); -insert into credit_card_transaction (time, features, amount) values (157748, '[2.04632034459966, -0.0277642367175021, -1.05622536419919, 0.418738870335234, -0.0968716018175335, -1.20027293230247, 0.24104214894528, -0.375617052299735, 0.438960886866, 0.0498748704859101, -0.619280965777002, 0.796633887964169, 0.73095131062767, 0.145069016676394, -0.0327926480248298, -0.138004912521931, -0.322700700765357, -0.952697690981258, 0.135641874176874, -0.165254478974978, -0.27604066894971, -0.647153198594462, 0.326079762381277, 0.0649931406468035, -0.280018002699793, 0.192272426379622, -0.0679113310596779, -0.0569854048983729]', 10.0); -insert into credit_card_transaction (time, features, amount) values (157748, '[2.19091521079005, -0.317362279223724, -1.7662852128836, -0.663390000862614, -0.11971372843457, -1.35958632204678, -0.0895239106883937, -0.426572707816931, -0.746343483478287, 0.248284108086772, 0.178394282251264, 0.0546052685741178, 1.16300457117473, -1.4928431253211, -0.306709604523775, 0.88305621485888, 1.38405602849814, -1.56463468882138, 0.508103691093454, 0.0827774774478032, -0.0072936520044746, 0.044828725293702, 0.236942252731653, 1.08312110937402, -0.0017934804411545, -0.341545119485686, -0.0223368558942935, -0.022303647117555]', 15.0); -insert into credit_card_transaction (time, features, amount) values (157748, '[2.20287935086538, -0.83917755281413, -1.51623822048021, -0.737539644031996, -0.665990096744758, -1.42158411857157, -0.289538545708148, -0.396269099406977, -0.25257585171814, 0.870033660700008, -1.03394556186747, -1.1769294601708, -1.0684426879714, 0.160989790522125, -0.224718238898465, 0.529784456382618, 0.470406278595387, -1.20821519860039, 0.563084909444508, -0.0983967532299143, 0.550626585402461, 1.6480286354807, -0.165041847378357, 0.119959540547246, 0.444186408439166, 0.290681093294727, -0.0537918831560525, -0.0747253897895706]', 27.0); -insert into credit_card_transaction (time, features, amount) values (157749, '[-1.15657377664651, 0.9964339929977, 0.838178465622397, -0.867772681400813, 0.642522043447302, -0.488090907415734, 0.631533367652051, 0.421273319802395, -1.00700572772504, -0.999795566635754, 0.421285870719857, 0.766778146960382, 0.0333212664749036, 0.665431558398277, -0.91050575948488, 0.211177738668658, -0.445418411118552, -0.165153940034023, 0.4651198229711, -0.103477236494009, -0.189673574203013, -0.784538961403902, -0.318408026743572, -0.387255181204249, 0.521605677066274, 0.325484583863894, -0.166371101041145, -0.0714860119645089]', 1.29); -insert into credit_card_transaction (time, features, amount) values (157749, '[-0.578991320013255, 0.176269869115641, 1.72959747436657, -1.05165833444821, 0.123865694886083, -0.767387046780066, 0.761666346221852, -0.168170447961388, 0.455547597365137, -0.793369567202865, -1.14947578586987, -0.72147540237967, -1.28613927867143, -0.135356071790557, -0.0372385716594587, 0.559436931657113, -0.800872143159333, -0.269226802238125, -0.664825037061927, -0.0347064489860529, -0.222606563308873, -0.670341991988361, 0.0996946645491959, -0.0088786388499015, -0.564961672152797, 0.108489709354273, -0.123975908065529, -0.0811182362070439]', 47.49); -insert into credit_card_transaction (time, features, amount) values (157749, '[-1.31218649527957, 1.47794604528064, 0.835260708483131, -0.973668550293296, 0.583924407310809, -0.233249287567359, 0.566023278091484, -2.8751659798451, 0.155457543985153, 0.458986603345045, 0.918786611148297, 0.432169731130655, -0.86575920634809, 0.0642431161311722, -0.945861892243984, -0.13633792796123, -0.557665163671291, -0.204176920851281, 0.294373282180676, -0.405861928525427, 1.9969671851274, -1.27526037649752, 0.165312730640243, 0.0183607371704786, -0.238080822288125, 0.129610418114815, -0.204347970948289, -0.244018252578356]', 3.59); -insert into credit_card_transaction (time, features, amount) values (157750, '[0.37707341751061, -0.785761319816824, 1.55634358016483, -0.848884021971634, -1.34457735242435, 0.657358226915269, -1.31655931351197, 0.153508217919353, -1.84383387865382, 1.47856470797897, -1.00188191922223, -0.772117045497867, 1.66728344900969, -1.00577065799995, 1.26534710137343, -1.2614443156487, 1.22110051287671, 0.670924631931016, 2.35747901502321, 0.166483286792319, 0.008564787294346, 0.613056734357945, 0.21735821930664, 0.628199165157873, -1.26958849953935, 0.0809728039354757, 0.330339839062508, 0.248804047174878]', 34.0); -insert into credit_card_transaction (time, features, amount) values (157750, '[-1.1444852175499, 1.46634408900666, -0.365784503068063, -0.793915880823082, 0.434679597323906, -0.488924822882275, 1.30281343071596, -0.101746728101585, -0.323897576430386, -0.788616361937625, 0.821229290531026, 0.0679061110252029, -0.486895558605613, -0.604478444778123, -0.0255427173172512, 0.441752999679591, 0.0722325252297329, 1.20462834075134, -0.127632979870371, -0.297017271636033, 0.316754219071224, 0.891904945925574, -0.530348541022318, -0.458556915769809, 0.26186228984748, -0.168980246885882, -0.653336386174846, -0.176615450812176]', 89.95); -insert into credit_card_transaction (time, features, amount) values (157750, '[-0.30657833666707, 1.04174718337986, -0.090966703914278, -0.530341836381778, -0.0004691658636179, -1.19600942803246, 0.618016490422182, 0.264137686380941, -0.0911828639183154, -0.615284265736217, -1.2060001223976, -0.135571452693822, -0.74704131854644, 0.592268067299415, -0.352859432943153, 0.0656562981048191, -0.190546542596523, -0.610394694738725, -0.0880134438732053, -0.186913442561252, -0.223257384024339, -0.648286658547223, 0.150784919608977, 0.0153364519812683, -0.491333449163797, 0.142731071980553, 0.114344205630448, 0.0332636525000347]', 9.99); -insert into credit_card_transaction (time, features, amount) values (157751, '[0.995536448723758, 1.8604287052582, -4.89863812941707, 2.04548218978533, 1.47310361810392, -2.24144023999241, 1.22333008906408, 0.129188612508083, -0.520690411302041, -1.50489855497871, 1.80005730340127, -1.6259847497, -3.31685510771455, -3.58410239272137, -0.217957576241076, 0.998067520421887, 4.25638249464842, 2.88418104171532, -0.418596476532229, -0.16591430638907, 0.2210992914627, 0.682204514751018, 0.223213986092436, -0.493809168008279, -0.855078470331945, -0.352004451994275, 0.179849970939297, 0.0192266340873271]', 59.02); -insert into credit_card_transaction (time, features, amount) values (157751, '[1.93574284930168, -1.22394751772485, -1.27473771655157, -0.491858458306682, -0.525888734919106, -0.0525375139868245, -0.517635371114252, -0.132763676164761, -0.165891062908025, 0.781954952045084, -1.69043305006766, -0.180301217109999, 0.620426933067886, -0.147970583197821, 0.254132470196078, -1.12743992287832, -0.421785323641085, 1.23684133396203, -0.613006316566133, -0.266509198998845, -0.332732352487289, -0.666949738268772, 0.127400319468649, 0.092216133515229, -0.309739217214739, 0.550797522229459, -0.0624281922962205, -0.0274398920709259]', 145.72); -insert into credit_card_transaction (time, features, amount) values (157751, '[2.00616333354732, -0.102957997721127, -1.00872363502309, 0.311893178388144, -0.0922913523546295, -0.852106113930458, 0.0697096663335968, -0.168770834380666, 0.270529123777551, 0.233122176556197, 1.08803451066019, 1.1894353773142, -0.0123713796248276, 0.477161435652408, -0.622302488258895, 0.0066721871032153, -0.453360851093921, -0.494180543124355, 0.332054381450122, -0.222234989389338, -0.226317932674189, -0.54482707297985, 0.345302753808434, 0.018631093559939, -0.353597166337901, 0.178367162491684, -0.0709379948780563, -0.069901327375337]', 0.99); -insert into credit_card_transaction (time, features, amount) values (157751, '[-7.21819546147783, -8.96771828144094, 1.50273907674583, 1.85796380927918, 8.99912602103606, -6.57097391729028, -5.14779023684865, 0.644873625992101, 0.469401243435839, -0.181275576912098, -1.35565956782952, 0.467249738500158, -0.281846967894806, 0.434323948713366, -0.516682797275072, -0.818545579208959, 0.196367774095126, -0.156594276196618, 0.108601452575295, 2.43520143919706, 0.925196875291596, -0.0170445588984718, 1.27785279442287, 0.03193065278178, 1.4085126985899, 0.852911369574687, -0.395061133282322, 0.217884998199604]', 57.5); -insert into credit_card_transaction (time, features, amount) values (157751, '[1.89768816736501, -0.4325048790701, -0.238286022657638, 0.553589326356288, -0.746598094038173, -0.579279604091999, -0.449418149578351, -0.155511820550268, 1.25247685356112, -0.22511706333054, -0.740371551341499, 1.23423281811443, 1.51819281578446, -0.466492861783479, 0.32474220132332, 0.0096020134140664, -0.572519465194055, 0.0293176274116009, -0.259668978023597, -0.0510208700828914, 0.234962279960646, 0.913901902739597, 0.0682567360571461, 0.111997459198014, -0.0657023641164369, -0.224722067025397, 0.0433485789588105, -0.0261791630404535]', 50.0); -insert into credit_card_transaction (time, features, amount) values (157752, '[0.0368117672889375, 0.839535024590251, 0.285488093283135, -0.590370231245683, 0.408437057001676, -1.04481259773251, 0.982371471217317, -0.166127010520899, -0.0036327386541445, -0.41177538679722, -0.924264405572009, 0.0072830840230801, -0.275692752978534, 0.173974207688459, -0.325089052220534, -0.138448856284179, -0.336194481283671, -0.802727435216233, -0.154029898467275, -0.0630528251062092, -0.257930872404855, -0.570648997882921, 0.0800862928457901, -0.0278834331507814, -0.513841647897647, 0.144346911921666, 0.248486090529327, 0.0962140465716221]', 3.57); -insert into credit_card_transaction (time, features, amount) values (157752, '[1.89170739500416, -0.535418234207353, -0.649055233453485, 0.160692492875326, -0.229655852274538, 0.340856330051236, -0.605532253459684, 0.219567501257327, 1.09393164260772, -0.016871538841787, 0.443548139481764, 0.830369798386695, -0.293535774962598, 0.214764634703597, 0.125780314135634, 0.51515258968659, -0.902328507273473, 0.454757093599476, 0.315176349262703, -0.116516418227511, -0.137147320123324, -0.425352543363503, 0.313525952982681, 0.165615719482378, -0.423358015771402, -0.645636348660543, 0.0182145704959304, -0.0323859078184513]', 50.0); -insert into credit_card_transaction (time, features, amount) values (157753, '[1.73278263686518, -0.592270260647071, -0.462045902778294, 1.19644582723498, -0.484116556270241, 0.250928230474426, -0.615395716587068, 0.255479023979069, 0.831429075065553, 0.375551689481227, 0.588540625141442, 0.182356444065303, -1.33669613816033, 0.490835719529378, 0.330270556765314, 0.695356248222205, -0.915768513950396, 0.969378411002267, -0.563212595820842, -0.114479139554471, 0.31885667216782, 0.726783492232213, 0.10557350243377, 0.654289050515933, -0.200611209120971, -0.617173807621627, 0.0245607598500652, -0.019838916332728]', 100.0); -insert into credit_card_transaction (time, features, amount) values (157754, '[-1.08437373698997, -0.0412353933328802, -0.165797624743433, -2.19547962682919, 0.191909781395609, -0.969693391039072, 0.389501989851879, 0.329852914326939, -1.26946382957439, -0.270440447911511, -1.30066986172269, -1.19657995857087, -0.953882290809789, 0.342889906964146, -0.859442939984685, 0.958405612856348, 0.349146044454139, -1.62221774675246, 0.097285102745393, 0.230069657182812, 0.15479247526566, 0.0121206326513846, 0.0309908285512829, 0.642558408052816, 0.129755664567465, -0.398887950359597, 0.172752596264637, 0.0639834429117401]', 76.19); -insert into credit_card_transaction (time, features, amount) values (157754, '[-0.945582711723325, -0.799151969050314, 0.644264103232057, -4.05352188828289, 0.381395552695166, -0.0687993504504064, 1.24520247283181, -0.191101683834918, 1.57213210266073, -2.28272915743526, -0.210813469179539, 0.887805747164436, 0.571868901293711, -0.256948330898479, 0.139600225916565, 0.315878658552191, -1.76638697434972, 1.4558766012445, 0.234058703096384, 0.446352683720084, 0.35439702931146, 0.878347311892487, -0.106315024204261, -1.3765006838409, 0.59924746466712, -0.888200056265963, -0.0967348639529727, -0.0993864296509226]', 213.64); -insert into credit_card_transaction (time, features, amount) values (157755, '[1.94745075040267, -0.166135946239098, -2.1789988559468, 0.259675948304535, 0.600266187134912, -0.385792777166616, 0.111954875304485, -0.119851953489704, 1.09993863711154, -0.930524920925639, -1.14133905144436, -0.155739453659387, -0.312837252818048, -1.56701368196073, 0.073052246972743, 0.237006697353214, 0.970423184107843, 0.321068653985394, 0.309033400867493, -0.020293814296173, -0.267960397036744, -0.696340579812742, 0.079140772639746, -0.162074004683936, 0.0058090256302605, -0.0785920908076026, -0.0221786968919089, -0.0084732558167042]', 75.46); -insert into credit_card_transaction (time, features, amount) values (157756, '[2.22937174280281, -0.564662323451588, -1.56304440884967, -1.1327568991883, -0.12369719813225, -0.950634618370871, -0.172291840174059, -0.337928002082741, -1.04225945626249, 1.01046242461322, 0.894189186048819, 0.421124238419084, 0.938854512454626, 0.168420574924453, -0.519795733394962, 1.1469081134977, -0.264848109965856, -1.22501638871071, 1.1313725279866, 0.0286812615289434, 0.0778540199652142, 0.18988439574898, 0.13716523706319, -0.472203387827786, -0.0044498094611528, -0.30689356629706, -0.0466223127278476, -0.0759521611455766]', 9.99); -insert into credit_card_transaction (time, features, amount) values (157756, '[-0.536399250777087, 1.09269093884251, 0.0314068708488752, -0.718972340435008, 0.86351894985858, -1.11813068621713, 1.28231479015933, -0.382034069909047, 0.0097074625160727, -0.436452431732871, 1.16241012433618, -0.135405498674783, -1.08061221308623, -0.758039036086932, -0.143115331017543, 0.278893564734146, -0.0059484932873254, 1.18267790897185, -0.339699527625088, -0.0185012536458631, 0.278959224317972, 1.04513464711954, -0.308366330102825, -0.0130010893263757, -0.151276944374993, -0.246861157028185, -0.0241853849781984, 0.0452097936799999]', 13.32); -insert into credit_card_transaction (time, features, amount) values (157756, '[-2.18880795479537, -0.497743923716989, 1.31560172552563, 4.86630879729476, 1.40941850566254, 0.253830145565313, -0.634590462763959, 0.749229751785257, -2.1148307841804, 1.02267086527344, -1.58850860407147, -0.959609663901933, -0.235106252236773, 0.658680217144038, 0.931018786180936, 0.127629182179435, 0.350181111152167, 0.484112244497463, 1.29947445980354, 0.869868835415983, 0.272937762982112, -0.181974140222543, -0.0962407741040469, 0.561695162292163, 0.289202182753139, 0.432880230335186, -0.0289126039611331, -0.270890277589851]', 88.95); -insert into credit_card_transaction (time, features, amount) values (157756, '[1.95400584549428, 0.655397195128564, -0.800645554137467, 3.71691852853449, 0.45298297826303, -0.483443968354456, 0.341575095868091, -0.233377861442085, -1.13049220745049, 1.54884478647581, -1.15433181399121, -0.38523453330898, 0.0705418460128302, 0.408296538734284, -0.315414160681798, 0.922552807035497, -0.944061897356317, -0.206842979000685, -1.71940675789533, -0.288283970433082, 0.224559510942943, 0.66151409853066, 0.0541920838425218, -0.0346133499052405, 0.134809410587815, 0.13401380020373, -0.0460666971361718, -0.0525580321456387]', 4.58); -insert into credit_card_transaction (time, features, amount) values (157757, '[-0.458621773689576, 0.682699395919958, -0.717700493667341, -2.7412829900963, 0.79994570700212, -0.651982955144735, 0.84297048631917, -0.432881763454238, -0.388895723073424, 1.38716248869094, -1.36141631435332, -0.845326268377232, 0.970517011252105, -0.747652380526367, -0.488045428227949, 1.12751682724628, -0.695389929559789, -1.10286498145696, -0.160340186601634, 0.580389473761996, 0.350170815111158, 1.50218057323091, -0.225763658542937, 0.0927971874095637, -0.43076290248475, -0.215199122019883, 0.606190882808856, 0.299291556796428]', 15.0); -insert into credit_card_transaction (time, features, amount) values (157757, '[-0.729037821210149, 0.639110463060512, 0.0316307195375617, -0.620396638876, 0.487170188648724, -0.175842768907904, 0.471087167016775, 0.500278982513446, -0.388546378299453, -0.816431294178666, 0.150579394898356, 0.484026317539133, -0.900453179060494, 0.627579538526255, -1.67824069490274, -0.254329596249963, -0.121784321136374, 0.182580007309519, 0.249926019906321, -0.178579942704754, 0.344371573679307, 0.899385461601915, -0.199641932441146, 0.776438831980956, -0.111418145282334, 0.6104960266223, -0.0377101235726492, 0.0624342373798584]', 29.56); -insert into credit_card_transaction (time, features, amount) values (157757, '[-5.7748067363417, -4.32227757549895, -1.29937262597976, 1.04887404906239, 4.12690082549974, -2.8397358767187, -2.04707532077296, 0.123781007629177, 0.762231195781618, 0.617482960411276, 0.621354556794564, -0.0458515743778481, -1.4657956555301, -0.307403443610212, 0.198119137378741, 0.837804586557949, 0.41367559863984, 0.379498094551388, 0.965424104963162, -1.48223402012487, -0.966762699248118, -1.50803320720952, -3.62521359507269, 0.596769572394591, -1.0543500073088, 0.217528109401039, 1.92434252218339, -2.05302930063958]', 8.97); -insert into credit_card_transaction (time, features, amount) values (157758, '[2.17084214383082, -0.913143597442236, -3.56163511718779, -1.99265008070707, 2.39205038258576, 2.70454314926379, -0.306117896979413, 0.465751272850535, -1.13777398376195, 0.927655372553512, 0.183075924351834, -0.627282681614006, -0.110632219055303, 0.582352837510263, 0.350668114039655, 0.363132051491306, 0.273091745774191, -1.82478072814313, 0.513075600093103, 0.117849693666259, 0.373891598093233, 0.870959869816497, -0.0701333838731601, 0.769021113031478, 0.469472131277971, 0.0955363493514126, -0.0685508903513939, -0.0793720094232542]', 59.9); -insert into credit_card_transaction (time, features, amount) values (157759, '[-1.30269411219782, -0.0418640727284351, 0.963828036033088, -1.08506627923451, 0.0742958691779834, -0.407220420858539, -0.0977229389862071, 0.617105780011204, -0.137341527112833, -1.01796292832634, 0.0563638067164112, 0.401193677069014, -0.279475281888258, 0.39915021104632, -0.50418464359173, 1.17020342005531, -1.1178191581226, 0.900995151620355, -0.606936051254229, 0.0281600872063651, 0.403782591298034, 0.693021517532399, -0.104615423876459, -0.370779028277872, -0.265745952914952, 0.53962925255222, -0.0571931587943226, -0.023851507204078]', 65.93); -insert into credit_card_transaction (time, features, amount) values (157759, '[-1.5608254226094, -1.06785779081051, 0.138003773072091, 0.780004173790235, 2.45151437918082, -1.1362534046161, 0.0973771954255916, -0.066839990531662, 0.151997929506751, -0.26895512947376, -1.55927588304372, 0.450376703513502, 0.608360569183959, -0.177370648596257, -1.1696379952774, -0.451448883067062, -0.516868903126989, -0.0903405180474666, -0.258703699149118, -0.120842383187683, 0.263528658179447, 0.973515977305121, 0.606723976833951, 0.597607777707733, -0.303055409059802, -0.65947536289348, 0.114351187137116, 0.422444170159428]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157759, '[-0.915149111878821, -0.732103700070389, 1.49069621661704, -0.450923280227081, -0.704878215076738, -0.494060725888955, 0.0237870140553342, -0.801321529221471, 0.163585727916949, -0.973935235585285, 1.39319968260154, 1.10467325534667, -0.423014185587626, 0.414208599710605, -0.156794493042451, 0.351135605962524, -0.479560017678668, 0.033509649172744, -0.2518095821509, 0.441220008946705, 0.726163557561348, -1.30439193978001, -0.964258204639311, 0.555589713594712, 0.988762713663006, -0.187225454717361, 0.0067962712424468, 0.210200157442145]', 360.0); -insert into credit_card_transaction (time, features, amount) values (157760, '[1.99318002048534, -0.558485868603381, -0.682291230278836, 0.162872636222983, -0.276326482085174, 0.394895499457525, -0.784860404581807, 0.219108104691434, 1.39517808299051, 0.01699714643554, -0.339379115077556, 0.439812518642154, -0.526328463447657, 0.0877231197409678, -0.0176908779296751, 0.563341226883815, -1.04489341263432, 1.04929510691301, 0.398211276012977, -0.22320691538389, 0.173279557567715, 0.691856395487233, -0.0149100689340387, -1.15247816715018, -0.0231690647988001, -0.157821234151418, 0.034256502430304, -0.0590990039260461]', 12.99); -insert into credit_card_transaction (time, features, amount) values (157760, '[-0.387016308294202, 0.885546810509896, 0.576911056022643, -0.246196704250171, 1.26220352242242, 0.0357934725830215, 0.537904841618394, 0.12271423549909, -0.98282935093223, -0.82859659698616, 1.06275462327465, 0.473996961307179, 0.809562502699716, -0.905139917757283, 0.680285294166137, 0.747654974068223, 0.187758406700493, 0.659629050222666, 1.40458637656597, 0.28609258449808, -0.501688991089838, -1.64453150156937, -0.0484504877013835, -0.038074699512936, 0.159200464028261, 0.198745385469487, -0.0901895402829525, -0.0293581212943189]', 9.0); -insert into credit_card_transaction (time, features, amount) values (157760, '[-1.67074797375828, 1.82082365145551, -2.52200953466509, -2.6746545795997, 3.74073522355887, 2.70667631305782, 1.62417230504786, -0.0285580020193143, 1.42983393139238, 2.65812801040098, 0.326584457209074, -0.355215597577748, -0.550939707199183, -0.33648457701367, 0.479446702920683, -1.17822281667817, -0.908659786991288, -0.724692013381181, -0.431888271899474, 1.01650279941969, -0.202766425390474, 0.785905869092135, -0.163050436529736, 0.72764151824788, -0.0017167587024862, -0.0022157418584732, 0.129194628697034, -0.531097752272958]', 0.69); -insert into credit_card_transaction (time, features, amount) values (157761, '[1.40694462058248, -2.22964420616156, -1.09278924554608, -0.521431442785045, -1.25080215662766, -0.145204768685222, -0.441124278894459, -0.0812557289632714, 0.211282577839796, 0.468449312292831, -1.05534025997817, -0.667440778259441, -0.490713485359621, -0.309137851540799, -0.241440792750203, 1.00508435713639, 0.418800533413061, -1.70792073070499, 0.78011860545921, 0.730794486274656, 0.0095547290122769, -0.84834440789254, 0.115268189565705, 0.567331085956412, -0.627161900049319, -0.635384902508728, -0.0716444352603119, 0.0290791235794769]', 403.48); -insert into credit_card_transaction (time, features, amount) values (157761, '[-0.401122422432255, -0.645339960165853, 0.0915963509265908, -3.31662642631649, 2.03008831501402, 3.90081139626387, -0.124758562493921, 0.813170426774759, -0.798233272590948, -0.118267596569829, -0.24322379818147, -0.978460792265181, -0.140870122605956, -0.611342374486742, -0.09413022967914, 1.18331663128513, -0.332136026863269, -1.169642821445, -0.324964079485232, 0.327934203295884, 0.385193222800044, 0.983422473423648, -0.107336115640603, 0.724395613925288, 0.02425207045917, -0.193409887623481, -0.0559692497362724, -0.0898981718065926]', 89.0); -insert into credit_card_transaction (time, features, amount) values (157761, '[1.70549287992302, -0.776769851154756, -1.269321913709, 0.193283838194526, -0.18941776641426, -0.411500022692395, 0.140278014498494, -0.142612548607431, 0.790211108372426, -0.131043037576414, 0.561370173341116, 1.35234409712455, 0.205757307188476, 0.254033378410913, -0.927709356641389, -0.273981225749802, -0.425864520181834, -0.148659817772306, 0.642261157640657, 0.11586753552278, -0.0297770086494233, -0.197822780702313, 0.0250761451731495, -0.364332749618645, -0.114156009804988, -0.100753282589354, -0.0535844740592357, -0.0414337906923724]', 164.41); -insert into credit_card_transaction (time, features, amount) values (157764, '[2.1175155782907, -1.11663247596756, -2.2302878588157, -1.98034002010056, 1.60353246599434, 3.34578886250108, -1.17050146507107, 0.837020898369754, -0.463790988167026, 0.760909132933108, 0.230911381352299, -0.3472023221394, 0.0817113559187495, 0.047503131605078, 0.697017465171006, 1.09409654181243, 0.053715276269157, -1.999946168881, 0.622025169270762, 0.101041804799662, -0.240856650468923, -0.943249384387394, 0.501566369683911, 0.641977508817422, -0.527746218925885, -0.670975082353041, 0.0015298525834196, -0.0454870254824985]', 39.95); -insert into credit_card_transaction (time, features, amount) values (157764, '[-1.30989059677414, 1.12980327572915, 0.441725781261312, -0.316067183384615, -0.753078173327791, 0.139722555312353, -0.883371840005158, 0.251249945812242, 0.575485443335261, -1.05559536288271, -1.89117130004564, -0.557081509676945, -1.50534156809895, 0.683612756139346, 0.489841289333537, 0.218167442861782, 0.0287942119084175, 0.84373675120483, 0.191045063431661, -0.571350397854006, 1.16538560368293, 0.695205033807072, -0.0321006105602973, 0.644284207832754, -0.253610962005684, -0.148318943098187, -0.137651443771097, 0.0349502998053518]', 9.95); -insert into credit_card_transaction (time, features, amount) values (157764, '[1.96168886365896, -0.0228905791480068, -1.81956766671407, 0.605365686281901, -0.0054948676190132, -1.5652948499908, 0.245925701512115, -0.327583095814266, 0.800732913460871, -0.493734836383028, -0.557510075341906, -0.723631300420433, -1.45515625526132, -0.531886059536065, 1.07311761562143, 0.307636523447466, 0.564281440561343, 0.730176787626216, -0.456946507715766, -0.198696834567125, 0.203000673387383, 0.583347524573185, -0.0460066359361122, -0.0635872915782479, 0.185293797337547, -0.104233871821745, -0.019703249051687, -0.0234773131254189]', 51.65); -insert into credit_card_transaction (time, features, amount) values (157764, '[-1.24408848958698, 1.19330632520761, -1.19635638526568, -0.168698167981753, 3.20348483542277, 3.62516663905731, 0.43212868247803, 1.23732426531801, -1.17622634555151, -0.30698692682965, -0.421755300569328, -0.0590431987713753, -0.422845756572558, 0.956501653798671, 0.245497178313069, -1.11597558271264, 0.314007277995835, -0.370367867076112, 0.834382394202446, 0.099246194259702, 0.0593075084841779, 0.112485890832437, -0.576128289794068, 0.728286525022359, 1.22087694806438, -0.161937834991758, 0.0745908720937911, -0.0046648865197071]', 19.12); -insert into credit_card_transaction (time, features, amount) values (157765, '[2.21734135992744, -0.988823844878078, -2.60643504663937, -2.02269347283352, 1.81733862530113, 3.16650688706906, -1.07694334578937, 0.732534918485502, -0.611046856597784, 0.881106027037353, 0.161659516476641, -0.57133579392004, 0.0780645293858644, 0.162916827005175, 0.827917211894789, 0.921990505112027, 0.0189876950808539, -1.44369894700329, 0.304113364825286, 0.031259645334043, 0.34595602029342, 0.905648238529103, 0.109967126755195, 0.745062187685227, 0.105037562025788, -0.0157633632639415, -0.009606430433617, -0.0685059262213962]', 5.37); -insert into credit_card_transaction (time, features, amount) values (157765, '[2.02474001199973, -1.04195921618869, 0.240668717474758, -0.417004602762899, -1.55363320107346, -0.340650650908301, -1.30683824786951, -0.059122860943785, 0.0677928111987486, 0.79385286667541, -0.832432824646551, 0.69533042600112, 2.22398524543296, -0.746864357433475, 1.18544880018828, -0.491384534831706, -0.798937860617149, 1.64298213992037, -1.37062654735142, -0.385600953949756, -0.0920158826773632, 0.298817268433962, 0.279405417422832, -0.0692194183538692, -0.662983361241718, 0.599295531685619, 0.0239562682798574, -0.0210275953423005]', 45.9); -insert into credit_card_transaction (time, features, amount) values (157765, '[-2.36249893049779, 2.18652491201584, 0.0330869364420679, -0.952162083735602, 0.598479014534101, 1.49417117857969, -0.820652969460173, -3.70344863256169, 0.195603957686532, -0.0086798130551488, 0.150725825780715, 1.60067612447849, 1.19811076312405, 0.0533424827453554, -0.636337482247557, 0.0262667795701083, -0.461270412659054, 0.112405351075221, 1.1882148974455, -0.914347039579022, 3.45567765074469, -2.38163198521093, 0.494036750132676, -0.311692503509576, -0.17960891565747, -0.793594976492951, -0.491144259234298, -0.129088806269323]', 12.99); -insert into credit_card_transaction (time, features, amount) values (157765, '[-0.228741091321712, 0.694153443914698, -0.791232524212178, -0.929637300935088, 1.88417030489634, 1.21197483188609, 0.567927138447901, 0.478190109588234, -0.147375221399862, -0.67235194853831, 1.06036785686647, 0.443567916522042, -0.344114631006769, -0.747466317874685, -0.0780803212328297, -0.160021125877982, 0.732612868267374, -0.831640211180586, -0.763777512680677, -0.104103868884938, -0.245614316569418, -0.508031449750812, 0.240274235610244, -1.06050131633507, -0.574463794093697, 0.218103156784518, 0.150053421906105, 0.0386370668648158]', 4.86); -insert into credit_card_transaction (time, features, amount) values (157766, '[-0.536936892625797, 1.12873968672868, -2.18683861650872, -2.3947487266753, 3.74597388045451, 2.77304915682203, 1.46934944014706, 0.198257237649481, 0.313032990338939, 0.887241898400141, 0.102475656430612, -0.277539631826574, -0.529640915976931, 0.296937398684015, 0.351415725713019, -0.962592229745583, -0.719892136158157, -0.604207711043482, -0.339360635534281, 0.507733528465347, 0.0436167750436431, 0.789218352956048, -0.224979024632596, 0.743067172153576, -0.163175356615064, 0.0674699471166676, 0.408460422708027, 0.0032633063709663]', 7.7); -insert into credit_card_transaction (time, features, amount) values (157766, '[-1.02152956085945, 0.336425145137876, -0.313553263385373, -2.37574074632575, -1.24365276004966, 0.25072928007119, -0.479263773057312, 0.910717504560184, -0.789249144668004, -0.0861725498597684, -0.572896643127133, -0.363761155508383, -0.0836958283477829, 0.0598091934281915, -1.1521057990177, 2.18782899237745, -0.466857216681224, -0.170132197777258, 0.31677566113259, -0.192849979100279, 0.366116021961412, 0.814691254502319, -0.256614347607256, -1.01829855377451, 0.309920150079677, -0.132524476187797, -0.232437087988535, -0.191173238902927]', 119.97); -insert into credit_card_transaction (time, features, amount) values (157767, '[1.44596827015342, -0.967781351868595, -1.45052837548686, 0.859817986090373, -0.314611724834731, -1.03451471947213, 0.713042867716276, -0.470117187930282, 0.384601111304867, -0.0902765207823949, -0.683802476267424, 0.941012053085625, 0.933540925050364, 0.150203612318974, -0.298497933226988, -0.276476616968022, -0.247571086525235, -0.900238859984641, 0.0389941203971027, 0.457884035586482, -0.0409693487055782, -0.611986036326481, -0.0112993831159174, 0.0914627236314364, -0.241331359081248, 0.0559144286062685, -0.113001746193072, -0.0036653972797491]', 317.5); -insert into credit_card_transaction (time, features, amount) values (157767, '[1.99978188271239, -1.38106930564719, -0.510861091272523, -2.0334754298425, -0.817134643662615, 0.731285945721773, -1.16423827559669, 0.268414131815501, 1.38908881781905, -0.513332926146742, -0.386251771271756, 1.74748777966454, 1.30880640066818, -0.700658610339719, 0.242186558412984, -3.50840044413948, 1.29663521662554, -0.858386689124356, -0.634919772398698, -0.65061098961387, -0.635277574546991, -0.764227923660287, 0.509443120589639, -1.04269213223713, -0.618404149446524, -0.467387544686102, 0.130478795615713, -0.0443650156202587]', 9.15); -insert into credit_card_transaction (time, features, amount) values (157767, '[0.086425106619282, 0.900032642421067, -0.358129728643541, -0.625827628318449, 0.833285800838617, -0.522932863536605, 0.788003376137708, 0.118301220595865, -0.145030997053161, -0.641489464184196, 0.972461060906132, 0.0234535335960295, -1.24452866506912, -0.580632861822568, -0.776102448827641, 0.487809510777499, 0.281032961543489, 0.291091160971207, -0.0494196163843757, -0.0526716531419151, -0.289089643609941, -0.769640915104281, 0.119523023251071, 0.569886482808782, -0.520803820326821, 0.0961276399165735, 0.214281526167865, 0.0723993197254135]', 3.87); -insert into credit_card_transaction (time, features, amount) values (157767, '[-0.528298223645267, -0.731875642714243, 0.0178543165502528, -3.4910795918773, 0.853715479730304, -0.596612102169269, 0.0981282849859685, -0.022334028448117, -0.23732224578101, -0.708153693457288, -0.797961026021, -0.162965234096047, -0.459914517077923, 0.324375749658801, -0.280650827893792, -1.8774694642922, -0.600028323277671, 2.55465599667619, 0.652943761494375, -0.353736123644125, 0.0071644185832811, 0.487273284646131, -0.522417351147492, -1.35478446297144, 0.558119179490178, 0.162605532681229, 0.0954202515621783, 0.102829359269462]', 15.17); -insert into credit_card_transaction (time, features, amount) values (157767, '[1.91063965823867, -1.12820485024079, -0.794145211838559, 0.297596684602411, -1.00485718522828, -0.560816933295807, -0.393137877086222, -0.188708712358157, 0.207397810631509, 0.638946493340846, -1.61061811516296, 0.35464422560531, -0.109596143999008, -0.401732138754131, -1.80422238642467, -2.27700097132786, 0.551392037660403, 0.262110056612717, -0.208856659952647, -0.471477772869692, -0.676112328650823, -1.32260451760321, 0.272120914217736, 0.0228504525002846, -0.293902191779638, 0.0877073042282331, -0.0249263159662662, -0.035345281816463]', 108.9); -insert into credit_card_transaction (time, features, amount) values (157768, '[1.83021175323441, 0.0152069672643427, -2.337987428892, 1.17606911527496, 1.00728618638305, -0.874858328889014, 1.11264192547235, -0.562675866580313, -0.401655965885629, 0.276676251999552, -0.84560550220951, 0.678838781192171, 1.22564592848784, 0.598545546316918, 0.0720918356915171, -0.410685883465121, -0.615007090362719, -0.401477390442439, -0.312609959816499, 0.128320855141149, 0.2494033398132, 0.540885516556525, -0.208752897926926, 0.525472970176081, 0.613520470159627, -0.452394555852107, -0.0621459464856337, -0.0347463364019328]', 150.0); -insert into credit_card_transaction (time, features, amount) values (157768, '[2.07148002858802, -0.643035393459739, -2.59335508082669, -0.398018505419956, 0.267754188032876, -1.23944320818091, 0.551255819226493, -0.466540216859111, -1.03476959056667, 1.04756650721258, 0.226693704045929, -0.124641254042228, -1.23941849872157, 1.19880417453292, -0.759988216402427, -2.2433346505424, -0.078821883309461, 1.50061431277259, -0.342761955659529, -0.595440943188553, -0.0019115227017201, 0.431267975970345, -0.23578935281118, -0.390004613573788, 0.644798870225799, 0.126206360261486, -0.0745242507924395, -0.0840601472188135]', 80.21); -insert into credit_card_transaction (time, features, amount) values (157769, '[-0.654893457602449, -0.504969417750165, 2.08852462863789, -0.692081273411401, -1.99432552649763, 1.03533540953023, -1.03860994444184, -1.7882274597354, -1.53681301435887, 1.4773042682504, -1.24789793325666, -1.01294020173202, 0.621546642790805, -1.22212913002582, 0.327444475381256, -1.76898815726383, 1.76964675353452, 0.239060159131878, 3.0274197236083, -0.384622425125271, 1.00365701809442, -0.950172790165122, -0.352600795956006, -0.0946933663432337, -0.113930247167629, 0.201831976959137, 0.265017235009149, -0.187115088634017]', 176.13); -insert into credit_card_transaction (time, features, amount) values (157769, '[2.10677907595987, -0.119487773947513, -1.65276702993052, -0.0684392716869086, 0.72317054798864, 0.15432681276692, 0.0168147320210374, -0.0360837744269233, 0.306746735743554, 0.229391996511042, 0.0166036273004197, 0.857335218488859, 0.429323797932416, 0.344588115171379, -0.563674618188453, 0.421887614003072, -0.968818851232465, -0.0158399153899857, 0.852440662310147, -0.133342260306259, -0.31181329173802, -0.822209454281445, 0.227948167524799, -0.345095761881023, -0.157492801101496, 0.210359823345141, -0.0792818395388925, -0.0735725230598602]', 1.29); -insert into credit_card_transaction (time, features, amount) values (157769, '[2.31215661584518, -1.40036098579913, -1.09906188853936, -1.67884149524907, -0.966691773178993, -0.350210581537372, -1.08150490735582, -0.247101917064222, -1.17686243079677, 1.52295180968422, -1.77393893238389, -0.573102149496182, 1.62585310802493, -0.754227811090483, -0.158839511812196, -0.244882397804565, 0.0381553547513713, 0.168134925252155, 0.189485022007953, -0.295320135055354, -0.200778942097377, -0.0426424916506479, 0.0932433132652524, -0.994819511082684, -0.0890488350507472, -0.121408565045101, 0.0220127748438834, -0.0506505427129274]', 39.2); -insert into credit_card_transaction (time, features, amount) values (157769, '[-0.98560150441428, 0.0027488429299808, 1.06398763313686, -2.93741998475694, -0.966534532472438, -0.928180918496612, -0.296156196043063, 0.355769372472044, -2.25370181420864, 0.397292158322868, -1.42034818687006, -1.45139916962189, -0.490115405947989, -0.0904981188342745, -0.716188135153326, -0.374637836388364, 0.581737115273459, -0.027376643610651, -0.780769860884393, -0.368406694636751, -0.173621169056687, -0.195741431847051, -0.326487494513507, -0.05778834345978, 0.756139210150513, -0.0963683707021458, 0.134642617991058, 0.0270221470189308]', 15.0); -insert into credit_card_transaction (time, features, amount) values (157769, '[-0.832518298863673, 0.779776243218614, -1.25021769149223, 0.961168379063914, 1.93679892041653, -1.19328782988975, 0.845158865908254, 0.0706803968453716, -1.23824382522858, -0.0062286526330954, -1.16245367190074, 0.490039718266208, 1.25663827558915, 0.914221198488144, 0.180629025683277, -0.775171509715917, -0.146259103831779, -0.0662089028429569, 0.640991832388317, 0.301384998669512, 0.389279156438792, 0.95396381857295, -0.21373248279491, 0.535825596604664, -0.220067889657704, -0.413149049450775, 0.373665734168359, 0.0943797392282521]', 3.6); -insert into credit_card_transaction (time, features, amount) values (157769, '[-2.24225907610366, 0.977886673797831, -1.22136121561303, -1.91164763208369, 2.92000132625384, 3.41693631151189, 0.287434910569005, 0.761615914295969, 0.207793947926626, 0.430248601163945, -0.158192744778151, -0.0103354642255143, -0.320903268512022, 0.120033822318762, 0.209387155372166, -0.214302216025041, -0.463829350602869, -0.89815290716544, 0.0015722748020685, -0.517524715349068, -0.290602901102974, -0.720429751187986, 0.27567779167481, 0.701451965160183, -0.036015299838611, 0.132265813579513, -1.05160084839892, -0.161274287214602]', 4.49); -insert into credit_card_transaction (time, features, amount) values (157769, '[-1.2221713764659, 0.256941101585903, -0.743576255788344, -0.601450809623127, 2.4756253937397, -0.768980289437268, 2.08519893250867, -0.221183811784298, -1.32773901054289, -0.7220193253328, 0.0272323899598352, 0.0693511147515338, -0.830731252709335, 1.02292781258321, -1.90873380604927, -0.122744517207548, -1.0721971135384, 0.264200877792174, -1.14931582354859, 0.14299419329196, 0.50681432700793, 0.98057983240688, -0.311384871205432, 0.229188047898153, 1.30658218342333, -0.391158707195793, -0.059376548670031, 0.0978467781656899]', 137.54); -insert into credit_card_transaction (time, features, amount) values (157770, '[-0.812429320224001, 1.01094065506864, -1.22323553988197, -0.319925505906064, 4.16993705425487, 3.21989130036166, 0.800424413193717, 0.824317820458038, -1.17795923808752, -1.15659480780641, 0.0776764992766642, -0.480303274122247, -0.641185168738057, -0.829568714054231, 0.0508342884666212, -0.516964150269976, 1.08644291843415, 0.19915410528376, 0.0228717890396188, 0.110572089496427, -0.0141152138482455, -0.117176016387318, -0.573328357231758, 0.586956111590302, 1.25379125432594, -0.264792519161459, 0.0505003491334401, 0.0761262644996659]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157771, '[0.124285182683536, 0.621313516802911, 0.350324027154793, -0.998057583130743, 0.520489298431237, -0.353371956029866, 0.469196209606206, -0.891390678398288, -0.307398652962039, -0.621586459245705, 0.587906819480283, 0.931623598798837, -0.0826423948246412, 0.470920781576085, -1.17892410952888, 0.426387123073848, -0.850344724417253, -0.417858245962064, -0.394843256504613, -0.343103939319599, 0.473240431842171, -1.12580857951561, -0.182608034210562, -0.399055991484434, 0.915010313947072, 0.232855311864915, 0.0576369964961767, 0.179180014402578]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157771, '[-0.242990654164359, 0.640742823570124, 1.00165439830479, -0.822652932678954, 0.84558966048581, -0.21138764956955, 0.957826044524522, -0.250031630632065, -0.10575091123484, -0.542821347036603, 0.539499045144091, 0.97056336348757, 0.781834905462046, -0.158656243510937, -0.764025845259596, -0.208713315184926, -0.937673937296159, 0.657149482437415, 0.0542891562586466, -0.0049543680482565, 0.431838598694042, 1.61971093967762, -0.561585227500615, -0.304102255831023, 0.183391913169409, -0.0396757235859728, -0.0062036655976332, -0.0828611499443617]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157772, '[1.31017480351477, -1.34463362363981, -2.13841767197186, 0.610094475184947, -0.412229024092678, -0.755911572302768, 0.279784998895369, -0.0400181586177361, 1.2155656482334, -0.741152491080024, 0.405338330641871, -0.73481892670317, -3.20303846507807, -0.572248959400507, -0.425405982234838, 0.45817094636224, 0.902172376877998, 1.06194764710972, 0.440674580545006, 0.361808133132404, -0.0354075927229494, -0.828468730435045, -0.142090624340617, -0.517739190017701, -0.287125493332519, -0.115937241277087, -0.0983546900626692, 0.0207458635426034]', 365.91); -insert into credit_card_transaction (time, features, amount) values (157773, '[-0.491711818696287, 0.534614466216042, 0.801587359080287, -2.25190653017621, -1.16736521547938, -0.218524878215519, -1.17231908620379, -3.21271110354301, 1.57431297826684, -1.24875448961119, 1.43833237166925, 2.12610554967541, 0.524117103252259, 0.0462122543072184, -0.133160554497505, -0.389566134565573, -0.210055440174481, 0.556853288423154, 0.258460915946185, -0.749468599916947, 3.37960379836302, 0.169932521631683, -0.0133275965242375, 0.604530093223917, 0.819350075028855, -0.0290593306772211, 0.348824864675366, 0.257084004095118]', 30.31); -insert into credit_card_transaction (time, features, amount) values (157773, '[2.0599937503275, 0.0355488102271656, -1.69847308189705, 0.447573486628858, 0.254865658468333, -0.889713872963706, 0.0600810766893002, -0.122942939283161, 0.735524976185817, -0.338016005434688, -0.714079190036607, -0.678416199495559, -1.6034190902689, -0.505481778399181, 0.426328403214653, 0.307532972835965, 0.658180215739715, -0.225415738505961, -0.0430830889905617, -0.27258947427812, -0.372020093494021, -1.03813778904758, 0.378703926164148, 0.533972862782642, -0.341145201602175, 0.176557519300914, -0.0700032604061238, -0.033746549328102]', 0.89); -insert into credit_card_transaction (time, features, amount) values (157773, '[-2.46066235781784, -0.134260617371438, -1.64608133812644, -0.485049444169885, 1.13843816735465, -0.493130984360106, 0.976381643565979, -0.110134773943901, 0.3604456995989, 0.275240349643357, 0.0815082547074308, 0.513358872635824, -0.460554660788366, 0.423908929381195, -1.11279765633499, -0.156506737291257, -0.672055956515526, 0.140807802598068, 0.653163998795033, -1.37758569756536, -0.226354310213918, 0.34222638500683, 0.242484209495559, 0.241107489527039, 0.48952718920409, -0.377624950790441, -1.28852956108261, -0.443494617639548]', 71.99); -insert into credit_card_transaction (time, features, amount) values (157775, '[-1.51787229288128, 1.89601597169539, 1.08803947675864, 0.689745988369079, -0.293459936611964, 0.315342515617058, -0.259726742242229, 1.05150253689085, -0.512157031426186, -0.482111628081265, -1.28214288095566, 0.471790495853741, 0.896301657672484, 0.335454796464131, 0.753107171666111, 0.145411947450018, -0.0475694327752496, 0.183734442637367, 0.715834581137235, 0.154769893602717, -0.194721850894505, -0.585940874906564, -0.123096943110259, 0.526648157153492, 0.498110570224223, -0.656244307470282, 0.21441600250756, 0.0905057901084075]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157775, '[-1.35631757734504, 1.55650247881456, -1.83155808432243, -0.737107497251717, 0.822091233696138, -0.133242338211227, 0.442238408681287, 0.546426023550378, -0.378576140842973, 0.064692793780443, -0.335981643984759, 1.00806295492729, 0.570816779482257, 0.688531898419825, -1.54964789933688, 0.0841975508565132, -0.547707708124814, 0.0903187076919027, 0.57070597718863, -0.388329648903317, 0.138911138179736, 0.179375784011847, -0.0626948032717035, -0.0933471487199331, 0.12408719211319, 0.251553264379651, -0.831383174732354, -0.0689882418601661]', 14.95); -insert into credit_card_transaction (time, features, amount) values (157776, '[-0.483629039672677, 0.862919343428215, 0.241969230306266, -0.785441760986528, 0.427981560738354, -0.787576862182843, 1.06808034766767, -0.206278838255919, 0.351421462401874, 0.599191666340965, 0.89603893745247, 0.351590452139754, -0.950416420246187, 0.130918104595845, -0.896827140899966, -0.0498459459317213, -0.652963902994332, -0.324376971493484, 0.0618234413974431, 0.190307376232285, -0.339269120006709, -0.496306277363497, 0.151789235330665, -0.0185433136120239, -0.472956756917792, 0.109604324311234, 0.318189299839678, -0.0226858177003829]', 21.99); -insert into credit_card_transaction (time, features, amount) values (157776, '[2.12235345137732, -0.590116036627406, -1.35125081044742, -0.330565288598222, -0.467085628600007, -1.29288906259661, 0.0346033821373705, -0.479632204910543, -0.73427294431221, 0.862830726147338, -0.856820268734154, 0.448003786093931, 0.989909143442742, 0.0944840712058948, -0.281778213092926, -1.80481687129195, 0.0073501375003945, 0.39910583600684, -0.610811832591531, -0.508364741113887, -0.49637218815194, -0.858987613790647, 0.265824292385938, 0.0573870872907708, -0.206568543964115, 0.471945846077107, -0.0702951930329385, -0.0567715704560007]', 40.95); -insert into credit_card_transaction (time, features, amount) values (157776, '[2.08494970576506, -0.350520653731993, -0.708783601505585, -0.0709942367123143, -0.249444003029974, -0.222100250449101, -0.494786145421839, -0.0488541750505503, 1.36175685642087, -0.210628763092686, -1.66155916746123, 0.315050183415565, 0.537106050349446, -0.171950001653259, 0.72676082867972, 0.502210335618381, -0.892504925497154, 0.031446896116047, 0.423359658417319, -0.173698078452189, -0.262775165326991, -0.573536093596569, 0.262426807108464, -1.0228692974591, -0.352104585883983, -0.221802570044444, 0.0109086796631646, -0.0470074534292583]', 0.77); -insert into credit_card_transaction (time, features, amount) values (157776, '[2.09390858165358, 0.53401185029948, -2.91531234609916, 0.326214432532907, 1.33883326834842, -0.601534842835176, 0.267619528846932, -0.182491703530762, 0.255959522738661, -1.05337498207531, 0.810535711317133, 0.322869703221466, 0.694755780535056, -2.52670388487826, 0.456073493953549, 1.28414677040754, 1.0426426006074, 2.05689383215808, 0.0343607354792053, -0.0683086403386421, 0.0709972308706514, 0.413801551095538, -0.230228264253773, -1.6445166599445, 0.415637690784945, -0.0314731412132949, 0.0213549677806067, -0.0156481366162287]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157777, '[0.258839065931237, 1.1453971320348, -1.57573269457828, -0.45300092427609, 1.13293192656881, -0.269520574963918, 0.455688213924199, 0.333666102250306, -0.415155350819534, -1.0118162930503, -0.0062858202328939, 0.481708589418944, 0.763384283018362, -0.62344775425611, 0.0396604258591865, 0.75003680173846, -0.0597849403509406, 1.53696423233389, 0.46779224766643, -0.172033539850104, 0.291105530387901, 0.863549010613311, -0.295847639480309, -1.50680307363793, -0.11416885136106, -0.0805547294325712, -0.0629772132992395, -0.0684703785402445]', 1.5); -insert into credit_card_transaction (time, features, amount) values (157778, '[-0.102318316251731, 0.355017385142264, 1.4729474047879, -0.267198469329434, 0.432963313649831, 0.864003581834754, 0.170403656950197, 0.0894079849153625, 0.0681694778015647, -0.13876815989909, 0.390471602207007, 0.544438214826899, 0.521064806462692, -0.399394273993292, -0.0070969403901762, 0.0413247041760433, -0.646901948601163, 0.810754270786257, 1.17321864421709, 0.20274326752777, 0.231805215223454, 0.980055521347744, -0.252267747871963, 0.304314999476033, -0.513289491251356, 0.658486645372563, -0.0088058684746288, -0.060263478647028]', 11.5); -insert into credit_card_transaction (time, features, amount) values (157778, '[1.78885650099444, -0.620721353303257, -1.29683818060075, 0.312485231876388, 0.160377841021539, 0.19213061552681, -0.0826120878409747, -0.0104654682919457, 0.451343753398159, 0.180742863611422, 0.351711310538646, 1.04488788405264, 0.609121115143989, 0.196760470711252, -0.392266646646408, 0.480538783404065, -0.949356935866486, 0.307028283308058, 0.359981850445685, 0.137656758835248, 0.0530947014703609, -0.0287710389485747, 0.046576215739148, 0.130467585542789, -0.158868745309286, 0.196682086122215, -0.0703939656537369, -0.0391379534370372]', 135.87); -insert into credit_card_transaction (time, features, amount) values (157778, '[2.06909916910199, 0.0397052035519738, -1.06398693868696, 0.389424959053613, -0.0036415044140161, -1.14985812850832, 0.265593848041661, -0.400595677414124, 0.360015730537229, 0.0377184852461005, -0.586878624187003, 1.07099011665861, 1.30196708505851, 0.0272995760690688, -0.0902466627413603, -0.144927176995156, -0.380598420791667, -1.00029649221806, 0.161291828303106, -0.145422282146189, -0.279690652576102, -0.609487261059133, 0.31858653504276, 0.0093056222660505, -0.248349374596992, 0.195725014727467, -0.0626385646269889, -0.0580654173897355]', 0.99); -insert into credit_card_transaction (time, features, amount) values (157778, '[-0.280386396725125, 2.05643735762257, 0.534355930918401, 4.18256033813513, 0.914642401455556, 0.715753461101099, 0.538351359728649, 0.338910769066097, -2.75509007784256, 1.24137802040785, -1.24904654255637, -0.247220129209848, 1.55446248616795, 0.546797647532527, 0.838776137080321, -0.0421295629723352, 0.0423417610365934, 0.300246569601367, 1.14222589817074, 0.168664606962584, 0.337966688586995, 0.941663240063254, -0.299339986619958, 0.53320250153497, -0.042557735542329, 0.55670703594055, 0.039420864571738, 0.103543010269652]', 0.76); -insert into credit_card_transaction (time, features, amount) values (157779, '[1.0134097597409, -1.9655360588414, -0.708390208894882, 0.78124302946241, -0.194990511214701, 2.36979931220596, -0.581227199737161, 0.632245206200184, 1.47045899796536, -0.516921847812739, -0.357660982930948, 1.09700220655567, 0.282846558500045, -0.403394496130535, 0.480205938337181, -1.20073431686844, 0.985619728378594, -2.35268009309668, -1.4600415689333, 0.499063633916394, 0.102240451946455, -0.167278676850877, 0.156677992105042, -0.655062378629036, -0.898178946869809, 0.112042163128384, 0.0023162637562903, 0.0225791241904814]', 406.5); -insert into credit_card_transaction (time, features, amount) values (157779, '[2.03677345725835, 0.193002540918551, -1.75160139762415, 0.54922211534906, 0.18191310139789, -1.46146921927532, 0.257708311470463, -0.359733982392946, 0.619170569916506, -0.518355848745698, -0.306505743754919, -0.0562179477206154, -0.238917061163892, -0.780443127329162, 0.981247727886079, 0.188504094327591, 0.546085695896767, 0.484974419641384, -0.520129596065853, -0.213010033011811, 0.196540228077392, 0.728276767612655, -0.017493670483, -0.0917350122553697, 0.228576764241645, -0.0981131052530824, -0.0004629771078641, -0.0289234351047625]', 8.98); -insert into credit_card_transaction (time, features, amount) values (157779, '[-0.953238505615653, 2.01717562940193, -2.16473841210852, -0.590454640775954, 0.450714815121361, -0.684606111148835, -0.422010485683253, -2.1476043732179, -0.893040890683037, -1.05089177491157, -1.47208397708579, 0.775888968278593, 0.306591591088268, 1.30680464378162, -1.03888670278806, -0.202829941659205, 0.117920147436086, -0.538876393285495, -0.286637497058584, 0.366296835496053, -0.982736814549142, 1.13839618665175, 0.198279944588642, 0.728502527744802, -0.326472430753723, 0.503456319711958, -0.154502789382597, 0.0494869112409223]', 0.76); -insert into credit_card_transaction (time, features, amount) values (157780, '[2.06781851306589, 0.104644818473505, -1.88233553368743, 0.186163653052426, 0.719439201649155, -0.276746819297447, 0.0780962269578774, -0.0639645409492846, 0.25229724103368, -0.211215868042542, 0.714489892750947, 0.729101792575819, 0.165676782665825, -0.697226186149773, -0.470997224178535, 0.64937272645024, 0.0406792521941312, 0.333277045739408, 0.524690552764447, -0.124251806292644, -0.34410214116787, -0.912771001091965, 0.266898474215621, -0.0006499218590423, -0.219808198103312, 0.184000484438893, -0.0663427438499875, -0.045463192563996]', 0.99); -insert into credit_card_transaction (time, features, amount) values (157780, '[-1.00095108167436, 0.0926641167751102, 0.993433700312233, -2.37293470003817, -0.828563658732537, 0.447451717943579, -0.0306836712000791, 0.229574327294367, -0.716573063136824, 0.123317126768489, 0.65320676846542, 0.306755402265459, 0.861406145904901, -0.771620096732248, -1.36128080040317, 1.50862175205157, -0.369610905379354, -0.565533709315208, -0.034173917044718, -0.127527282854108, 0.574577495609956, 1.69848764543759, -0.245973485269818, 0.786508030681239, -0.233665344307878, -0.224636046667381, -0.465867239980456, -0.145249429858136]', 99.63); -insert into credit_card_transaction (time, features, amount) values (157780, '[1.80402729010402, -2.04594918249489, -2.03183687980939, -1.50208853905351, -0.896096915629037, -0.971482678299379, -0.117744364374252, -0.529923446606477, -1.76406653919984, 1.52379208510727, -1.37582485362172, -0.953328937904946, 0.834740156702428, -0.011332020539433, 0.151632174441215, -0.405426877640654, 0.184321218702203, -0.151580958715886, 0.0897142959038938, 0.213882804399551, -0.173125159325849, -0.758588070440682, -0.0683581935558691, -0.738910045975062, -0.181430394348902, -0.301734407697735, -0.0795126595948357, -0.0111360382367686]', 319.99); -insert into credit_card_transaction (time, features, amount) values (157781, '[-3.60040535002477, 3.37524390240019, 1.16154086116526, 2.16935186158576, 0.0972442717562901, 3.48277723336278, -3.49208787302232, -8.98538373659828, -1.010034161261, 0.716370984091628, -0.701455945783577, -0.295982297681442, -2.25665180292854, 0.791144257934859, -1.48954231088906, 1.75718070250106, -0.499024229491665, 1.16459520090701, -1.66334581247123, -1.03857031888746, 5.79689883638001, -1.6312361405125, 0.668684566928378, 0.0057695045405777, 0.613965220646946, 0.171247477194366, 0.304495914014083, 0.169033240489043]', 8.31); -insert into credit_card_transaction (time, features, amount) values (157781, '[-0.926530016935426, 0.552819758126288, 1.02101606870697, -0.56145619530983, 0.286978089461931, 0.429921046548355, -0.240833171475264, 0.779094719217207, -0.0889682025711841, -0.949481719104565, 0.129912320302033, 0.519085559886705, -0.369264909172681, 0.492552884286289, 0.0182917238995829, 0.402471482886646, -0.592370314465078, 0.72549363504051, 0.764600577427886, -0.0564104546495315, -0.0324616641790198, -0.342450227274175, -0.0493663571994011, 0.172209458445337, -0.28670858188023, -0.549882533672813, 0.029676237606545, 0.0293976301892023]', 10.0); -insert into credit_card_transaction (time, features, amount) values (157782, '[1.99420007382194, 0.20328209088513, -2.22167546044555, 0.919224564867899, 0.334464973210506, -1.20236454726703, 0.0854832415120591, -0.15169093557666, 0.908378668820332, -1.03308819688495, -0.201889286682662, -0.804728288805386, -1.78826429436411, -2.32900233159897, -0.164745181451475, 0.27107971396419, 2.28493581907534, 0.635223873172831, -0.457834732566073, -0.225464982597318, -0.0094999376291866, 0.192975393388965, 0.0561449983873097, 0.907103269554833, 0.109863848070806, 0.677949478246875, -0.048309398780374, -0.0044567957004425]', 12.31); -insert into credit_card_transaction (time, features, amount) values (157782, '[2.06611903766989, 0.146688440940063, -2.77421847595329, 0.284229499356089, 1.08884530586723, -0.736788000680978, 0.549751660944165, -0.212392867022638, 0.0362142805102205, -0.174926365627297, 0.684277478770633, -0.0661757510162737, -1.30999300941029, -0.321066017856137, -0.660527649495515, 0.114580030676273, 0.589319219530518, 0.514893253061197, 0.337266642486896, -0.194768736004111, 0.0475876530702867, 0.202438262493501, -0.0791494940933178, 0.163797400828135, 0.369052099496389, 0.695610417284528, -0.114180681306726, -0.0643989958084699]', 19.0); -insert into credit_card_transaction (time, features, amount) values (157783, '[-0.979878896179132, 0.522062312058962, 2.01258301551263, -1.18247142890477, -0.0170107201378416, 0.127065921655057, 0.376307500997139, 0.217552591188037, 0.104611886870281, -0.876101264409803, 0.122635490710218, 0.13327557076538, -0.708813119843512, -0.13586137394032, -0.840978782361654, 0.798200430969386, -1.0323014880277, 0.758217704127001, -0.394200712799383, -0.145651159958244, 0.19794762160684, 0.521943775921732, -0.511829845422854, -0.297383447825327, 0.575334423118718, 0.597587947747104, -0.15037960011195, 0.0398573096008523]', 28.75); -insert into credit_card_transaction (time, features, amount) values (157783, '[-2.43447321443071, -1.49630092261442, 0.988123243933406, -0.185585085496054, 1.63736629712212, -1.28897188033997, -1.05892166209401, 0.69146823642827, 0.163342353480053, -1.16002343833251, -1.16989599544257, 0.330159212543466, 0.25895474896615, 0.386305625295146, 0.734111911105668, 0.438046735243131, -0.52953227760122, 0.15030146155238, -0.333336569232114, 0.475120614509924, 0.166263692749722, -0.493615282569969, -0.0437927036812678, 0.579518966227291, -0.295912368361664, -0.660305404762921, 0.0638148727303666, -0.278890680506288]', 1.18); -insert into credit_card_transaction (time, features, amount) values (157783, '[2.07439814554867, -1.20023839307236, -1.00340453983047, -1.15969893963708, -0.473629259057983, 0.497460234902729, -1.06717287054404, 0.123267623806147, -0.152889132789216, 0.856702417553234, 0.193237104707309, 0.142038244838355, 0.769863559805138, -0.430140926075868, -0.41684473448237, 1.55715196616014, -0.427964325276582, -0.466826410708433, 0.984986838831341, 0.175708428553576, 0.356062279085961, 0.948192103751228, 0.0010807285451168, -0.156149082121745, -0.0638014486663824, -0.0890644644358541, -0.0039194555651569, -0.0496404707551375]', 69.0); -insert into credit_card_transaction (time, features, amount) values (157784, '[-6.83494585506618, 6.01149920932796, -3.76166846494157, -2.38438038184422, -0.951454362918691, -0.69396007181302, 0.0287032185130134, 1.11973462385617, 4.66964640367519, 7.81788492428989, 0.19585355042168, 1.12951707766327, 0.461511601028897, -1.17332423240942, -0.695849051709386, 0.0494065408354222, -1.01078774988656, -0.303315732077302, -0.213116414489196, 3.28374639857706, -1.07213122092326, -1.21565617827113, 0.314256724601256, -1.20985429374393, 1.05034170829954, 0.257051456492317, 2.30558304027547, 1.25372599380128]', 10.72); -insert into credit_card_transaction (time, features, amount) values (157784, '[-1.61453549413703, 2.23655506897636, -1.40665957136483, -1.07459976320833, 0.713048441531505, -0.412666008627848, 0.697932203774938, 0.257758782622531, 0.831307090790867, 1.26618973989421, 0.86969423441911, 0.85338194994886, 0.54029910203655, -1.29729730689968, -0.877221954184634, 0.513154755554104, -0.0400221598274527, 0.236200752589882, 0.0124765900635108, 0.773529114025214, -0.486337679659915, -0.863372486405895, 0.121597789108536, 0.166925261406621, -0.0885963882884426, 0.103197289248606, 0.418249661372906, 0.186256617321987]', 9.84); -insert into credit_card_transaction (time, features, amount) values (157788, '[-1.23806870081621, -0.241370910316551, 1.78951666107227, -1.95849788995376, -0.630024063624882, 0.1826377184353, -0.68559739383919, 0.599707185311589, -1.05219984102774, -0.625705991193626, -1.20483792716033, -0.242677147569136, 1.5731595832371, -0.759474973418733, 0.125146765617839, 1.68037468315652, -0.0737421236078771, -0.759565502043703, 0.413325963181539, 0.371066566625343, 0.359032963552828, 0.628953747373009, -0.205918640016089, 0.5177493434165, 0.499011592427931, -0.133753572686875, -0.0696998679487452, -0.0483639740316609]', 66.09); -insert into credit_card_transaction (time, features, amount) values (157788, '[-0.0538441777189786, 0.516663067015787, 0.702899966237766, -0.425265521708626, 0.0466963615380727, 0.151970801546386, 0.0979226019228953, 0.0479308608149707, 0.72430240930352, -0.266566681916688, -1.5719018814677, -0.330003472536231, -0.189827166107374, -0.326443219904772, 0.172896927417679, 0.206757051068396, -0.580001578083732, 0.387909419609355, 0.171883669721597, -0.14041993430956, 0.334035812950463, 1.0387651788967, 0.0387459363526379, 0.525989467303559, -1.37831327929168, 0.398160260245502, -0.007013475458329, 0.268774433185507]', 11.5); -insert into credit_card_transaction (time, features, amount) values (157788, '[1.90483460877212, -0.680000949574439, -0.516134896317598, 0.396361237267193, -0.619690794280313, -0.0645270298795779, -0.680489386135686, 0.0679856103737888, 1.350639076842, -0.0072222218139201, -1.28367658489775, -0.0627387235976184, -0.38349524510082, -0.157458684592997, 0.47762663827315, 0.438326046107281, -0.544215113179838, 0.179753226817695, -0.192474034989205, -0.080835502191962, 0.168845716888357, 0.51953624932574, 0.133577490755637, 0.620046481296115, -0.275699558240373, 0.541108591518084, -0.0386475470016383, -0.0333449831255197]', 64.99); -insert into credit_card_transaction (time, features, amount) values (157788, '[2.02060192477424, -0.113312080659788, -1.18116849832287, 0.230234223145931, 0.0979436411472906, -0.691716504228536, 0.119542569810986, -0.195272326402994, 0.235979527083364, 0.224522743893134, 0.746702427235777, 1.25566787298096, 0.47621521618637, 0.368030445885188, -0.683820453791438, 0.165316884917122, -0.679750102064181, -0.32153937361557, 0.549563712323539, -0.152055810665382, -0.246750499064289, -0.615445049665521, 0.273130862984504, -0.32339939116368, -0.275103485529216, 0.19562810759799, -0.0742163810614929, -0.0704639708833981]', 12.99); -insert into credit_card_transaction (time, features, amount) values (157788, '[1.97681586145809, -0.300227574124501, -0.202509829270536, 0.514450296628804, -0.688378361578636, -0.577494048178286, -0.498154426432531, -0.147607737908881, 1.2479949784983, -0.208564405031669, -0.751244885604305, 1.262623088601, 1.58765070285988, -0.491428774983362, 0.313639531784825, 0.0083111493676174, -0.587018056256389, 0.0205127939159817, -0.237851044829026, -0.127056989823762, 0.20988686289498, 0.936274049867588, 0.0995308658620479, 0.0866056783142172, -0.0451967504276541, -0.21912933157175, 0.0513469735634152, -0.0332469539016636]', 9.99); -insert into credit_card_transaction (time, features, amount) values (157789, '[-2.07189825678866, -2.89725197851471, 0.915629533410171, -1.03671855444872, -0.0615598270327908, -0.856319052934606, -1.86418245203782, 0.98893820487952, 0.0179712896745276, -0.206299713917169, -0.600998459503273, -1.24978947256139, -2.91337643219801, 0.152993940439434, -1.62757341889876, 1.44907395301715, 0.424859254000954, -0.380859073037304, 1.08037602445019, 0.577281686862415, 0.278026934451293, -0.329678654841556, 0.172955274048497, -0.41193745945975, -0.18795114859601, -0.37306535214685, -0.105579519748476, -0.438733444508114]', 101.79); -insert into credit_card_transaction (time, features, amount) values (157790, '[-1.33847170533031, -0.111245308432117, 0.321350739432179, -0.105076259064268, -2.74654469384719, 1.14779886831328, 2.37939175304536, -0.129443494240711, -0.0036474432747553, -0.581719463774343, 0.73225500347074, 0.0065964417418837, -0.668367515770877, 0.154513694170835, 0.229227555569845, 0.888000487683456, -0.842977026522441, 0.908178014533206, 0.0311094077957141, -0.502696107127784, 0.112415724077736, 0.840739034158676, 0.222557740208872, 0.126270742747746, -0.0423189404819935, 0.390042672122973, -0.179813204908807, -0.426970486753851]', 572.9); -insert into credit_card_transaction (time, features, amount) values (157791, '[-2.70324614823207, -0.340501685859222, 0.728988015887111, -0.0787558038947305, -0.214525421514046, -0.16414946891801, -0.0414199275384106, 0.903150308388252, -0.266103449304912, -1.43049553170244, -1.15783365854529, 0.245259202785765, 0.374256667601856, 0.561935615802697, 1.14336551538312, 0.459566952317976, -0.191384396005968, 0.230225487995711, 0.359369728730184, -0.218679023315111, -0.0856197166348758, -0.453883543919644, 0.535629709988353, 0.575731744543518, 0.496849461577905, -0.419972793971856, -0.0157496148585376, -0.59232023806864]', 68.82); -insert into credit_card_transaction (time, features, amount) values (157791, '[1.97054751776093, -0.760623421427038, -1.67157026037189, -0.637687109696004, 1.6652902680225, 3.92653078274165, -1.30440982698839, 1.05872763846903, 1.11058953814946, 0.0237403500193585, -0.216871341471088, 0.371081672934286, -0.0223005581197026, -0.0622073906825891, 0.76694010262227, 0.244276330096594, -0.566969378451654, -0.127845508391831, -0.393274463401349, -0.110734387951164, 0.160351657608665, 0.564189165496309, 0.202586142725311, 0.759792872726705, -0.245286156758252, 0.589136426517134, -0.0002525065755098, -0.0529491958647838]', 11.5); -insert into credit_card_transaction (time, features, amount) values (157791, '[-10.283840326559, 8.73711360390633, -6.25330974661393, -2.45024877678851, -2.56093879594621, -1.33378879234573, -1.25946016721643, 2.73580670425344, 5.88774663796836, 9.67169006809798, 1.30871552526723, 1.94769160921491, 0.548987944031479, -1.91738077821551, -0.547095584663062, 0.237957570618949, 0.704478801108747, -0.299044465112427, -1.17118782944075, 4.12650511602013, -1.28080026741558, -1.41057724201119, 0.720097726241932, 0.460297611367704, 1.44526002111981, 0.125872714560615, 2.09049364024244, 0.856336026652095]', 9.84); -insert into credit_card_transaction (time, features, amount) values (157793, '[1.70426112012253, -1.21723015184258, -2.6590138769852, -0.16962221378476, -0.0995270934332791, -1.65210398193167, 0.970277658633988, -0.768445643973197, -1.22169456048433, 0.897693011540047, -0.918536993788862, -0.0791270371168364, 0.256962111023529, 0.720436402586334, -0.328788215028114, -2.32369095262563, 0.248242692450853, 0.539097376352781, -0.83078590128427, -0.0647737252828582, 0.0743359531383701, 0.242295510706484, -0.333876428269169, 0.0808861447671155, 0.39209091536391, 0.992057881423392, -0.170347997344765, -0.0431583663526275]', 289.99); -insert into credit_card_transaction (time, features, amount) values (157793, '[-0.941075928255147, 1.28633024228262, -1.07687293442658, -1.39046125326578, 1.43061052775681, -1.23053906433383, 1.73407122127421, -0.542389222190825, 0.212248655442623, 0.959118897606692, 0.621014855315113, 0.269938275195855, -0.546320069292819, 0.475047431052903, -0.671344860128032, -0.536315480872384, -0.875355875867887, 0.0920936944304808, 0.185843559174571, 0.195725437872443, 0.089002743620273, 0.964125006335455, -0.12043648313724, -0.427629160702855, -0.137407325198694, 0.0866793615809219, 0.494364656059916, 0.163389410493054]', 2.99); -insert into credit_card_transaction (time, features, amount) values (157793, '[1.40881559177793, -1.55713284586253, -1.13491976241115, 0.345679637936459, -0.654766466863484, 0.006810677876549, -0.188424483665475, -0.0829263009312008, 1.17067106218679, -0.0934368723754421, -1.75493489590746, -0.301603380671381, -0.0141160580170873, 0.0261619745824533, 1.08963463844386, 0.843983925732166, -0.93005246277163, 0.433402569407785, -0.162612788749123, 0.518393435909588, 0.318678698796014, 0.270905737949466, -0.22917623162061, -1.00418347723432, -0.367749434467483, 0.684483858935735, -0.101795841969133, -0.0004027601922978]', 352.32); -insert into credit_card_transaction (time, features, amount) values (157793, '[-1.1899796712283, 1.89133152014838, -1.50382624216855, -0.992897074673071, 0.740751862618331, 0.570557901130913, -0.287722069688846, -2.0111499604055, 0.248511132178709, -1.04981077617008, 0.233052089272971, 1.19617566027916, 0.81630393050234, -1.3566394103766, -1.33717529319061, 0.566678551320692, 0.643196984946578, 0.889065393449315, 0.481156217036166, -0.713867019432395, 2.18901942970767, -1.13963188370464, 0.260885070471903, -0.290936007890761, -0.0941916505802669, -0.179866204141953, -0.377582941100181, -0.0309089405483861]', 29.5); -insert into credit_card_transaction (time, features, amount) values (157793, '[-0.0354484927244249, 0.730175148017973, 0.330132311329335, -0.674381883359044, 0.407005295234552, -0.786659113463449, 0.852747280344624, -0.0035221742108129, -0.215483630309981, -0.233704399734699, 0.789823718839538, 0.538536864697287, -0.723863511660823, 0.44676274091715, -0.992120607045315, 0.0499755865673419, -0.536108856638944, -0.289741615224721, 0.105397280446734, -0.0627986867173875, -0.200565479906558, -0.473075582106466, 0.0954852428414791, -0.0068473172003214, -0.564490397539484, 0.122724199658887, 0.240348445434052, 0.0868966699629609]', 7.16); -insert into credit_card_transaction (time, features, amount) values (157794, '[1.5054188142728, -0.663141131019519, -1.82721902533205, 1.50291579164055, 0.123218519731032, -0.805778420080681, 0.809267781049699, -0.291916324702562, 0.0399271703654445, 0.338321858789789, 0.656092031455265, 0.585527683531508, -1.193889690807, 0.965122231842391, -1.09845048067001, -0.494213906317943, -0.289452788942982, -0.0351413041283715, -0.0383327184291764, 0.149872184084339, 0.245722187709739, 0.301197007932837, -0.209492887345876, 0.0121126993617299, 0.29705294597988, -0.53538427156362, -0.0704194261207085, -0.030524233283834]', 253.83); -insert into credit_card_transaction (time, features, amount) values (157795, '[-1.09524449799202, -2.08486258833577, -1.61282104198312, -1.65028590912733, -0.69943692831602, 0.513547047736151, 2.73329184994019, -0.284772443308236, -1.5750877294259, -0.246401417558659, -0.181472804964862, -1.02655085763717, -0.94510976484046, 0.371276828671496, -1.75649263483503, 0.854378647728466, -0.0874402403379363, -0.579409792095228, 1.06566347983326, 1.50284547037691, 0.750287653327273, 0.839512686258899, 1.44625649225825, 0.0320225941007407, -0.263077226122788, -0.259622976586242, -0.0652480312764561, 0.265176912943714]', 675.0); -insert into credit_card_transaction (time, features, amount) values (157795, '[-1.1000160779094, 0.291211950319425, 0.157204771254036, -0.630805393549851, 0.0453442932722407, 0.370754662351859, 0.988364209672035, 0.476960215105395, -0.688994122996438, -0.996703117078864, 0.175292946428921, 0.742694436065353, 0.354052102776272, 0.474695881146295, -0.864716846831595, 0.534585823528542, -0.78082901526066, 0.50235661240969, 0.131142532676325, 0.320292751086516, 0.247227514668375, 0.179540077546935, 0.319905550315546, 0.35679127720391, -0.126108599448645, 0.151868724601958, -0.097839476874566, 0.0690080900724724]', 209.85); -insert into credit_card_transaction (time, features, amount) values (157798, '[1.88636805509399, -1.69106924878415, 0.172131498017553, -1.03945748508987, -2.10528535901864, -0.479979542022299, -1.48133707242017, 0.0412689582262737, 0.939901653906973, 0.43224136958161, -1.12868754288559, -0.104254024427807, 0.116612533517988, -0.522228783375368, 1.05070826482395, -0.839808201109878, -0.319475822040389, 1.71351266618556, -0.912773601270047, -0.355056414475206, -0.100139912822088, 0.119542699214534, 0.242156321689805, 0.0709727951370877, -0.776636067064766, 0.864146376838571, -0.0119149596761949, -0.0168288622922416]', 120.75); -insert into credit_card_transaction (time, features, amount) values (157798, '[1.89969467743245, -0.683079288017006, -0.43764357746394, 0.454744961831374, -0.749998570682082, -0.285773891366412, -0.639655171261453, 0.0085190773210286, 1.37061128932421, -0.0088333309115908, -1.38817600090682, -0.0496881503828339, -0.341784204535597, -0.155226560725719, 0.491720089117549, 0.408714051724439, -0.537683192278867, 0.115614878232876, -0.201478015447254, -0.109308416806466, 0.167824668261193, 0.566092185530666, 0.0794297783880152, -0.373060634318798, -0.281931873520492, 0.592690630312245, -0.0305438387986692, -0.0429024290883929]', 64.99); -insert into credit_card_transaction (time, features, amount) values (157798, '[-1.56614371337096, -1.10693239810506, 1.77284847898343, -2.28493973369918, -0.264700990447496, -0.161627137716695, 0.127037332024835, -0.0861226204207469, -0.563170732863897, 0.250466538012205, 0.323031405000328, -1.49108959090539, -1.75437162498233, -0.363816133964697, -0.313715336960086, 1.83562204227253, -0.589120866101788, -0.149860091600641, 0.135215891538, -0.119417289762808, 0.324400436745769, 0.981932507551466, -0.262115931098626, -0.403542801772277, 0.658971419543815, -0.0541286457657929, -0.402749386959748, -0.0046031863982481]', 127.75); -insert into credit_card_transaction (time, features, amount) values (157798, '[0.0717710443982317, 0.753516692410123, -0.984974259008293, -1.24756611258667, 1.71319288379423, -0.63812538392805, 1.60438741913532, -0.5405278809027, -0.404328116091301, -0.0401934976728908, 0.616694543219629, 0.377847497308172, -0.172795688280997, 0.553395785357984, -0.595742280806656, -0.406635308584287, -0.881831437583427, 0.121085223740003, 0.300454949134101, -0.16062321024601, 0.204559542765417, 0.728217503866964, -0.263298198562384, 0.270649307683319, 0.228751199132963, 0.0973390325057113, -0.467004343031063, -0.266497894160752]', 7.7); -insert into credit_card_transaction (time, features, amount) values (157798, '[-0.444765598861338, 1.4627002885693, -0.880433959796999, -0.556376131927674, 0.616283347546082, -0.884929262646801, 0.65443010354292, 0.291004051506747, -0.114848220369264, -0.7694764811407, -0.732539713278964, 0.369788145204632, 0.685989688752277, -0.893586952353969, -0.325634003133353, 0.414216351739519, 0.481519585730879, -0.260239286706494, -0.259291156266131, 0.081566767767721, -0.323589916959774, -0.825590009077581, 0.14828898750374, 0.571969365975727, -0.321968248331121, 0.118447678763248, 0.210471038850441, 0.0790120613342076]', 9.42); -insert into credit_card_transaction (time, features, amount) values (157799, '[2.03366408140585, -0.0833393815847641, -1.17305539330393, 0.211189610999452, 0.14959928275766, -0.604363683345264, 0.0938741840653013, -0.169100508228718, 0.228032031805312, 0.219556109328809, 0.79842057185103, 1.30147264544246, 0.526854962992368, 0.359733156346715, -0.643201984182282, 0.105300913566589, -0.630077193524295, -0.416557445454839, 0.484176487231363, -0.176936883853522, -0.247493639344885, -0.583147784274602, 0.287797107760436, -0.381990204604314, -0.283074969671472, 0.202297184485535, -0.0686148773088367, -0.072912980623324]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157799, '[2.00145510449199, -0.3640913493235, -0.505150794759056, 0.219068606484759, -0.456185848574338, -0.369052650094353, -0.487073857691969, -0.015589597393387, 1.02205274237803, -0.0093018226952011, -0.836523616955133, 0.32769854422222, 0.105261622254801, -0.0629508169127828, 0.566749597818622, 0.454491906522139, -0.535872111010472, -0.448028196133696, -0.0081160894693764, -0.144538038084023, -0.267001452049833, -0.725826540128248, 0.465148517872478, 0.719175806945812, -0.626860750943678, 0.19855587433563, -0.046282506461219, -0.0355115776401416]', 16.9); -insert into credit_card_transaction (time, features, amount) values (157799, '[2.13414538455416, -0.661133756271348, -1.62020309454371, -1.80997787279354, -0.493490957186542, -1.65088868752532, 0.0492398231276711, -0.394477536561428, 2.4796692887107, -1.28128021128026, -1.00824035250406, 0.612818792606274, -0.921740936016974, 0.350522934108258, 0.361087432136657, -1.6197206563663, 0.26256794374308, -0.0363243555034819, 1.28656592455884, -0.301006891099887, 0.169722443010636, 0.93537256888383, -0.103470706404273, 0.0331165628042509, 0.550642274269616, -0.551365312090925, 0.0323452695913875, -0.0645029207216555]', 0.23); -insert into credit_card_transaction (time, features, amount) values (157800, '[-4.71915049006679, 1.59252490416968, -2.77258664723401, -0.498435936843101, 0.0862327867792849, -1.28217641634285, 0.110770674355989, 0.621997425154314, 1.78121060829476, 1.89354129619428, -0.89978516738163, -0.049430419132411, -0.256056578737117, -1.12021664474182, 0.136701657768248, 0.646386275540903, 0.509462863953576, -0.276863394154898, -0.144206613551039, -0.840948552959527, -0.969393619172675, -0.848938034479947, 1.01278059333581, 0.478191586938237, 0.169007371363003, 0.0875961383361338, -0.324330891455179, -0.515202678666404]', 8.96); -insert into credit_card_transaction (time, features, amount) values (157800, '[2.12667843180652, 0.133713443950872, -2.42777775999825, -0.096190961163517, 1.24382599776436, -0.371659310695292, 0.626161813595055, -0.288448829506422, -0.092206427167988, 0.191698543086133, 0.388735065111448, 0.954648513131259, 0.551570612664994, 0.822799917368543, -0.207282566708548, -0.194168910125332, -0.892265401023494, 0.182727892336413, 0.557631096372231, -0.155880921197694, 0.111172616944129, 0.420920095209807, -0.0957957580094313, -0.165403955024978, 0.531199584254473, -0.162307976902683, -0.0582324650055861, -0.0812866001290752]', 5.9); -insert into credit_card_transaction (time, features, amount) values (157801, '[0.0887065212412666, 0.671882530527959, -0.328513081669109, -1.05325255415979, 1.12358263889934, 0.196045567863838, 0.716812566827932, 0.192173702280555, -0.0114290786690494, -0.201183642288358, -0.469416836360925, -0.379908560318137, -1.38654065868403, 0.532065928907626, -0.813704804217099, 0.516036796028196, -0.988442457520956, 0.320782290568175, 0.634688866187384, -0.0637802489863149, -0.304158150648714, -0.838992116765941, -0.0266499361434722, -0.399958478397064, -0.408975086103619, 0.158634024864416, 0.227705074155744, 0.0799647221145074]', 0.99); -insert into credit_card_transaction (time, features, amount) values (157801, '[1.9735382184824, -0.147425138707456, -0.599246028867224, 1.08804878544682, 0.0732754100694228, 0.383364645579075, -0.451485731702857, 0.0982676112933362, 0.90663549383973, 0.128761867448397, -1.4651525474147, 0.32735165650902, 0.533903566628463, -0.136347095302895, 0.543279076679071, 0.531401513975966, -0.902928034118601, 0.0022829410542289, -0.258475490943602, -0.162518793580638, -0.204209320059014, -0.500164386275119, 0.308062419687576, -0.0408613540802333, -0.271705466889993, -0.929683420196922, 0.0549855011854161, -0.0217298188919691]', 19.9); -insert into credit_card_transaction (time, features, amount) values (157801, '[2.01830670288122, 0.0931911700577121, -1.60942403841763, 0.348380177241888, 0.358500129930782, -0.669727481531726, 0.0691712544751756, -0.0866844517300812, 0.261000291569162, -0.202013781975235, 1.25386058917496, 0.758184250024602, -0.314348565226374, -0.584543685131868, -0.4802515494999, 0.470483892452355, 0.305771983743395, 0.158658560182585, 0.273490970439248, -0.167240773196018, -0.303477276538758, -0.819197993835738, 0.353464826937627, 0.662657093125669, -0.32213878650529, 0.143428186684445, -0.0680184523112714, -0.039252929058807]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157801, '[1.97560988443601, -0.817668328450572, -0.525335964834477, -0.904969880073108, -0.554565913008623, 0.129656949366575, -0.827775847769124, 0.0236044256365399, 1.69438094609917, -0.521669296698851, -1.20404430539154, 0.978779468346732, 1.75375048894336, -0.637687818930429, 1.01691665173731, 0.551238775272759, -0.879625304752796, 0.159658354835614, 0.40476816657131, 0.0910090554521392, 0.0261771051875942, 0.188393994522829, 0.189203096617308, 0.118325879901473, -0.439152455777008, 0.534854161742983, -0.0207366959673776, -0.0298431563004567]', 60.76); -insert into credit_card_transaction (time, features, amount) values (157801, '[1.91287333121634, -0.416397195209376, -1.83478074831675, 0.355999626944455, 0.166662748657346, -0.905560750342791, 0.404800849619557, -0.234917067784546, 0.361806013944991, 0.286331550014571, 0.271153631848679, 0.131214427717345, -1.64812143327027, 0.908130262815438, -0.948889902075486, -0.198725558743612, -0.348971679440399, -0.0472083879472373, 0.592916702819985, -0.151136198935177, 0.026626676054661, 0.003787006106764, -0.0269927621737257, -0.311536580442517, 0.110858216809369, 0.557599446584875, -0.125910463060418, -0.0794813664768505]', 84.98); -insert into credit_card_transaction (time, features, amount) values (157802, '[2.0579682372007, -0.0684551655947941, -1.09797955689948, 0.39351780275777, -0.0867946578808905, -1.0909706649568, 0.162363103157028, -0.299255940455945, 0.559294751777712, 0.0676338175553091, -0.769976535487005, 0.384450783029092, -0.023187848319652, 0.295945015670599, 0.103064396304832, -0.138724323681403, -0.251828539871413, -0.923799957736315, 0.101375165298171, -0.234150781460144, -0.289005523242351, -0.696373108347065, 0.339215265258751, -0.0863960835613664, -0.307350112052131, 0.205731819147201, -0.0683123157429526, -0.0613843734468539]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157802, '[-0.662579830545148, 0.353075290813157, 1.41182994209554, -0.392374918692448, 0.158478536668967, 0.543043141948079, -0.437423860066864, 0.276350030346687, 1.61112203379215, -1.4217206739337, -2.1439523399203, -0.0207896149251316, 0.456672346458041, -2.43470155534823, -0.638659850456144, 0.644993285478948, 0.156328940462853, 1.27748852679236, 0.0121014679009533, -0.169687510623998, 0.147664043963046, 0.789870322417577, -0.38565441956634, -1.05334016819136, -0.440951870893653, -0.243626478490085, 0.0443777701082882, 0.222243042419404]', 7.7); -insert into credit_card_transaction (time, features, amount) values (157803, '[-1.01015212072886, 0.633830094908954, 1.68437076850686, 0.299068887075505, 0.711967035645827, 0.572947214952501, 0.407069893075968, 0.266185254763064, 0.0115740094057204, -0.554820141501952, 0.401217734016973, 1.15595885756949, -0.0667284508338286, -0.361890919936152, -2.10600352397657, -0.277522586916977, -0.328805007685352, -0.384637047355829, 0.350736881494707, -0.209975958521421, -0.481706181869206, -1.31370812660583, -0.0847678629843969, 0.629921569170175, 0.552263283413985, -1.05212396800231, -0.267668691111145, -0.0188005550464329]', 10.0); -insert into credit_card_transaction (time, features, amount) values (157804, '[0.862941187980347, -1.88749019335918, -2.17087155786798, 0.852340177395539, -0.621354181195796, -0.781277508071769, 0.682628938147886, -0.201053970899531, 0.87937039968048, -0.904076081002724, 1.13762261571622, 0.417394820666489, -1.37793888553869, -0.86467663176151, -0.585048920415896, 0.222538462574613, 1.00530597135217, 0.656441242794341, 0.135987224791507, 0.895278671772378, 0.147433546394276, -0.690343079415677, -0.295426478503889, -0.101920082758047, -0.371265073573484, -0.164802184968382, -0.122705562608091, 0.0653487872328319]', 578.8); -insert into credit_card_transaction (time, features, amount) values (157804, '[0.169367883595559, 0.956147953074134, -0.556427123686125, 0.936963561208608, 0.930524383977687, 0.0636670684875959, 0.41622741991107, -0.0466919099127169, -0.538375101643974, 0.196328088871118, 0.79058152210962, -0.0181310328141218, -0.361565946321907, -0.504925910185467, 0.707689218194274, -0.515066597432359, 1.05275932766738, 0.847558427187433, 3.12387907619402, 0.180782302865973, -0.135378894098173, -0.335589119619996, 0.202964448648445, 0.206551350161792, -1.56237916096899, 0.414619289668535, -0.010551588799948, 0.305325512713878]', 1.29); -insert into credit_card_transaction (time, features, amount) values (157804, '[1.7006940593433, -1.42123237639736, -1.236457695055, -0.451099156233925, -1.20180416536041, -0.810533600090655, -0.789689274938437, -0.0233491361941443, -0.0546303091436498, 0.191947700884504, 1.25585753821169, -0.629191490336688, -1.01847302417451, -1.63492786820819, -0.228735136051851, 1.91095573571045, 1.23038232679234, 0.190069856999646, 0.398541286980192, 0.37380933899007, 0.405629138174191, 0.718489472418009, -0.0597655152051037, -0.0411395882353453, -0.304357932886922, -0.130779229930871, -0.0198535948597151, 0.0119640120314064]', 219.0); -insert into credit_card_transaction (time, features, amount) values (157804, '[1.93023662261023, -0.196151849026805, -0.598748101949689, 1.24976328085023, 0.139448992847324, 0.717800771260176, -0.41239489264628, 0.2553959189401, 0.918409464006159, 0.142431299306595, 0.0358968765579994, 1.31270067658047, -0.0803377023810168, -0.131581267851333, -1.80560602428491, -0.134041026321317, -0.43969189855515, -0.308555520479416, 0.613804168172047, -0.242471693522345, -0.50302574730202, -1.20216131086347, 0.412954529689502, 0.137592601043651, -0.279280342348862, -1.12554099041351, 0.0498527649449709, -0.0387168199646039]', 4.94); -insert into credit_card_transaction (time, features, amount) values (157804, '[1.93023662261023, -0.196151849026805, -0.598748101949689, 1.24976328085023, 0.139448992847324, 0.717800771260176, -0.41239489264628, 0.2553959189401, 0.918409464006159, 0.142431299306595, 0.0358968765579994, 1.31270067658047, -0.0803377023810168, -0.131581267851333, -1.80560602428491, -0.134041026321317, -0.43969189855515, -0.308555520479416, 0.613804168172047, -0.242471693522345, -0.50302574730202, -1.20216131086347, 0.412954529689502, 0.137592601043651, -0.279280342348862, -1.12554099041351, 0.0498527649449709, -0.0387168199646039]', 4.94); -insert into credit_card_transaction (time, features, amount) values (157804, '[1.93014002822133, -0.196311465319916, -0.598804167418757, 1.24980389623073, 0.139399680518361, 0.717818764605702, -0.412328543602562, 0.25538294124622, 0.91840357469867, 0.142408011109847, 0.0358975929153066, 1.31270273601648, -0.0803287880500169, -0.131569948050575, -1.80559973431211, -0.134034431594372, -0.439690416200348, -0.308545276116013, 0.613788198660126, -0.242369870508684, -0.502995450759948, -1.20218770026672, 0.412910459714429, 0.137595166667521, -0.279298701122698, -1.12554632302787, 0.0498433175974572, -0.0387081140778168]', 4.99); -insert into credit_card_transaction (time, features, amount) values (157804, '[1.93014002822133, -0.196311465319916, -0.598804167418757, 1.24980389623073, 0.139399680518361, 0.717818764605702, -0.412328543602562, 0.25538294124622, 0.91840357469867, 0.142408011109847, 0.0358975929153066, 1.31270273601648, -0.0803287880500169, -0.131569948050575, -1.80559973431211, -0.134034431594372, -0.439690416200348, -0.308545276116013, 0.613788198660126, -0.242369870508684, -0.502995450759948, -1.20218770026672, 0.412910459714429, 0.137595166667521, -0.279298701122698, -1.12554632302787, 0.0498433175974572, -0.0387081140778168]', 4.99); -insert into credit_card_transaction (time, features, amount) values (157804, '[2.03293896236003, -0.133499827984758, -0.89097044694298, 0.469413420697929, -0.239498274872574, -0.905814587957579, -0.0608221756817656, -0.293101114214716, 0.897950341445993, -0.107902136797229, -0.726465882732101, 0.901733083294368, 0.977775761845263, -0.0510636643707597, 0.289582133657649, -0.372094322914973, -0.396585488713015, -0.0899310999854533, -0.294323200071065, -0.196368066383948, 0.365756138437933, 1.39092070870144, -0.0637909019249169, 0.0756799428703881, 0.312066658713002, 0.0203421735598049, 0.0157803308645931, -0.0532324129855432]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157805, '[1.98715784052101, 0.135969609181324, -2.75632867292445, 0.972901390868871, 1.40648405286108, -0.453710983919198, 0.979853505673817, -0.331547606140305, -0.447530670756135, 0.537492962382802, 0.176339587035396, 0.323719651741669, -0.696354651086258, 1.17025753255851, -0.845682284316742, -0.479041764873774, -0.638627595659541, 0.254659839309911, 0.167354635807938, -0.158992273661776, 0.343683627668722, 0.970225724655249, -0.321650658135891, 0.0707611653510068, 0.901520460578426, -0.208591996229026, -0.0749462597584223, -0.0794109844745718]', 64.0); -insert into credit_card_transaction (time, features, amount) values (157807, '[0.14328828221439, 1.03347205192401, -0.413954804730453, -0.546000253454251, 0.927088521052604, -0.824445563093275, 0.980871727808579, -0.113080498625127, -0.0551913781455736, -0.836754858765189, -0.702518607586338, -0.0945402718921675, 0.0702091679663794, -1.03012421184268, -0.243739030537978, 0.33615651199416, 0.353881746644832, -0.214583603729398, -0.220268149322069, 0.0273538045715858, -0.341512651035965, -0.834778728151865, 0.0956055015074986, 0.560463369200917, -0.414990455926793, 0.113468812126446, 0.222112471808535, 0.0844250605859257]', 4.46); -insert into credit_card_transaction (time, features, amount) values (157808, '[1.89020976926467, -0.718621455617211, -0.494607816018931, 0.41125257367279, -0.664836358728663, -0.0341650686895274, -0.723185802641591, 0.113822222940725, 1.4102089553693, -0.0029513111663952, -1.23903740947893, -0.250509146300211, -0.839344788770907, -0.0599141230617934, 0.567476418025163, 0.377830180221047, -0.43476284183696, 0.119471329861976, -0.290453776516448, -0.117693369815635, 0.174754378194728, 0.521449562973754, 0.155090705247644, 0.634628275709373, -0.315882989950332, 0.542924745528679, -0.0382390801003175, -0.0340646234220689]', 64.99); -insert into credit_card_transaction (time, features, amount) values (157808, '[2.08484113647936, 0.0153232723818007, -1.32095765528647, 0.30363706764646, 0.320449667392797, -0.679532519123371, 0.239355660538362, -0.309144985942832, 0.392165630475432, 0.0154146291929246, -0.744364814841996, 1.02210715677496, 1.26734856338744, -0.0236232077167782, -0.306773778112924, -0.258168858213166, -0.325246078299231, -0.97113190068104, 0.255659549359951, -0.120214069555673, -0.25017179844612, -0.520295794938215, 0.291670547472232, 0.70955009787486, -0.116828793769917, 0.243480492738206, -0.0699730067167858, -0.0550860593735453]', 1.18); -insert into credit_card_transaction (time, features, amount) values (157808, '[2.20272194782546, -0.783839579807829, -1.4386409678936, -1.05101659983573, -0.469859293163585, -0.94967760996934, -0.452134650379234, -0.233771115500973, -0.6779648342407, 1.06726679220494, 0.685310397860821, -0.360276894457644, -0.437209850146088, 0.328133579657708, -0.284828213386965, 1.19845319670586, -0.183045318178142, -0.629692830783504, 0.836709217242646, -0.0499072046662009, 0.457185805373731, 1.27739833230359, -0.0588538258339816, -0.290948207325745, 0.195626880085859, 0.0708728312446743, -0.047410123274501, -0.0801127492014495]', 15.0); -insert into credit_card_transaction (time, features, amount) values (157808, '[2.10265459972427, -0.974301947985372, -1.17943178479541, -0.807064648785807, -0.840413029339322, -1.04973445657136, -0.489679937276198, -0.131114196078993, -0.316009410432336, 0.964188458030938, 0.685427354188882, -0.660510342424728, -1.9476774145923, 0.444591211282609, -1.0022474381471, 0.854999705174846, 0.343969200464974, -1.22155520937397, 1.15501656588183, -0.115045606390623, 0.0209352790007677, -0.0610606754782581, 0.226101669435722, 0.0312980285661253, -0.191185143054015, -0.349560367261045, -0.0528551377558542, -0.0689431140232731]', 40.0); -insert into credit_card_transaction (time, features, amount) values (157809, '[1.72749825858346, -0.460940688670449, -1.10648329544574, 0.55067129546286, -0.163783824672603, -0.336237705326993, -0.180240691292153, -0.081110999858166, 0.791214209032195, -0.577537884750753, -0.337726488684758, 0.650499645419312, 1.09754995477988, -1.41880756136142, 0.63528400304427, 0.762605823463408, 0.339199479665297, -0.0634259065005024, -0.312694006485262, 0.217658078488462, -0.234254970478256, -0.864549526831725, 0.30834230683611, 0.515998894161786, -0.620018086431606, 0.0773377808843559, -0.0386484696811715, 0.0163597096084855]', 150.0); -insert into credit_card_transaction (time, features, amount) values (157809, '[1.94799262008175, -0.045237038198725, -0.455975703893429, 1.43124399296622, 0.0385352593135862, 0.237105147166421, -0.210081916637175, 0.0112467661869301, 0.95394411441597, -0.066708049639737, -1.14203108587611, 1.44012438494246, 1.27755510901435, -0.572895640717578, -1.27495348576189, -0.488472894711816, -0.145500865222528, -1.07402841693146, 0.190989702384496, -0.175796872667835, -0.516890670781023, -1.14598589288621, 0.448670451783649, 0.55639940519416, -0.24856331810995, -1.13307491699875, 0.0625063089648343, -0.0220802721424277]', 6.49); -insert into credit_card_transaction (time, features, amount) values (157810, '[1.857446099099, -0.546959335002011, -0.45363278102496, 0.277492259171764, -0.495370106695829, 0.0562012445094075, -0.618161061893275, 0.20781873519935, 1.11199973853353, -0.0076445690233954, 0.818138680551881, 0.810064741507163, -0.716242473757146, 0.311031406135812, 0.127532157161612, 0.39006896945034, -0.707323114611947, 0.338559572852083, 0.13531737049558, -0.153857021883862, -0.109265804241523, -0.364034803493023, 0.377332824637121, 0.640375817891629, -0.49928884766645, -0.674471318625301, 0.0166398762373841, -0.0282127279240626]', 49.99); -insert into credit_card_transaction (time, features, amount) values (157810, '[-0.247917116688247, -0.655768904879766, 0.11677152910076, -2.64983844936901, -0.488275194960327, 1.11764833890607, -0.947184257728264, 0.865315283554798, -1.88325495693079, 0.478701126344802, -0.951172724747645, -1.29665431350972, -0.613563920957981, -0.0233874820861105, 0.380776913911904, -1.20181009178415, 1.4235580770564, -1.11568158427419, -1.46981278259855, -0.549178272623337, 0.0451194729197998, 0.412136430443857, 0.242727717729859, -0.404977631617722, -0.641704622729318, -0.16781994916912, 0.0075579600766935, -0.0163945189241929]', 46.0); -insert into credit_card_transaction (time, features, amount) values (157810, '[1.88549683468638, -1.20153555374825, 0.696203433229769, -0.314601472163345, -1.76011788319106, 0.156165304977569, -1.46510675707153, 0.193588945694349, 2.98475414773138, -0.925686714455559, -1.38330250650493, 1.74580023538335, 1.29135053134651, -1.5713346337322, -1.28254485308116, -0.608165647578597, 0.179888563198066, -0.208673785749401, 0.732285609926405, -0.0654036540181713, 0.107793832550697, 0.952347034241795, 0.117622289199077, 0.194246945884365, -0.303082320873311, 0.623667829519586, 0.0573531882575415, -0.0309188039903835]', 33.04); -insert into credit_card_transaction (time, features, amount) values (157811, '[2.03960974435102, 0.0757104311597996, -1.9008910923745, 1.11392897225594, 0.731730634367903, -0.435411066015483, 0.438702510998587, -0.154061725916454, 0.18207149997809, 0.465546657668439, -0.143222193545841, 0.105168923946084, -1.47117971098552, 0.935108495939136, -1.02838087113208, -0.270569056054109, -0.572602029878565, 0.227337964069095, 0.351324886948925, -0.350427644162902, 0.038047120955391, 0.250009126680236, -0.0885182568475055, -0.830053254689188, 0.484104664051276, -0.457074483557609, -0.0273133228961275, -0.0826069572342486]', 6.99); -insert into credit_card_transaction (time, features, amount) values (157811, '[1.9719159070628, -0.388731121104135, -0.624006943055621, 0.17015573536754, -0.277733696648881, -0.191131386335047, -0.40097827954714, -0.0543587408742976, 0.906612703241837, -0.0458665498407903, -0.921401238098533, 0.700679833045854, 1.01543716433756, -0.2440392102851, 0.494478197168139, 0.493074498195497, -0.678565391240785, -0.463829779018159, 0.0758096096619381, -0.0299614617424366, -0.258970150409411, -0.716360744113209, 0.400668459063837, 0.484286742120343, -0.572348252538824, 0.209080917242179, -0.045735406548267, -0.031928751743242]', 41.97); -insert into credit_card_transaction (time, features, amount) values (157812, '[1.95178559994952, -0.409727009211516, -0.444015475328114, 0.125487611536859, -0.486976047716096, -0.0577029616634854, -0.699150214488992, 0.232274347938193, 1.23743810020455, -0.0365047003412201, 0.82261019499935, 0.518472881862301, -1.22851738167275, 0.510042677246535, 0.590608682650595, 0.437274570592855, -0.794885215131684, 0.598339258265772, 0.0809074332997959, -0.289030394758501, -0.0786696716460054, -0.218988266371108, 0.400863418781075, 0.610056507052829, -0.439500751304051, -0.970243130806716, 0.0454609463993414, -0.0327784475264763]', 2.35); -insert into credit_card_transaction (time, features, amount) values (157812, '[-0.422421521095763, 0.658543922031277, -0.542993291613436, -1.91077933609488, 2.55752848754234, 3.67851431842003, -0.183898937905112, 1.12543274032514, 0.467184839533209, -1.20056879741915, 0.196317532303265, -0.0996175290741946, -0.288940846422521, -1.28628731988351, 0.855903906145092, 0.545086615514229, 0.269021030996727, 0.261788803371768, -0.482030433066122, 0.0960908874996435, -0.26443143843773, -0.752090922759935, -0.0086320332130002, 0.561731359228306, -0.145211291283595, -0.245972410243061, 0.168815933695936, 0.100460460840373]', 5.78); -insert into credit_card_transaction (time, features, amount) values (157812, '[0.0024960324417067, 0.788164180599921, -1.25484607760832, -0.82336568428351, 1.70747188308121, 0.619559406227495, 0.671560922026512, 0.217821956147169, 0.562239179129043, -1.22713229708576, -0.43150171228519, -0.0249860060926184, -0.495942732420654, -1.74682180509996, -0.584917494202639, -0.595252253685278, 1.63427367867747, -1.08957455661534, -2.07621588234904, -0.406714901289419, 0.322887103476518, 1.1882984618713, 0.234853074605478, -0.432318258813192, -1.97366146694542, 0.23056355011325, 0.0945152146477225, 0.37637794258061]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157812, '[2.01652460331248, 0.197597603262843, -1.70558625054696, 0.548291330260255, 0.190817636093764, -1.50755986197748, 0.349012810877867, -0.44121785950865, 0.484656779092686, -0.501663018213626, -0.224559439906617, 0.430782072646178, 0.681551107047013, -0.859250949937578, 0.824812492899406, 0.170613393918332, 0.361442475553509, 0.417222682587251, -0.447246309176938, -0.120208967695477, 0.216763843195825, 0.787944084515085, -0.0460610578341789, 0.0023672939038673, 0.2674714614548, -0.108543027645682, -0.001856078329216, -0.0258953665999172]', 24.49); -insert into credit_card_transaction (time, features, amount) values (157813, '[0.0245406853862598, 0.834158696854512, 0.279423515963669, -0.581056858872866, 0.413832824945075, -1.11715639703404, 1.02181159037646, -0.207648220991299, -0.0459097877986485, -0.414935763033553, -0.939626144379386, 0.137872662303856, 0.025706194958167, 0.110417921229033, -0.402328086924192, -0.0881568947645665, -0.415336033575582, -0.741678608888256, -0.0791318668810542, -0.0204920378985217, -0.25672151736005, -0.574843814940882, 0.0843517814733371, 0.0136256383933616, -0.483594183991414, 0.139086611652184, 0.244614495231356, 0.098022680591708]', 9.0); -insert into credit_card_transaction (time, features, amount) values (157813, '[-1.89941235074885, -0.835026396217829, 1.66793132486525, -0.646436489043085, 1.52527136759406, 1.13379438858827, -0.310950049331796, 0.638651130892026, -0.195195301251167, -0.602018053632396, 0.918502152812633, 0.378459805344627, -0.255858020847809, 0.165080231517051, 1.13534214789979, -0.0900824216782614, -0.10831140545711, -0.652537748075668, -0.130096452458055, -0.135957644236223, -0.104949842418508, -0.138522232200461, 0.613932943698787, -1.65136356235412, 0.106802237640361, 0.628331759968377, -0.0047200532136992, 0.0265065304979407]', 25.3); -insert into credit_card_transaction (time, features, amount) values (157814, '[-0.0408645436674328, 0.643505132346518, 0.682483895219545, -0.537851306680335, 0.785663820022569, -0.219362528377173, 0.545235620103251, -0.155021156498491, 0.606893027977926, -1.14690155385672, -0.726292299540116, 0.0127270458053618, 0.605513711344683, -1.77213207624616, 0.34676268617161, 0.370041022616633, 0.116644742572105, 0.895540889827852, -0.657126267725782, 0.0091098227613336, 0.29973447644084, 1.22805640499734, -0.19605763451332, 0.549346072211329, -0.710797168706551, -0.33221154212398, 0.113629117667617, 0.0459507976560507]', 2.49); -insert into credit_card_transaction (time, features, amount) values (157814, '[1.91413522555332, -0.66584263691139, -0.571756504768202, -0.913025199012016, -0.570311477436205, -0.317848716721277, -0.549136756749172, 0.0048753584101016, 1.03215036139995, -0.294236720406826, 1.33056615424238, 1.7792247340108, 1.25076632785714, -0.0399209339802863, 0.379142524285099, 0.453145372958297, -0.82357018985906, 0.0811629568394416, 0.526705137750816, 0.0490124103568653, -0.0831337901014837, -0.258884089061158, 0.380226371330108, 0.80867285876941, -0.639265957036621, 0.268833577781513, -0.049688075238884, -0.0372744770147582]', 57.0); -insert into credit_card_transaction (time, features, amount) values (157814, '[2.06536702630595, -0.185842664413203, -1.10932923221241, 0.373668790959369, -0.279027561019407, -1.22946369548719, 0.0857156000797023, -0.261914967063858, 0.811973016089996, 0.073986754873404, -1.01550221237828, -0.201476239390462, -1.23751330241331, 0.464629116766291, -0.052178453682874, -0.163304074751581, -0.112220188082995, -0.777765299745355, 0.248967369192527, -0.30684345847883, -0.294656869850248, -0.736116650117601, 0.331539811061915, 0.0276121178569083, -0.306344804488189, 0.357923693419442, -0.086919074750387, -0.066287276404903]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157814, '[1.9021008785613, -0.482844154348986, -0.601523633155915, 0.179886971764206, -0.25909496971808, 0.219205258493644, -0.565538099369571, 0.16577228248986, 1.02711701744355, -0.0191377865785395, 0.535331378508032, 1.0588679928049, 0.114062426483948, 0.129832519933771, 0.0262672930768413, 0.530508960416592, -0.953857493848836, 0.465758951057107, 0.355454632729674, -0.0931921046465438, -0.135135632861565, -0.398254373317797, 0.314696620216382, 0.306981137172287, -0.403444488315781, -0.656710585289073, 0.0185440301190065, -0.0307360977269626]', 46.48); -insert into credit_card_transaction (time, features, amount) values (157814, '[-0.309006417742835, 1.69743830986966, -0.334570089891847, 2.52065973486873, 1.83324100755956, 1.24449837402443, 0.023365102972311, -2.32096984629601, -1.85417027631769, 1.13929124043572, -0.330898624029878, 0.393039701634436, 0.0541494658972232, 0.609635506751284, -2.30118885101429, 0.800796913914809, -0.957152785599905, -0.132212089011764, -1.17598131222284, -0.681050820855386, 2.25325709977215, -0.990421283568725, -0.586470236991348, -0.130776394990222, 1.19526883195869, 0.0985717764493531, 0.206530037645392, 0.23280725745383]', 21.18); -insert into credit_card_transaction (time, features, amount) values (157815, '[-0.256069392576177, 0.641016316788403, 1.23599786105643, 1.10967000219345, 0.739315250937195, 0.408433003634605, 0.380705187350078, 0.135026748531129, 0.0498645175526142, -0.487835994233637, -1.34097169353132, 0.809816864589273, 0.880417348629801, -0.489823046627348, -1.02980463783317, -0.943606131881048, 0.206346698570494, -0.716394253633113, 1.20623923845022, 0.0723482312025159, -0.390153119584736, -0.881605479674927, 0.191987178757877, 0.560352244906919, -0.750145770646455, -1.03510609069657, 0.263701914394897, 0.225430223978651]', 5.55); -insert into credit_card_transaction (time, features, amount) values (157816, '[-1.19466168797146, 0.904479617259957, -0.727543282784896, 0.948610388342598, 0.754179739501868, -0.501770345120198, 0.956482175709518, 0.33811944114813, -0.710580137749843, 0.259129942299583, 0.0445229092162285, 0.156054594517973, -1.13606430995869, 1.11066638372623, -0.871198669710597, -0.736082606751366, 0.0279779127761554, 0.393553299816004, 1.14282044030211, 0.0961437774020731, 0.149109517059488, 0.584798720001557, -0.116917287999219, -0.403244916259447, 0.122852144837373, -0.359362507005129, 0.446956737832394, 0.195110981693878]', 76.4); -insert into credit_card_transaction (time, features, amount) values (157817, '[-2.33567210288528, 0.733138221649288, 2.0120099315408, 0.570452636629583, -0.560033894628143, 0.864410513456987, 0.0170526509325223, 0.284058903226262, 1.36797757028668, 1.63002234763906, 0.271161287916639, -0.24497861983797, -0.802494768393077, -0.699874500415324, 0.857624610180712, 0.530786442562383, -1.00186667451541, 1.55474026574662, 0.610348673619972, 0.631512187804047, -0.0912926770852709, 0.713324206954873, -0.451620578010056, -0.523147501320451, 0.68667927757969, -0.252686619350527, 0.663833119056286, 0.675868508138676]', 100.0); -insert into credit_card_transaction (time, features, amount) values (157817, '[2.01225660541128, -0.12090862323187, -1.01133122217169, 0.325476421186976, -0.158659570466063, -0.949621553308758, 0.0633844777917638, -0.176685409638332, 0.321384826339672, 0.250849992567385, 0.989175211706786, 0.996650219727563, -0.340384382288002, 0.538035432510428, -0.633944869222583, 0.0782937932135224, -0.487582582090626, -0.367404249890262, 0.402502545720778, -0.235416238019861, -0.23481479952135, -0.59440583314119, 0.34277598792859, 0.0691624275537647, -0.351271213437363, 0.173690252517699, -0.0764478284820569, -0.0697888491767698]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157817, '[-0.0030630410061332, -0.684657807221811, 0.297792231561736, -3.3466535165441, 0.153821265574126, 0.301944521007295, -0.148805741060795, 0.176905609705918, -1.83221510082318, 0.450191859109921, -0.72430532294448, -0.675000939775357, 0.373065372112177, -0.485818938217281, -0.703747314953181, -1.14945106379088, 0.793464752663303, -1.58607543310855, -2.64946542349511, -0.64826280462242, 0.0875770886152101, 0.798256808757288, 0.18761843034172, -1.06091216151852, -1.27522786620147, -0.456043138582043, 0.295467161130535, 0.240630561325634]', 15.0); -insert into credit_card_transaction (time, features, amount) values (157818, '[-2.36265172021935, 2.24444032102664, -2.41785970342538, 0.791624671803851, -0.076004460222897, 0.16295223379335, -0.688874149737515, 2.01735520530894, -1.33602291698205, -0.689971180803214, -1.1022944104057, 0.448983502356223, -0.992706533888524, 2.30972276728927, -0.892585639219672, -0.0332048747267003, 0.463520645926414, 0.751234593579852, 1.41440509219953, -0.718632830516321, 0.372483320536492, 0.278604871368275, -0.218364088002813, -0.219181241038021, 0.0019911974490226, -0.478007450983075, -0.953881444756312, -0.210779472515315]', 16.89); -insert into credit_card_transaction (time, features, amount) values (157819, '[-0.964045125612063, 0.401958802950009, 2.1977831516738, -0.729470190516652, 0.195106370886337, -0.397534278096216, 0.239500366757542, 0.238780214698133, -0.0068377775341286, -0.9648974451456, 0.701341534165569, 0.434148218466311, -0.798178403269352, 0.201861370393168, -0.257776554436292, 0.348178115392445, -0.728458630145008, 0.51417832786665, 0.172123004385327, -0.0406260900446285, -0.105658283079042, -0.438823990466515, -0.212498998001795, 0.0179382099396533, 0.320945596480672, -0.523091236594453, 0.0420783011102279, 0.0648088152694283]', 4.6); -insert into credit_card_transaction (time, features, amount) values (157820, '[2.00704675985152, -0.279405405346904, -1.28956087290228, 0.100786611413697, 0.156186742923983, -0.440342552080132, 0.0814742665626667, -0.226649935964445, 0.949801853207362, -0.260853903166807, -1.07452115842414, 0.962385050693463, 0.965162274969219, -0.124460783657848, -0.321463255860613, -0.438023978708979, -0.291000561790328, -0.633590345164846, 0.464355644488598, -0.068970173114129, -0.15951091658087, -0.266323232999436, 0.170644556868241, 0.515265340319667, 0.0157499850284986, -0.112843979380258, -0.0299753353603384, -0.0436620922839824]', 40.0); -insert into credit_card_transaction (time, features, amount) values (157820, '[-1.10782746910529, 0.818007001151512, 1.23441133451061, -1.33078828029731, 1.05881250675329, -0.716022442446408, 1.18402602137007, -0.194652589029391, -0.324783546652541, -1.23023561554114, -0.802934841360688, 0.732481356758106, 0.850399254752658, -0.396186122192683, -1.67508080947407, -0.326969899836686, -0.394945247275416, -0.86993893333513, -1.22496458554483, -0.176013488544165, 0.170286296549614, 0.593383379883429, -0.620246922024202, 1.20563069766128, 1.14130427420137, 0.598097375634103, -0.192605467790794, 0.034651388695736]', 3.07); -insert into credit_card_transaction (time, features, amount) values (157820, '[0.0271775324813036, 0.821080821077469, 0.182819999066708, -0.778501091963439, 0.626265555479052, -0.611722792794885, 0.914758999117007, -0.0475013734472113, -0.301344931788006, -0.24575141705346, 0.507308892531776, 0.786300341155683, 0.10528223119812, 0.264853615542356, -1.09416566728214, 0.190699597846666, -0.782707158846096, -0.164111144534707, 0.325160299296116, -0.010412459617805, -0.228765806691467, -0.507309429988439, 0.0155310222655124, -0.339498398397163, -0.472696739737868, 0.140226979307561, 0.243889958184265, 0.0841729877243635]', 3.27); -insert into credit_card_transaction (time, features, amount) values (157821, '[1.88665705922934, -0.360965320950786, -0.297727339493862, 0.46446755871876, -0.604808765772919, -0.508171188799265, -0.383475047512767, -0.0788128803541868, 1.10480129068373, -0.216085071905604, -0.352940380035797, 1.07437593976372, 0.933254840791105, -0.193385705382018, 0.578190435918073, 0.0778374544524609, -0.482862659152504, -0.376732625623661, -0.220424140042421, -0.0658078315218247, -0.126037353687638, -0.305315218837071, 0.405318059829234, 1.12656061129541, -0.444332828399621, -0.688489158115425, 0.0283170630663477, -0.0105742493363594]', 49.99); -insert into credit_card_transaction (time, features, amount) values (157821, '[2.02297796313133, -0.451698797647335, -0.523431233028171, 0.373860239825938, -0.523903322869473, -0.235145877911942, -0.637525594159163, 0.0002517286694999, 1.57312390824529, -0.153479726626306, -1.66880347964446, 0.060374746238083, -0.136066884867294, -0.165343839309445, 0.565061269109967, 0.291475463048405, -0.727039997022602, 0.466614024085402, 0.0288750143179468, -0.22320424240174, 0.144349596930845, 0.661177114183402, 0.0382360573204955, -0.63955439142185, -0.017475740445534, -0.171117731230469, 0.0384218127231883, -0.0440449312862853]', 9.99); -insert into credit_card_transaction (time, features, amount) values (157822, '[1.47213000036966, -1.10965201447505, -0.530079772016693, 1.30211685261894, -0.469214861607331, 0.747243422225682, -0.501553862352727, 0.156071341288157, 1.18891394692465, 0.0034108379361629, -1.60958876428604, 0.212803127547787, 0.557309080691805, -0.283026605536064, 0.821924342590273, 0.803487214498176, -1.03105218868005, 0.531108329437095, -0.554660950355263, 0.350410663691309, 0.191638037473539, 0.11349418416183, -0.0181016987719031, -0.0507676437024086, -0.319582805849277, -0.744618829527683, 0.02989188895939, 0.025596850448959]', 269.0); -insert into credit_card_transaction (time, features, amount) values (157822, '[1.95260941642706, -0.463763496156111, -0.787384780096095, 1.39114631147901, 0.193293893885378, 1.20077942517405, -0.843212462361275, 0.36325570364224, -0.170777712518457, 1.30984483645386, -0.761064455868926, -0.708803351997812, -0.644543464519214, 0.0825555562704867, -0.311669570304863, 2.23122765817023, -1.54486702198862, 0.732286707866648, -0.348632120451662, -0.0385540299102912, 0.0759815094916214, 0.0019616327078082, 0.128106059372384, -0.635350697384354, -0.641170558351484, 2.27263580909368, -0.189125635497311, -0.0765970137726111]', 53.96); -insert into credit_card_transaction (time, features, amount) values (157823, '[1.94486901534407, 0.393022084545182, -0.981243860593355, 3.67363032923613, 0.837687690005821, 0.770438248184241, 0.0458714848508149, 0.0658161152500346, -0.566099758843042, 1.36884214413366, -2.1326432260674, -0.489444585331139, -0.2064169321907, -0.011502791251268, -1.3616144522607, 0.632279967763316, -0.717537153627847, -0.320688816331692, -1.14004217303203, -0.260791705400167, 0.0320644712281213, 0.218062292145084, 0.0325631841399894, 0.0139196239470554, 0.219852720839999, 0.109739818288953, -0.0322666704626435, -0.050269144580269]', 15.12); -insert into credit_card_transaction (time, features, amount) values (157823, '[-3.06761475038232, -2.45757422381283, -2.37781833374031, -2.75327430744293, 0.405270219564038, -0.587300907165915, 0.985344454363531, 0.444995319920586, -1.44856299433554, -0.954020409832174, -0.617750097436486, 0.860476183269492, 1.33205170099883, 0.809959856510232, -1.40672634850991, -0.640053638097413, -0.913410026106095, 1.72412664100913, -0.947931624535411, -0.572463091197429, -0.0876827194099806, -0.156815339512873, 0.589958048172099, -0.268956803656156, -0.213857626134977, 0.430112980760767, 0.132307165833751, -0.722747290729469]', 261.06); -insert into credit_card_transaction (time, features, amount) values (157823, '[-0.191673063048596, 0.821384159145986, 0.787674730152658, -0.0922151874145524, 0.681725373574366, -0.722273978632257, 1.26231684222704, -0.739932271562768, 0.152280334918435, 0.388642660435366, -0.774156086293229, -0.485026817886725, -0.549312350960892, -0.14034120075895, 0.434589447227881, -0.787100501008745, -0.127915916983925, -0.642284630683373, 1.13529016002422, 0.0358413872948787, -0.236158337446056, -0.374780192492369, -0.0119837966207439, -0.0847080906541573, -0.906443609943872, 0.208797558300003, -0.59845703660515, -0.252546698431979]', 1.79); -insert into credit_card_transaction (time, features, amount) values (157824, '[2.14725144561267, -0.911386646510524, -1.70743781131686, -1.08121823771349, -0.123056751918487, -0.526472948782039, -0.294571891453705, -0.242186844703195, -0.406899172991187, 0.779200245089816, -1.33341809792709, -0.92799832254967, -0.0587987196156513, 0.0236448955414936, 0.214033993508898, 1.15067640098965, -0.0281973819969767, -1.50455814329727, 1.02405841178102, 0.122064764920196, -0.0779838009596802, -0.452922814833994, 0.186934782075766, 0.0066968744621801, -0.12824301356534, -0.422302825655525, -0.0545148178467393, -0.0461967776619663]', 78.76); -insert into credit_card_transaction (time, features, amount) values (157824, '[-1.48323702696132, 2.10624752649122, -2.16123474882007, -1.22838859489731, 0.233052200224787, -1.36326729699469, 0.43310605472374, 1.04871855353305, -0.609369507776305, -0.337206237993234, -0.0827354737797539, 0.432264304119711, -1.11153317007751, 1.90577260521751, -0.785213429118827, -0.0455624209302278, -0.193326016872693, 0.354370197799988, 0.164834257011197, -0.203439962648355, 0.332130148034254, 0.83334654767392, -0.10917360155125, -0.449728325179691, -0.160171131847402, 0.118467146575708, 0.222562436856777, 0.185344428381212]', 0.92); -insert into credit_card_transaction (time, features, amount) values (157824, '[1.94385824857617, -0.324216926499365, -0.378751671816814, 0.243042148973371, -0.386030995318921, -0.0200066019164586, -0.576057723689871, 0.124435047076755, 0.938180727889361, -0.0153386791813126, 0.977178748442479, 1.42171305419448, 0.464162303746381, 0.0609745917180072, -0.0555692970560797, 0.385183200248637, -0.829375704497138, 0.27097393308082, 0.208626965098023, -0.153419697371748, -0.125178645056365, -0.267839631504996, 0.392750230913669, 0.730302646638874, -0.430623237868935, -0.679854795300319, 0.0287855482064301, -0.0319837818302215]', 9.98); -insert into credit_card_transaction (time, features, amount) values (157824, '[2.06249030426725, -0.0648454310765915, -1.0650812664132, 0.420367017994954, -0.168214387594192, -1.22471681726083, 0.168718161269045, -0.322472670570973, 0.575602771936041, 0.080237911519834, -0.772147943304741, 0.319930193231773, -0.166258743588161, 0.321343992406884, 0.0643805860927848, -0.0971402553273107, -0.271777142273838, -0.844595885668367, 0.144470872369702, -0.240377265067763, -0.291616211892481, -0.715908440885158, 0.344507283686344, 0.0400238915933294, -0.307124950232525, 0.196202778537347, -0.0721207325752885, -0.0604255538216545]', 1.29); -insert into credit_card_transaction (time, features, amount) values (157826, '[1.52888870056684, -1.96676854409923, -0.664912635773967, -0.557305595239503, -1.56125111879195, -0.642749040643673, -0.629031621413586, -0.233352569887686, -0.0045228312455695, 0.593968700843232, -0.578246524436214, -0.166290706760199, 0.991319476045783, -0.523114973812103, 0.592208550164067, 1.3299480960183, 0.009074238013735, -1.05785885405177, 0.0975332152883663, 0.668302342788377, 0.606375699207481, 1.10871855185019, -0.149626859529165, 0.0589351673001042, -0.31441138802195, -0.0995421601121922, -0.0373538621589966, 0.0124885141114627]', 334.28); -insert into credit_card_transaction (time, features, amount) values (157826, '[-0.551296409572373, 1.50583905262851, 0.514153108628084, 2.42072420626781, 1.66512928232429, 0.463940384200157, 2.27057447197262, -1.05359343127532, -0.562582716083645, 2.55930820895058, -1.33880035562573, -1.36858822142472, -0.800853632259143, -0.742586864441154, -1.07784886470889, 0.38648719370457, -1.32925767874308, -0.611923707768003, -1.37718713089342, 0.0746974523978003, -0.379669295897999, -0.341695726300356, -0.248587197565725, 0.404802531019539, -0.293272599619504, -0.393227629181931, -0.740158693792147, -0.701280472714805]', 86.15); -insert into credit_card_transaction (time, features, amount) values (157828, '[0.0094132298917694, -1.5071776819449, -1.88671933901564, -3.64719484766952, 2.53673608073762, -0.338748956282057, 0.130848644830295, -0.0967668282929549, 0.0185210137290804, -0.284888707522018, 0.787329209712129, 0.650563221330971, -0.279868673012532, 0.869180307172842, 0.894726642338023, -3.74327236595601, 0.430318531798971, 0.777385064737291, 0.0434022369398565, -0.311852013670493, 0.142299576141314, 1.03209694412214, 0.320208704504647, -0.953743428336158, -1.60903702675943, -0.893601388814555, 0.247073030425973, 0.129056000939828]', 11.37); -insert into credit_card_transaction (time, features, amount) values (157828, '[-0.91575425733639, 1.5912851193345, -2.02032190594613, -0.240148772738088, 3.00067127247173, 3.52860342148369, 0.410435665027943, 1.24915376531265, -0.593411389384587, 0.420328443148663, -0.478967948023834, 0.0485772389851593, -0.405192086342592, 0.86586695923979, 0.0514365493960024, -1.14373561685891, 0.204696306460171, -0.390598506121877, 0.637884797230501, 0.262606328344763, 0.0809618975278517, 0.455974620149795, -0.206969355646798, 0.711395683193602, 0.198817419056023, -0.345422922504724, 0.551754430877551, 0.288847270792079]', 9.99); -insert into credit_card_transaction (time, features, amount) values (157829, '[1.93463403830276, -0.222941544714367, -0.332789948576418, 1.11929077754318, -0.370950738860409, 0.138379275970264, -0.694966719371524, 0.222893127365693, 0.758564033189333, 0.414010768123185, 0.640976615783874, 0.461756578586964, -0.787057128821181, 0.350599097792385, 0.207654741374768, 0.71164436622105, -1.00416608987488, 0.965576765616621, -0.46655632058962, -0.275937294065399, 0.259464734957981, 0.803858325074834, 0.181308740558508, 0.724160654791181, -0.130899158891553, -0.614081313846642, 0.0439878082065253, -0.0353870048218169]', 0.0); -insert into credit_card_transaction (time, features, amount) values (157829, '[2.34570314489825, -1.38909737166812, -1.09221934822197, -1.6871127151492, -1.00467205964082, -0.371296931278659, -1.14692852907896, -0.207306614426596, -1.08090141691831, 1.5493612652813, -1.87993568190705, -0.903604337805547, 1.00264490968216, -0.634810691326469, -0.0930212340506033, -0.218117501100234, 0.073067109113477, 0.240604090931093, 0.199292750430603, -0.370890063096231, -0.218572630123933, -0.0841357668647441, 0.116198620246752, -1.0126995996372, -0.103566963076992, -0.117453585049837, 0.0212846900092629, -0.0550467264777384]', 21.6); -insert into credit_card_transaction (time, features, amount) values (157830, '[2.08851206565192, -0.489526696539034, -1.10668908538124, 0.665678158825648, -0.16048498916161, -0.115652656338969, -0.308425897709755, -0.17693717496671, -0.451164184313014, 0.929227532604979, -1.36499582905341, 0.533496210440932, 1.06685420505759, -0.259032857193185, -0.83276036010968, -2.03429229024651, -0.0137131424432421, 0.920494999457383, -1.00033677801498, -0.583494962686243, -0.247506752386339, 0.0474518194247801, 0.0993180659549081, 0.597725798717517, 0.261089616371313, -0.487430972718392, 0.0494598147442813, -0.0359975418316735]', 19.98); -insert into credit_card_transaction (time, features, amount) values (157830, '[-0.447925927972273, -0.172584932009424, 0.0569341138869356, -1.40284384610808, -2.20502462878886, 0.0560163277368336, 0.756950475513314, 0.0430077622008576, -0.916479273185834, -0.102806922331421, -1.01255478601743, -0.417674051501705, 1.19933857798349, -0.418871024632366, 0.213944634942227, 1.3755474737578, 0.0503882581384439, -0.729183993452069, 0.568356471353435, 0.0261563791144963, 0.607656684982254, 1.75503241951108, 0.362728777856288, 0.0458702212168817, -1.20206160102013, -0.197355221958857, 0.185480909057384, 0.124347807162022]', 325.0); -insert into credit_card_transaction (time, features, amount) values (157830, '[-0.198524600413521, 1.07056611697248, 0.210865437832398, -0.63896971205222, 0.453348373731048, -1.14898655562123, 1.03046033510157, -0.240133778605682, 0.0334370374083989, -0.120377506966644, -0.765167289228136, 0.559653885117001, 0.774966736423035, -0.109575083169424, -0.47116797480918, -0.152494552607784, -0.457694608353885, -0.862655827940222, -0.120953560944248, 0.130283385701381, -0.283558228376962, -0.530419173642584, 0.0643493886011424, 0.057564507479873, -0.414701799134791, 0.140122709890796, 0.363297935304445, 0.157527602339208]', 2.69); -insert into credit_card_transaction (time, features, amount) values (157830, '[-1.41637994242257, 2.08581438831372, -1.20812762489462, -0.435652715006095, -0.836699173966815, -0.0757787047767257, -2.00204219158296, -1.34089451588921, -0.346342947706735, -1.98849207010635, -1.04601064829146, 0.745948023749714, 0.789587384068126, -0.30440165784537, 0.602529274210554, 1.76141266795973, 0.569673760996769, 0.785720589100461, -0.982234241197868, 0.198847099619588, -1.08790808796609, 0.405200890137176, 0.644970369212119, 0.534240058657476, -1.38144870584727, 0.0115216224049188, -0.547496784347021, -0.0041537578676155]', 9.8); -insert into credit_card_transaction (time, features, amount) values (157831, '[-0.426382615533359, 0.429368652813297, 1.40631158426411, -0.58929268894478, 0.206332502253387, 0.713655068586189, 0.215282272103876, 0.322875560685921, 0.235229778166525, -0.754793868097043, 0.0693717581290611, 0.299751782010992, -0.360197998290926, -0.0164509199494985, -0.185155491332744, 0.219218321267268, -0.780262196487368, 1.16024794941629, 0.677787668726897, 0.0385416709853648, 0.283305303501857, 0.860771986892383, -0.294678575203266, 0.29815791126435, 0.0522178086006876, -0.146656606508687, 0.14424944156103, 0.135031904463973]', 35.97); -insert into credit_card_transaction (time, features, amount) values (157831, '[1.91761659516388, -1.27989042468339, -0.550512879866041, -0.675503386937241, -1.23135480129488, -0.715860319329705, -0.755444386509895, -0.231467593215809, -0.0488695654291568, 0.64396613210052, -0.582051893581756, 0.141068825560873, 1.34962686603566, -0.675067367142543, 0.110420966351565, 1.05256119777113, 0.133430385368821, -1.3548709396005, 0.324134472209228, 0.28187162439205, 0.415992878265722, 1.07503062012215, 0.0210676667911795, 0.0617928605364573, -0.172640661241608, -0.101567033826545, -0.0021142918020167, -0.0246200169536936]', 134.99); -insert into credit_card_transaction (time, features, amount) values (157832, '[-1.80346507043129, 1.94336351248285, -0.477192108231044, -0.401702597457705, -0.364354050082577, -1.36866894683339, 0.387747076722669, 0.344476113557209, 0.445387497102268, 0.731469924962325, -0.685099722598294, 0.335507199868123, -0.251346974320909, 0.397305842955965, -0.0994221366011376, -0.432827203638135, 0.182755154865333, -0.868298803648426, 0.150896667377805, 0.136729912408897, -0.188720269612872, -0.356520984447129, 0.187783520495935, 0.390557329551228, -0.933427342866825, 0.0844267878051226, -0.0667968389304196, 0.0853278684349329]', 4.95); -insert into credit_card_transaction (time, features, amount) values (157834, '[-4.37223272149791, 4.21387369062807, -3.97500050717615, -0.727923467186792, -1.70898981519024, -1.21635706382299, -1.51576250232597, 2.96065803610176, 0.434915678768808, 0.338122672548367, -1.42546779386574, 1.30812689981799, 0.847538384339796, 0.488138763051702, -0.354454893435288, 0.953268790918532, 1.48251852711152, -0.223059074778375, -0.600471602033495, 0.406914971149439, -0.320077450954875, -1.07793786137694, 0.506073576883736, 0.476447505830663, 0.201744331521787, 0.171836693000445, 0.298014787747813, 0.202332772727528]', 17.99); -insert into credit_card_transaction (time, features, amount) values (157834, '[2.19012899669411, -1.46153591009937, -0.803229671372471, -1.66107890407783, -1.15247172132322, -0.132293613880988, -1.24160020822153, -0.0372063708667921, -1.49851074512902, 1.67789309453922, 0.881536323757477, 0.355461625117194, 1.20325870082014, -0.468643047196173, -0.826559645452109, -0.381824106478064, 0.216441188084143, 0.284603079373507, 0.0178000099483304, -0.299460416591788, -0.0792238528330689, 0.217324469894423, 0.25464672620821, 0.707688528935559, -0.264319048131056, -0.233752008525689, 0.0161476018440291, -0.0434131033766562]', 42.0); -insert into credit_card_transaction (time, features, amount) values (157834, '[-0.637324313396194, -1.57689847025112, 0.917671048143363, -2.83681618149499, -0.838599902326643, -0.115953339092963, 0.436287160180054, -0.198810273679015, -1.59661557388642, 0.621985198992814, -1.67892172728516, -2.21434231290518, -1.17819702725974, -0.561841765249186, -0.52350256779129, -0.149958156740237, 0.0363420997301917, 0.470333103166933, -0.806909986909746, 0.165940258356955, -0.002061610294654, -0.0126027785330679, 0.431931858852278, 0.478634109326586, -0.152987133751504, -0.338863984576134, -0.12514648623781, -0.0540566219742693]', 239.0); -insert into credit_card_transaction (time, features, amount) values (157835, '[-0.402507052578237, 0.985184942134102, 0.782167914865014, 0.65501469914171, 1.01980221604131, 0.162967988863067, 1.30684286163706, -0.544255201902881, 0.553265972609925, 1.35127056602887, 0.194178629796895, 0.0226360633595435, -0.71437628656684, -0.463729726724478, -0.96954692983593, -0.900845681999007, -0.609141226227762, 0.581341873668803, 1.19092769318587, 0.508880555870567, -0.0421708374308417, 0.923073375288087, -0.416535325621101, -0.485350248747449, -0.0445354734478045, -0.407512914278499, 0.193432392494004, -0.296088418703337]', 10.0); -insert into credit_card_transaction (time, features, amount) values (157836, '[2.06600812011579, 0.212733685158645, -1.67667616274652, 0.40715771961777, 0.510978546137638, -0.790015457180319, 0.228000247297557, -0.259959557826988, 0.363375521745164, -0.411214817032647, -0.352558855664839, 0.622301334087091, 0.898382128729849, -1.00503720024482, 0.158401967024696, 0.211361309697192, 0.490323784768256, -0.50776489329618, -0.0334631399351485, -0.109995257111866, -0.34778820722648, -0.847448818941393, 0.339761738276403, 0.531585493776343, -0.247659288106161, 0.172541932655976, -0.0538974367239986, -0.0290450111215878]', 1.29); -insert into credit_card_transaction (time, features, amount) values (157836, '[0.0417576258490837, 0.849666970892494, 0.23128169516166, -0.615711165721009, 0.493059001875554, -1.04411168366748, 1.01420179368104, -0.203190219732137, -0.0486971447772289, -0.4142776289848, -1.04226921328416, 0.140920141067685, 0.133708925595141, 0.0849909491972045, -0.402495913302537, -0.0546273603100446, -0.467683543137562, -0.710936730621702, -0.0294000190500372, -0.0194206134345929, -0.266725840713801, -0.591554247389514, 0.0580324998549543, -0.114944660786308, -0.46480139489786, 0.147047769954302, 0.246367806791632, 0.0965567545530596]', 5.37); -insert into credit_card_transaction (time, features, amount) values (157836, '[1.97465908888964, -0.0223951560658185, -1.41708789062216, 0.648787448766615, -0.114031128747409, -1.20724263274786, 0.0206231328480823, -0.209847329147051, 1.02409979572353, -0.58655098654999, -0.569907075300941, -0.237431690507807, -0.96599306826236, -0.82753312955599, 0.614083941341488, 0.155052361083398, 0.676323649846123, 0.299558425306579, -0.283785985590054, -0.232739726316218, -0.0521000212794944, -0.0193475348600889, 0.138452581639282, -0.138786133224291, -0.0454942656006256, -0.335580434307477, 0.0104167148469378, -0.0205564520783589]', 24.99); -insert into credit_card_transaction (time, features, amount) values (157837, '[-0.387011219770642, 0.494090691748053, 0.961992096965214, -0.611490948924778, 0.919883229892197, -1.15211907325743, 1.10392321468602, -0.397080168441054, -0.132434878390282, -0.4965585330485, -1.0314215493946, -0.407010679765922, -0.694604638725308, 0.11989302211298, -0.222157549874694, -0.207746127831496, -0.422062492404337, -0.61908361178042, 0.155466705472628, -0.0168831621875002, -0.251108179557846, -0.620449103204238, -0.0753213384575987, -0.0388695516359171, -0.367655193695854, 0.158839095708461, -0.110907244005624, -0.0818975687330509]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157837, '[2.03782407479185, -0.16442298678413, -1.22529997810387, 0.205262308720011, 0.0863746951306857, -0.590046990996929, 0.0181986252820673, -0.102478635402143, 0.398393562646139, 0.251768551946654, 0.548966423025011, 0.696793939624909, -0.55404384367956, 0.573074716185609, -0.518102950641522, 0.17713032712586, -0.593218344541852, -0.2594430614813, 0.518112629247304, -0.244698119248414, -0.264695666669397, -0.68565680428439, 0.292209606262834, -0.482487368102455, -0.310662369724611, 0.210329901700057, -0.0758539926565251, -0.0759754232909689]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157837, '[-0.531707408435599, 1.45227755432358, 0.025451742188867, -0.575801075336073, 0.402596786634284, -1.24531875260899, 1.22318857142778, -0.436403220795202, 0.254630048132528, 0.993262139497165, 1.59124577093176, 1.27573391576437, 0.752235053637642, 0.044505244536199, -0.319422116170718, -0.605807466352912, -0.703385056832718, 0.277164199461892, 0.020604482519279, 0.492960320494032, 0.330366686815289, 1.59817069089154, -0.0949656118602944, 0.603040508441781, -0.736443525022912, -0.29290976784478, 0.664431490309938, 0.276975750995135]', 0.89); -insert into credit_card_transaction (time, features, amount) values (157838, '[1.91012764654507, -0.214911460242795, -0.149054703791262, 1.23587509910457, -0.614024091646997, -0.222327147820015, -0.640327487495576, 0.141235652060546, 0.745379305996641, 0.408467254876142, 0.776924880566786, 0.613102707751832, -0.683076204345837, 0.34695027642404, 0.1920990820685, 0.604685794990127, -0.913239041756053, 0.807549535948923, -0.570318211677253, -0.303663272429458, 0.276614316427436, 0.9043343788319, 0.155751838809788, -0.0169447489238734, -0.167111441901268, -0.578380903105959, 0.0529191329244133, -0.0420215725506592]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157839, '[1.96256285463695, 0.19629847035573, -2.00081401799851, 0.617643909717091, 0.478082770385361, -1.44344180426208, 0.672101220623945, -0.509841259818088, 0.372268261545081, -0.625001033223497, -0.348249648813358, 0.845402080653515, 1.11002660882389, -1.0075363431364, 0.0183935235966256, -0.180997038667057, 0.610558728570152, -0.179821284582034, 0.0206455926374934, -0.0279161232273599, -0.130514499886407, -0.235961815726805, 0.0432290091998405, -0.179386744023229, 0.196669418587758, -0.379590227879475, -0.0151225713585166, -0.0214028136966656]', 59.74); -insert into credit_card_transaction (time, features, amount) values (157839, '[2.02722978880361, 0.462557604185985, -2.50196013305768, 0.596618746012089, 0.6581273407066, -1.32726737597522, 0.203059082140186, -0.190893505642236, 0.41208365441355, -1.0023855451196, 1.44997587865354, -0.145681667969982, -0.986028701983297, -2.17052348887086, 0.49590435112659, 1.10472977757573, 1.45631195743283, 1.98484866958775, -0.282110157578382, -0.192375331401661, 0.117388668982725, 0.462074767243637, -0.0882561341894579, -0.576061194329224, 0.238862484462931, -0.0971389099578121, 0.0097643554649189, -0.0075869145497367]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157840, '[-0.289766221469332, 0.628559424479173, 0.943144284726303, -0.389692867287835, 0.560809599404991, -0.0491961641241497, 0.588693955780259, 0.110346030595749, -0.763375402564385, -0.281196127532713, 1.06492894781139, 0.443670878478515, -0.144314638995957, 0.553301548272612, 0.51528607876118, 0.139913017084407, -0.436221209582252, -0.0249041546814199, 1.30047059498911, 0.146298291760619, -0.301832802100491, -1.07255262772272, 0.266429405671112, 0.610975875614744, -0.926387177309548, 0.125821169573456, 0.0838071829234286, 0.16018698855591]', 27.56); -insert into credit_card_transaction (time, features, amount) values (157840, '[1.77258351226467, -0.788988000485366, -0.592611225620543, 0.22580449713795, -0.650874285009313, -0.247781807412575, -0.444965604621342, 0.0654538568418677, 0.879930744083094, 0.137735801635657, 0.471242560725537, 0.621001173219971, -0.541254696136626, 0.274544439610745, -0.072302719445212, 0.765234185927878, -0.847630157838773, 0.219210734096822, 0.369042484467334, 0.0171948669582646, -0.176508775391131, -0.724164406200276, 0.291294998619352, -0.430730860425196, -0.68914217577619, 0.227501640378244, -0.0690895260050541, -0.0395666601470801]', 120.0); -insert into credit_card_transaction (time, features, amount) values (157841, '[-0.555276477106862, 0.855721993047392, 0.0918589883442275, -0.760091342228719, 0.0955813626546279, -0.884911601097234, 0.69803317791985, 0.253334566973163, 0.17967836388236, -1.20377641331705, -1.63385983881794, -0.213543161280976, -1.09950980251242, 0.514944666376774, -0.873934511057197, -0.642116336359251, 0.133597304402471, -0.179060455128908, 0.0757904719549056, -0.324517073813025, 0.286660610399304, 0.903979079926945, -0.284215609380972, -0.0327359491682181, 0.0214474605373953, 0.218645838542426, 0.0029078782304432, 0.0951700228296631]', 20.0); -insert into credit_card_transaction (time, features, amount) values (157842, '[1.87447457125147, -1.92605834951993, 0.462380772373881, -0.553780253603811, -1.76137985895345, 1.42200572201284, -2.15937290954825, 0.590852496654097, 1.41873386665477, 0.488476630788313, -0.346948345993439, 0.463015783122129, -0.100675271030776, -1.51393894342423, -2.35623452105639, 0.988065123384293, 0.382699744529149, -0.513633277351094, 1.24038606625674, 0.141293007651812, 0.361983634352254, 1.27709675697346, 0.0354027462051676, 0.368429912863443, -0.253272111779542, -0.0106380542718407, 0.0720308983438213, -0.0266888704510744]', 92.2); -insert into credit_card_transaction (time, features, amount) values (157842, '[1.89162577093522, -0.35717416722083, 0.667425678294614, 1.76515630006475, -0.755774232959439, 1.00248611929123, -1.34007998469617, 0.408196992336103, -0.023652807642118, 1.14023012053801, 0.7844327245034, 1.16309792796846, 1.50231874819735, -0.782873925069329, -0.798034020530616, 1.8282734867967, -1.10357658763516, 0.106351448949116, -1.00204437285227, -0.0440496325347035, 0.18852040310767, 0.646036076974909, 0.385829138989342, 0.831254282443608, -0.953098909022139, 2.17010738401089, -0.115299821991652, -0.0533127892216617]', 0.0); -insert into credit_card_transaction (time, features, amount) values (157842, '[1.97801371722969, -1.06003704155414, -0.0375962080544792, -0.356999933077957, -1.26337356667985, 0.05145658230032, -1.21134001319506, 0.114724054557106, 0.146326136958788, 0.766527474030122, 0.413861570573846, 1.12890909235027, 1.10433409285051, -0.335595946595136, -0.0383281006369141, -0.852525595496914, -0.800280789107831, 2.07625418689173, -0.657695272378165, -0.479890601607901, -0.255169539606108, -0.162339328066228, 0.268953004531386, -0.374446015247298, -0.481871448033971, -0.439245416646459, 0.0744215342111052, -0.0267779011751512]', 46.66); -insert into credit_card_transaction (time, features, amount) values (157843, '[-0.16476058666961, 0.571057429709443, 0.392732635190925, -0.722876478495109, -0.0043006944316656, 0.486237771544567, -0.312000103369092, 0.711764617945534, 0.377263813522055, -0.887539949180069, -0.0915024469963657, 0.913623951596695, 0.333117455302897, 0.0903995810545895, -0.650510595106977, 0.606132797928513, -0.93443806251958, 1.03779619183735, 0.0366614903365086, -0.229734109188045, 0.315207281265638, 0.903593838959301, -0.10630733505883, 0.214837046813191, -0.220446428834252, -0.304785647216578, -0.0510936813387178, -0.0546688222497397]', 9.99); -insert into credit_card_transaction (time, features, amount) values (157843, '[-1.30590884627008, 1.16343275633271, -0.442157013142903, -0.271323551678816, 0.749967454794187, -0.303754881254632, 0.817414039737156, 0.353370181868569, -0.370981728836364, -1.15070060988245, -1.45977383726823, -1.34859152038967, -1.25696966300599, -0.296333337969729, 1.40422773993092, 0.272468046251167, 0.658451690604524, 1.25877604402342, 0.714697813669478, 0.112372918947992, 0.15349443436303, 0.296697885691122, -0.588842036983424, -0.0546777787648191, 1.089016112025, 0.182222970870572, 0.0399234061789595, 0.0503712947333781]', 81.43); -insert into credit_card_transaction (time, features, amount) values (157843, '[2.03298120480541, -0.519250867766739, -0.755020951694331, 0.229512970384677, -0.225139840441982, 0.328881590905993, -0.755790511466087, 0.16696279533742, 1.66457522598513, -0.150521675280538, -1.85991709700497, -0.344120069654245, -0.736174343122989, -0.0549022323684959, 0.736375549012799, 0.327935590851161, -0.705120023593535, 0.534321382323816, 0.0216223944853121, -0.235608640060191, 0.128614965884603, 0.55178110464381, 0.0726469668071797, -0.0922732879710547, -0.0182358331002292, -0.190102810175813, 0.0322620006240155, -0.0402332748670264]', 9.99); -insert into credit_card_transaction (time, features, amount) values (157843, '[1.48741837869265, -1.32344086118531, -0.798170060422109, 0.302493493566117, -0.742597188599083, -0.0343754304195434, -0.289082446434825, -0.0712278515600484, 1.39908116739226, -0.362185965833303, -1.05135663865608, 0.690611131336777, 0.810579406231439, -0.300588494738193, 0.532178798076625, 0.189200896874319, -0.579502115119682, 0.20438418829632, -0.12852123507699, 0.4263491179056, 0.333483684599355, 0.585397235160658, -0.102529488772589, 0.649220117098237, -0.204640769318829, 0.0704243163493087, -0.0370913349684176, 0.0122615838603845]', 283.09); -insert into credit_card_transaction (time, features, amount) values (157844, '[1.98847926751272, -0.438674011257909, -0.0853955437465157, 0.339162822529171, -0.712007567103061, -0.0219103836659887, -0.890245150236702, 0.124223712050773, 1.55566333698797, -0.179120280159013, -1.00061918408885, 0.426288727247951, 0.283524830289165, -0.291086678837846, 0.958926433354009, 0.485204224850785, -0.748190526941709, 0.334781867920445, -0.26839213221904, -0.187479727437693, 0.0618863200466343, 0.3494765019992, 0.293805171014466, 0.651020057739376, -0.350113351336363, -0.438066533233105, 0.054396555577505, -0.0206531008868494]', 2.29); -insert into credit_card_transaction (time, features, amount) values (157844, '[2.05891199440156, -0.179774461961558, -1.12970484192705, 0.408030616671213, -0.227139560654568, -1.12906424418599, 0.0534076449278054, -0.208948076616949, 0.799359081544365, 0.114683304451371, -1.04022833099562, -0.458358239021822, -1.60800641830317, 0.611058117515671, 0.276787720259479, -0.0645365850016284, -0.161308466894115, -0.729608931888649, 0.112422032348397, -0.337898214973206, -0.307885323414823, -0.825574923642232, 0.35919616209149, -0.129837652594825, -0.36056651051359, 0.211158258365743, -0.0784654387523142, -0.064977424796829]', 0.89); -insert into credit_card_transaction (time, features, amount) values (157844, '[-1.2804131924784, 1.82233396280854, -0.0693940062742576, -1.00979846792662, 0.426852296880116, -1.13599059328136, 1.42991556542049, -0.614385394880862, 1.46929046712057, 2.0517432726412, -0.531295713538944, 0.169108808414783, 0.310969373121468, -0.897334666222061, -0.265542726149647, -0.437431147680413, -0.73406559765094, -0.954282341496572, -0.250579647401289, 0.921442306108557, -0.605066642313551, -0.586242535331929, 0.0192424465724631, 0.0005771814038475, -0.249587598326457, 0.0537393513124151, 0.0973312234037515, -0.473180603798492]', 8.95); -insert into credit_card_transaction (time, features, amount) values (157845, '[-1.04017342964516, 0.478068994061985, 1.26254653096111, -1.77784110314035, -0.284508102016783, 0.346007986891355, -0.287310625711571, 0.623377864022016, -1.15174920832849, -0.263121442448326, -1.95459919552996, -0.363526536476605, 0.749634019000826, -0.191738518222399, 0.139910818313873, -0.747937170382772, -0.413011868328195, 1.36049292428697, -0.598319118240791, -0.296736319363136, -0.622118074869156, -1.42517410458178, -0.10634005038137, -0.0119490791002042, 0.273939050943132, 0.42561643216254, 0.127248590380951, 0.0493072559584417]', 21.0); -insert into credit_card_transaction (time, features, amount) values (157846, '[-1.16998501632616, 0.450392812276972, 1.86993548881047, -1.22240944985834, 0.160216720822717, -0.0700201136657804, 0.100492276009131, 0.354659236748992, 0.360202361660083, -0.568240058415776, 0.0069072836545446, -0.583522980993074, -2.0072168154799, 0.178300966880409, -0.437900452625466, 0.838860810803269, -0.966590537413451, 0.920042823709935, -0.568776764468839, -0.133647107239914, 0.215592166131897, 0.638381882539009, -0.58632569625624, -0.381093332856378, 0.633625722529762, 0.700466445548409, 0.104079898614449, 0.0820819296957852]', 2.77); -insert into credit_card_transaction (time, features, amount) values (157847, '[-1.25936237205995, -0.245868072798358, 0.362838361121548, -1.34375786830269, -0.256033687416538, -0.560010425778525, -0.144129097344281, -1.80519185491725, -1.44904261184901, 0.626208886322148, 0.877302394194352, -0.825970454488623, -1.04263154150753, 0.422574823030625, -0.0287707908931669, 0.876279947115107, 0.347987026493651, -0.400915416221153, 1.48851079444722, -0.595862914429193, 1.93485990558038, 0.93219870281267, -0.451096017674422, 0.14402131723528, 0.189719424833817, 0.237770477575723, 0.44963235365984, -0.006833134629177]', 159.8); -insert into credit_card_transaction (time, features, amount) values (157848, '[1.70101712255528, -0.653911951709174, -1.19885043851807, 0.241982152960315, 0.534503896198341, 1.21156062970239, -0.274383046338503, 0.303670847714445, 0.411365996134159, 0.0579316524007709, 1.05771714372146, 1.49604098097081, 0.840306369121232, 0.227411909894642, 0.290174272435812, -0.438222566629529, -0.11552551201505, -1.11745243468877, -0.715074260002397, -0.0207298651157425, 0.127857039855905, 0.406288381680372, 0.114498315645619, -1.58349984636476, -0.372882132761873, 0.324656715163677, -0.0087143897082049, -0.0607143585767801]', 109.95); -insert into credit_card_transaction (time, features, amount) values (157849, '[-2.0689537918788, -2.67806913519051, -0.704399244439648, -3.72072408996058, -1.64253375492401, 2.59784738931079, 3.22197415324644, 0.352375836843928, 1.42130918110889, -3.17499235007923, 0.564008794547129, 0.195029931505474, -1.365736813362, 0.511969001674109, 1.070918834197, -0.394278112992076, -0.588150511207407, 0.467622902134886, -1.27545557469269, 1.61422117378547, 0.920723225101146, 1.15347683423775, 1.83756159463081, -1.07430103913248, 0.274722706086566, -0.909587618782527, -0.0988205827759531, 0.200475636877625]', 915.71); -insert into credit_card_transaction (time, features, amount) values (157850, '[1.9979595211613, -0.236238202694561, -0.299657024454352, 0.382220683158352, -0.622272150638863, -0.69921522019942, -0.446888471611756, -0.0874257918847648, 1.16027938204007, -0.135330853777436, -0.696472899012873, 0.560858325517991, 0.334576542650276, 0.0108274677307566, 1.00701545551332, 0.285868766692241, -0.637068755041453, -0.186410347953965, -0.23243494339709, -0.225710489377349, -0.138284402123124, -0.257183326029473, 0.372755385286338, -0.125934917026405, -0.443633781884186, -0.607855010509986, 0.0381713352632872, -0.0318873278536854]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157850, '[2.0337549284767, 0.134559064027543, -1.70784396766942, 0.762003346736829, 0.175958487238388, -1.15208225189517, 0.130662628191557, -0.307477388906162, 0.763405022150723, -0.686822353751845, -0.627820949394655, 0.307568570219323, 0.324824038472356, -1.80148364270555, -0.466084469214962, 0.134304715945167, 1.16100782967738, 0.165183677772925, -0.071483074691605, -0.140154529127182, -0.0337851948508485, 0.238191571841133, 0.0096459702594858, -0.165512702652204, 0.124603020028329, 0.643740795109804, -0.0385589476695535, -0.0298154750404508]', 9.11); -insert into credit_card_transaction (time, features, amount) values (157851, '[1.85775908884859, -0.031628155917328, -1.81128960400676, 1.05731771669384, 1.17500541309081, 0.793123282521759, 0.287902315119428, 0.187470889368437, 0.00245578781301, 0.298001298167532, 1.04978303171865, 0.987706737891137, -0.680943255646487, 0.865422745965599, -0.389177453163675, -1.3217602820902, 0.370927126768223, -1.38377230755514, -0.903672981803826, -0.377746986204501, 0.166477914664873, 0.742394227957657, 0.0301588518667023, -1.3481952293484, 0.234932931562616, -0.395908981632443, 0.0272869981967712, -0.0849084209723135]', 18.63); -insert into credit_card_transaction (time, features, amount) values (157851, '[0.133841777275129, 0.91340732317306, -0.586068888298282, -0.752408102671662, 1.09916983386924, -0.279001883907169, 0.812982984656937, 0.111391493274789, -0.149918873336896, -0.641433939672887, 0.470984292055473, -0.02513641809735, -0.848115166541602, -0.678400181419487, -0.814746273681456, 0.696155460703694, 0.0040787440014157, 0.527011768958075, 0.231507646321294, -0.007882666267082, -0.328024520616025, -0.872410982177272, 0.0416231537260778, 0.067256898394634, -0.420720022763395, 0.12474165322144, 0.212056680035392, 0.0679584688667059]', 4.56); -insert into credit_card_transaction (time, features, amount) values (157853, '[-0.418279890450697, 0.81579536323124, 0.368985412027566, -0.637428195883281, 0.850412176076468, 0.0572675513367951, 0.310865439387002, 0.0978606567568951, 0.58870205999343, -1.10848075352022, -1.23894810448455, 0.0652587725700526, 1.12378477233819, -1.80700428143635, 0.45155641578147, 0.694948606653118, -0.0428357439733203, 1.1253942564681, -0.338690994174335, 0.111952288788801, 0.171215003939959, 0.780982657540377, -0.273413739226443, -0.0210120211562227, 0.327827801321158, -0.119782180410774, 0.212917048824943, 0.114382596885579]', 2.49); -insert into credit_card_transaction (time, features, amount) values (157853, '[1.47544036344737, -1.58256845976234, -2.89705666475184, -0.30023943531686, 0.0922802918639253, -0.966930393751996, 0.982769244532117, -0.595733424446083, -1.54815582093274, 1.01063410891185, 0.790592481784231, 0.707077874113169, 0.47990785366851, 0.868639336480863, -1.05122411892755, -2.05003115053192, -0.0829270823298786, 1.13672333431214, -0.505883458584193, 0.213272643794415, 0.183343376120601, 0.247238083150039, -0.408659751586596, 0.869738126179322, 0.361807787372725, 0.920997248054669, -0.200351659289703, -0.0265149795267364]', 394.99); -insert into credit_card_transaction (time, features, amount) values (157853, '[1.92287448702174, -0.554943829608252, -1.63975639957667, -0.44165434257599, 1.60555989801129, 3.87214829745946, -1.58918894332324, 1.16181376627752, 1.09369688167302, -0.403028952943393, 0.374688967611876, 0.0267785971742734, 0.164138842084068, -1.31148323379252, 2.00852008253198, 1.34273225417583, -0.0890269972747848, 0.916779918391951, -1.04710167378957, -0.0406077881672269, 0.186853826891385, 0.520044260158824, 0.26562660330476, 0.621437877059116, -0.510364496039619, 0.324701271059333, 0.0504415899514766, -0.0075721997728669]', 16.26); -insert into credit_card_transaction (time, features, amount) values (157854, '[2.21536640244687, -0.761832351460431, -1.44009502509636, -0.982544007461661, -0.441309728945228, -0.926601129697856, -0.393720326013322, -0.186882566749054, -0.538050863033201, 1.00159439142156, 0.513079455713455, -0.465511856216402, -1.12261178229244, 0.380478446107364, -0.868930711070512, 0.965109852963288, 0.093271830946926, -1.13402915369833, 1.2462731890581, -0.125468256071979, 0.038631357864001, 0.08318456191179, 0.162091625555105, -0.357887959147389, -0.0362178780142174, -0.273892481450678, -0.050224878924179, -0.0805616994704347]', 3.71); -insert into credit_card_transaction (time, features, amount) values (157855, '[2.05111836839243, 0.15740855574506, -1.77858292410485, 1.30581548131097, 0.554152759147043, -0.934726134885325, 0.588798593382001, -0.351999236803142, 0.342446185020113, 0.27932995848784, -1.4621011097146, -0.206990119069699, -0.939526774434236, 0.658990785611951, -0.406651200617979, -0.585834138272509, -0.231079702688799, -0.436103086097665, -0.0668402513658939, -0.3307773289533, 0.0164457752436528, 0.236933609967714, -0.0454524536230938, -0.43373260337407, 0.48577564734282, -0.462149301834284, -0.0206162388502714, -0.0672376011113651]', 11.46); -insert into credit_card_transaction (time, features, amount) values (157855, '[-3.71532525934512, -2.07197333799974, -2.04610422655669, -0.396167587198657, -1.03145282756029, -0.0103205086914879, 0.488058836771038, 0.820881967706672, -1.88922686639007, -0.477766366478084, -0.663032389232418, 0.818952495741138, 1.41412180788548, 1.14596253861254, -0.294753297910607, -0.913476925981963, -0.263414539003976, 2.46725934422878, 0.0130169566719335, -0.416706840325311, 0.208040654412326, 0.318879740222887, -1.09262117812668, -0.897391142591055, 0.137042600655579, 0.0064575342940457, -0.247580678883342, -0.536546546537076]', 334.0); -insert into credit_card_transaction (time, features, amount) values (157855, '[-0.530909875155746, 1.17435827853442, 0.336783716800536, -0.614669457642115, -0.0192581354577398, -0.806302148792159, 0.337612201591243, -1.61704742305679, -0.0850360782366578, -0.08048384622935, 1.12032887671022, 0.699680935363251, -1.03575772016956, 0.558804302624249, -1.08897693923071, -0.0095915894878863, -0.281210448171338, -0.308834647498908, -0.0332952070081408, -0.430407538232863, 1.34410810446113, -0.943107703618564, 0.363276105804988, 0.490827843034998, -0.584133869196096, 0.101312190916888, 0.311724568192207, 0.105158942451035]', 7.18); -insert into credit_card_transaction (time, features, amount) values (157856, '[2.01540437435644, -0.111465787280573, -2.08860495970329, 0.457634705801435, 0.368061511330875, -1.45072604984734, 0.733388380109151, -0.473974788176933, 0.55310744822025, 0.0030824437059599, -1.13350897009547, -0.290800359929977, -1.34187000512968, 0.897001670784938, -0.0164148055050148, -0.846185005698976, -0.032998027637546, -0.459026116964284, 0.139900996870749, -0.256544189397996, 0.14214005213038, 0.496488953738721, -0.116455129676418, -0.148894131920432, 0.509548567209587, -0.0566273144356917, -0.0660938175389855, -0.0710031420590403]', 50.0); -insert into credit_card_transaction (time, features, amount) values (157856, '[2.11410663455505, 0.221262303751733, -1.90895918004813, 0.279334454292127, 0.776150447661988, -0.544063738201821, 0.246480735696864, -0.26240861999487, 0.369526832558714, -0.408771110807906, -0.872743867506429, 0.535175038487399, 1.22828334169484, -1.08973177434185, 0.127805899621275, 0.425140590827894, 0.214414741259754, -0.261083703055955, 0.250943509101405, -0.0697879472999849, -0.388131869207295, -0.957464582459925, 0.25962582353087, 0.0192075506697944, -0.149273411842119, 0.201847314090332, -0.0564306681947466, -0.0336757521987126]', 1.79); -insert into credit_card_transaction (time, features, amount) values (157856, '[2.05534908604041, 0.0841374965825322, -1.29722359923244, 0.33111646993233, 0.153078401225327, -1.12754270891507, 0.29442090303109, -0.403542072735935, 0.374511579862079, -0.0294502273364214, -0.179856858308834, 1.02373714614744, 1.24148684657356, 0.252718846228885, 0.624932005265181, -0.351854302151727, -0.464742147968007, -0.296263238405889, -0.365638899418296, -0.144354978991445, 0.278485159894634, 0.984355184443863, 0.064104682998156, 1.21596852576972, 0.278990261805842, -0.171699129172392, -0.0165538768696907, -0.0449067067384646]', 3.79); -insert into credit_card_transaction (time, features, amount) values (157857, '[2.062958371039, 0.0374118687130256, -1.23238631328565, 0.354402294981913, 0.0255049866263097, -1.23013794186386, 0.249955473863987, -0.412144622270941, 0.504484687246529, -0.021886362923122, -0.503478024728184, 0.774307206790292, 0.933662823360504, 0.291939208034237, 0.727805958460171, -0.27854796170213, -0.513597148924842, -0.216909366100751, -0.332601982233066, -0.196549557490007, 0.274938407751407, 1.01393494641999, -0.0032273479077474, 0.0485636061013697, 0.268049133291928, -0.101561794485043, -0.0072822780080278, -0.0563001426893159]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157858, '[1.18157870250369, -2.26084423770886, 0.328917436013441, 0.359712601878124, -2.46558566741515, -0.623433771763082, -0.817246592064876, -0.164288768593195, 0.385780619264421, 0.38947186814969, -0.124518005204928, 1.21158132789166, 1.86252347165147, -0.690367423879642, 0.747558107269647, -1.20363557096104, -0.246565966172785, 1.53137017520168, -1.72640925552612, 0.303274489442358, 0.212195378393862, 0.415929782511567, 0.0063310035918036, 0.958262657320884, -0.697765868671362, -0.375895419118922, 0.0304260329009418, 0.0674369928222688]', 427.8); -insert into credit_card_transaction (time, features, amount) values (157858, '[-0.285060437222363, 0.398444681342833, -1.63777311632013, -1.25444027336329, 3.52089269019313, 3.04248046652764, 0.343326673841843, 0.818680942487868, -0.39610984935726, -1.04047177138057, 0.185781787589992, -0.344012476237531, -0.298991365523662, -0.538194721490538, 1.13177946103248, -0.0926321684099298, 0.391015259888771, 0.638623515519903, -0.201123728209062, 0.130945753989379, 0.364238611494246, 0.920123282286803, -0.121531199871469, 0.638238398796436, -0.320486640294529, -0.122157560964199, 0.216835034408679, 0.233610744325548]', 31.33); -insert into credit_card_transaction (time, features, amount) values (157859, '[2.25531756741648, -0.728737266335447, -1.61407454275529, -1.04719983638802, -0.255346188428555, -0.855547645554183, -0.394301485905557, -0.295472444662657, -0.458816204961659, 0.885603993615658, -0.990917799826062, -0.991988740209498, -0.154195209329196, 0.0816910672084263, 0.439545317703883, 1.0181100669324, 0.0370028413909377, -1.11427321253212, 0.553885950892409, -0.0191625160524406, 0.402426751515702, 1.12458222329607, -0.0113625780670281, 0.521917148016722, 0.249189228682813, 0.052855380599109, -0.0473898334149382, -0.0623947804171946]', 15.0); -insert into credit_card_transaction (time, features, amount) values (157859, '[-1.76156073693198, 2.24809372244951, -1.62956269742749, -1.61315396238162, 0.795771625258495, -1.40296619787448, 1.52316929236213, -0.207766560200248, 1.02074902604269, 2.08673774061626, 0.469382157875629, -0.203142738431112, -1.64396640553965, 0.573774804015273, -0.583698249471286, -0.504210017428086, -0.790736305530579, 0.24938292184699, 0.0739926413176555, 0.782990121796363, -0.010993774693265, 0.757758644884818, -0.237946347399714, -0.3461125366316, -0.0115550313594168, 0.069825569513537, 0.660851089908105, 0.188171830007109]', 7.69); -insert into credit_card_transaction (time, features, amount) values (157859, '[-1.49690673173603, 1.21086579197235, -0.0045701849654747, -0.258420767092212, -0.0725201006481231, -0.402729968702352, -0.384362184970498, 0.935465162541433, -0.0116594093433838, -1.31028519583209, -0.803422742830355, 0.395364963809889, 0.689080294918112, -1.03297507055313, 0.304272957686309, 1.00151092125707, 0.648408728057791, 0.274869037765567, -0.514391647279716, -0.0982329000933663, -0.162758470401473, -0.732194481053031, 0.0734308530124817, 0.560831525503217, -0.204672591618141, -0.0322806502465715, -0.254617060241025, -0.0232005549027079]', 10.0); -insert into credit_card_transaction (time, features, amount) values (157859, '[0.132328260110561, 0.559162285845658, 0.463002797535602, -0.317521049404263, 0.808976543454281, -0.982835849392863, 1.23199499936075, -0.753896960395423, 0.264605008197533, 0.227898100067521, -0.662527026864023, 0.0057162107925079, 0.0801521555170468, -0.30278503733417, -0.0589371603046416, -0.528320150031622, -0.415717435275568, -0.843314888906276, 0.362569532263927, -0.047478146484045, -0.245992985421662, -0.326829587263855, 0.102511555820814, -0.0073609724267186, -1.02420721871642, 0.0643554156859474, -0.512804210146063, -0.330712800041969]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157860, '[1.77515295239732, -0.991510743470274, -1.96380871022228, -0.883603012511522, 1.71194224603874, 3.70009539285151, -0.910823445845902, 0.962892631161506, 1.09011834416348, -0.238640606497804, 0.019527909849207, 0.556805701145316, -0.0295507095468021, 0.211939250823184, 1.09147637936223, 0.121754209402216, -0.569456967259642, -0.457012463675216, -0.0907126191866462, 0.0955213154367886, -0.174089094668087, -0.73644068780735, 0.34900319133562, 0.67518345755326, -0.514468017508317, -0.316209291717666, 0.0028495279318687, -0.0238627050949399]', 119.0); -insert into credit_card_transaction (time, features, amount) values (157860, '[-0.142051582617379, 1.14096330176463, -0.442775972771893, -0.689439971531945, 0.879699015057055, -0.515459217509872, 0.849827736770779, 0.0695165633625453, -0.110815299190136, -0.363991587525768, 1.17155245741182, 0.582184104103802, -0.210818676307783, -0.85694528816157, -0.873943846180469, 0.419066586515102, 0.212774650613408, 0.148185277579467, -0.0860482474064571, 0.138711262148833, -0.308359558058872, -0.706423117840218, 0.122292249135052, 0.594315940972221, -0.433115110251284, 0.0975585641889865, 0.32854355269546, 0.134657321110325]', 4.97); -insert into credit_card_transaction (time, features, amount) values (157861, '[-2.96357080997129, 2.1650067956824, 0.103935712419153, -0.232358239340725, -1.52231571253481, -0.532397029409427, -1.29355065858134, 1.99123436226992, -0.625109756177384, -1.73787167366151, -1.45388287367673, 1.36329608350479, 1.34786629257774, 1.13657125749964, 0.472572444135707, 0.443900769910772, 0.433047559881013, -0.0106435985743426, 0.379947648506217, -0.586620813757666, 0.106928927356735, -0.447181571140975, -0.0638718333482507, -0.0865347151317248, 0.386370510086327, -0.454903224457373, -1.05082280836792, -0.311628524991711]', 0.12); -insert into credit_card_transaction (time, features, amount) values (157861, '[2.21823721149997, -1.46315018810705, -0.785747596251717, -1.62152252214866, -1.29816006129773, -0.447642348865608, -1.19845341566177, -0.121523105986679, -1.42038775438825, 1.70346303804077, 0.494806859794691, 0.123070103989853, 0.98254284422534, -0.428370958633208, -0.864473775530415, -0.238108251523691, 0.0738189020231212, 0.481722840904335, 0.210614311839494, -0.335280365141519, -0.10672229859758, 0.166967968847933, 0.174978613195283, -0.338981886745532, -0.22986492283471, -0.182060726507927, 0.016310364056674, -0.054457048899242]', 39.2); -insert into credit_card_transaction (time, features, amount) values (157861, '[-0.456886723145933, 1.05737971736289, -0.0166428949712578, -0.867822511754261, 0.553752975439729, -0.541404530688917, 0.848166160282426, -0.0619542776405086, 0.0902244542089866, 0.28671470250161, 0.515820739541806, 0.584191238398215, -0.319280721913853, 0.213434091443719, -0.967656370746243, 0.109949544499459, -0.727922515335695, -0.229542248742426, 0.235348489617812, 0.0528061154988361, -0.223781080349237, -0.545599860580502, 0.0466600665834584, -0.415477587760806, -0.473034983292476, 0.1258925391657, 0.0736249192326495, 0.152394338664803]', 7.14); -insert into credit_card_transaction (time, features, amount) values (157864, '[2.03894121293921, 0.241511138776091, -2.79413442153445, 1.15723274777169, 1.32688267168467, -0.109779510107214, 0.38911098925061, 0.0188212010951561, 0.314203110815138, -0.121782438684363, -0.190421950114032, -0.970514118290818, -2.70138656250686, -0.3582982054163, -0.673517343462302, 0.385869847159292, 0.523906864519133, 1.17171606333828, 0.257701273252827, -0.323399717409358, -0.0776003431449847, -0.190486871599213, -0.107993634449155, -0.54925052392386, 0.498880489443572, -0.468905203526214, -0.0245221037817681, -0.0464512070867046]', 17.18); -insert into credit_card_transaction (time, features, amount) values (157865, '[-0.313323463958786, 0.632376259311107, 0.29512940271073, -0.633751526769824, 0.521940269990254, -0.927914785959757, 0.872894367941366, -0.103640554904512, -0.22899830031809, -0.125025558359861, 0.866704035821042, 0.859562676711219, -0.0711443171864997, 0.271862000867153, -1.08838932474487, 0.0745732129293522, -0.639493412401333, -0.283686108094917, 0.192923938815524, -0.0788723236117352, -0.201694313601081, -0.422014083402148, 0.277153520229165, 0.0661532314380647, -0.492290471915714, 0.110904549820421, 0.139240068148655, 0.0612397718041035]', 7.14); -insert into credit_card_transaction (time, features, amount) values (157865, '[-0.283381145646162, 0.865941939843279, -0.304250232515033, -0.477897404666189, 0.33665478710437, -1.15208798032244, 0.698611426428284, 0.166240510927027, -0.212691520738045, -0.782183846435798, -1.46238731323645, 0.0651593562090485, -0.325187834913675, 0.562219757664704, -0.767158714520289, -0.130305346440044, -0.187905707397729, -0.585587193521494, 0.112876711725679, -0.282981722857364, -0.0363362290512662, -0.160842678520698, 0.191091025307775, -0.104403114298763, -1.22209681434188, 0.0862144881157604, 0.0720594421031196, 0.169780033801031]', 10.74); -insert into credit_card_transaction (time, features, amount) values (157866, '[0.0213854350252852, 0.0779246208762383, 0.758548415858107, -0.42678718817739, -0.336747025765528, -0.524122517788203, 0.543094355937069, -0.017708618858103, 0.605688140202642, -0.764610436739245, -1.03918633964772, -0.0929879626083142, -0.42364553523217, 0.0329404635775625, 0.556115631785696, 0.0101720039707508, -0.388122197905019, -0.121009201269123, 0.272664946939963, 0.0603466582067189, -0.0707435185515384, -0.300752074705935, 0.463839356256913, -0.140340455531774, -1.13261415329168, -0.37629378405746, 0.117633760642754, 0.129313289839772]', 96.85); -insert into credit_card_transaction (time, features, amount) values (157867, '[-0.68779198262862, 0.996084243399009, 1.02123215795639, -0.392809937789044, -0.16316483379291, 0.0301552356689265, -0.0988483202813573, 0.55614497632988, 0.317956847278456, -0.898342596399979, -1.23568736479504, 0.608120812575767, 0.976925263312046, -0.156951160775036, 0.268495717458668, -0.0357724986714881, -0.319629018399072, 0.405532513172817, 0.177933348426048, 0.0292873229780241, 0.268655452237953, 0.977792758049683, -0.201545123771574, 0.759883645495179, -0.129958835774833, -0.18557041036972, 0.325164390155835, 0.176550972309605]', 0.01); -insert into credit_card_transaction (time, features, amount) values (157868, '[-0.364398348967928, 1.59733315853756, 1.75161321849181, 4.29005549101201, 0.264393178921372, 1.36451601362395, 0.0807976973315875, 0.269726675523837, -1.40074952428764, 1.8134334456855, -1.16197755162496, -0.0040626198491432, 1.74467935667803, -0.592694831930135, 0.567361756319281, 0.0406961523874426, -0.0962061966950021, 0.413457025747264, 0.990609721824906, 0.555365594380113, 0.192101834579288, 0.974530389567436, -0.0768549533097639, 0.708801447086545, -0.509850513824215, 0.427342092313316, 0.614883397179661, 0.327002375779003]', 20.0); -insert into credit_card_transaction (time, features, amount) values (157869, '[2.06980685354973, -0.863579693969263, -1.42740541359924, -0.845321005129525, -0.413993431215116, -0.0351673461050645, -1.05471785618858, 0.140981924657615, -0.11025526985459, 0.236675832460463, 0.905396069794825, -0.491467755021709, -0.280190576610429, -1.84597484185882, -0.18998139156363, 1.98741978365491, 1.01975257463699, 0.201878094427111, 0.596009066557203, 0.111845716423449, 0.274006710999891, 0.72708219119874, 0.0567390972955766, 0.109913329663389, -0.142530876045586, -0.109784085979704, 0.0140180672730919, -0.0153263458042373]', 49.0); -insert into credit_card_transaction (time, features, amount) values (157870, '[2.00980304896714, -0.0611619152510945, -0.994514023349943, 0.318080889495356, -0.0803144339766726, -0.927732723415108, 0.126286901259942, -0.227986958836113, 0.185579222933123, 0.22379387547165, 1.14194046649691, 1.47306147454536, 0.555559836925861, 0.360153045072208, -0.732011279476894, 0.0364926847927436, -0.538716634964072, -0.476960754806422, 0.395941218220649, -0.174752319866999, -0.223541365552769, -0.521903295590109, 0.330606403083856, 0.0937673580176166, -0.321557320019921, 0.17051713159915, -0.0708969036195145, -0.067584936177259]', 3.59); -insert into credit_card_transaction (time, features, amount) values (157871, '[1.46500439134067, -1.02205465396596, -0.962494360832829, 0.951331138850521, 0.388866090669564, 2.07794617347438, -0.659606104718875, 0.624189304870921, 0.738709058529508, 0.179711775348874, 0.668109972797724, 0.605067416568192, -0.430424249114796, 0.387392943427837, 1.02383503769648, 0.0668671309150085, -0.449804739256787, -0.129312814604111, -1.32718686161072, 0.0834228851888532, 0.418729406050595, 0.920927985217283, -0.0067786229360114, -0.967583994709863, -0.315062701360656, -0.499281977467194, 0.0559284370542651, -0.0174922161053317]', 203.65); -insert into credit_card_transaction (time, features, amount) values (157872, '[1.99647328097931, -0.0381841365560539, -1.63037686768932, 0.510740886050215, 0.306297274192582, -0.373240479551309, -0.118707476599749, -0.0066143975628803, 0.596754410795014, -0.344505737253383, 1.0215691905776, 0.750525324571754, -0.425349883522695, -1.06072807181574, -1.05617363268476, 0.148392899669498, 0.727410554509579, 0.453266133022171, 0.160628028154977, -0.17994528471532, 0.039707920133854, 0.358452898449485, 0.082079749014033, 0.66443916446072, 0.0546860860072242, 0.589264082461755, -0.0519493845136182, -0.0434301095203548]', 2.0); -insert into credit_card_transaction (time, features, amount) values (157874, '[2.07667621413615, -1.14266363000882, -0.196127468714129, -0.661195101757663, -1.09178595073599, 0.399910473942942, -1.44816337694613, 0.135126214003721, 0.254706538211903, 0.817920535569862, -1.5668839399739, -0.101350586892645, 1.30479553553733, -0.589712907860213, 1.3885558597828, -0.239164211901475, -0.982387371879407, 2.00395351833037, -1.12473022788478, -0.402397001917534, -0.149441799666046, 0.0453216196244074, 0.253415270951199, 0.0431764136687273, -0.599204880379358, 0.605916449990743, 0.0113482288645007, -0.0223315212734847]', 45.9); -insert into credit_card_transaction (time, features, amount) values (157874, '[2.18843802436568, -0.412798189654439, -1.6295927808053, -0.211671821073954, -0.184440128614853, -1.36486559600937, 0.237835818561819, -0.574413031439371, -0.889479299724334, 0.887774784741999, -0.909480538058839, 0.680776627888251, 1.35767112811994, 0.048290968809378, -0.768194125342138, -2.18238506188074, 0.138753144521003, 0.353218149564336, -0.578375843433238, -0.551831265129919, -0.342896043061234, -0.254675497843972, 0.105143081167337, 0.105657412126341, 0.165450240296441, 0.601038343499216, -0.068177613463495, -0.0700240680016269]', 14.0); -insert into credit_card_transaction (time, features, amount) values (157876, '[0.05766828044699, 0.795595532573441, 0.212103643328337, -0.611327658013335, 0.3878452830345, -1.06458305943904, 0.940253876951564, -0.141010009339799, 0.118105158088936, -0.380658366271332, -1.23010504338887, -0.445946319623032, -0.969892946930854, 0.303356897373207, -0.282364792772973, -0.0031631419261157, -0.404746746645889, -0.577389969340814, -0.0213295548251179, -0.101194628914302, -0.282593449988528, -0.680626109535534, 0.0607788818246599, -0.14469382272303, -0.504107662577845, 0.15083550838898, 0.240837185041486, 0.0936294135667924]', 2.28); -insert into credit_card_transaction (time, features, amount) values (157876, '[1.54785715827941, -0.985304866879443, -0.338721628084299, 1.59768003853413, -0.677484352390009, 0.464078604060804, -0.479724304549656, 0.167239802283361, 1.50822093207687, -0.0863835190177967, -1.62791013508354, 0.273970136809261, -0.493270440442393, -0.354579688486155, -0.616648974019689, 0.0470318673341477, -0.323158342674437, -0.106907556534061, -0.0988073573640446, 0.135468914465149, -0.116289824802597, -0.526088358581744, 0.161008144658474, 0.523077344490894, -0.327561547912714, -0.905578537885612, 0.033064247033536, 0.0144412227555499]', 207.97); -insert into credit_card_transaction (time, features, amount) values (157877, '[-0.234077557803502, 1.05382611960802, -0.29533586182078, -0.931633798689611, 0.984728925396521, -0.242332234035449, 0.946296152054668, -0.184674576244223, 0.17194563917938, -0.0957683505043199, -1.56559722765138, -0.0745298580635738, 0.321109682303334, -0.0848462704632371, -0.29970536622435, 0.10814934943764, -0.734561282503127, -0.509340662270577, 0.217451078670974, -0.0174220321554876, -0.259844100523559, -0.755727625854643, 0.0308405743776666, 0.025659380870398, -0.400666345891702, 0.11108107565499, -0.167821624370546, 0.0921694873115362]', 5.99); -insert into credit_card_transaction (time, features, amount) values (157877, '[0.0397928079975763, 0.74938020001181, 0.146912561105988, 1.80354074417267, 0.796011893126402, 0.62870877871757, 0.835704966313316, -0.0601162510144385, -0.712171607054627, 0.193352872838765, -1.52422517913491, -0.477492078900505, 0.28451354668182, 0.358936115673517, 1.33482255639452, -1.17258987588461, 0.313593799999029, 0.559912710790312, 2.49465459614725, 0.411515052395084, 0.288991006705053, 0.920210390402821, -0.129488800757688, 0.0600154896854977, -0.156255769008756, -0.0638682267914006, 0.225413282865286, 0.201849964297183]', 83.5); -insert into credit_card_transaction (time, features, amount) values (157877, '[2.11129378499563, 0.317328116684567, -2.49533074047541, 1.18132367306935, 1.03109789401673, -1.15133128671849, 0.931180264508032, -0.431307889682383, -0.0403003450373583, 0.431813061611664, -1.22131147221688, -0.809473791630871, -1.90150265231977, 1.22799810095014, -0.0648155960119166, -0.79248207213154, -0.117799651163266, -0.292387768620937, -0.306107816557538, -0.392207011700612, 0.277229503225996, 0.897965696195175, -0.169973589842068, 0.651934146411564, 0.839757062608298, -0.215342812256031, -0.0662014272622437, -0.0770319699431879]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157878, '[1.88014049625136, -0.237915221632302, -2.68383509619243, 0.291842672945627, 0.817611167690785, -1.21352252150818, 1.07424358470135, -0.501471875920381, -0.0981340095280535, 0.195731610420852, 0.523539217310717, 0.555860311059213, -0.749224032964665, 1.20601245536685, -0.680564876462848, -0.748008799248941, -0.402836685949778, 0.0955972112171333, 0.425646799639706, -0.0479670438834034, 0.391203211452122, 1.03111629250031, -0.37490208150116, -0.393956676004386, 0.774109915388234, 0.121629744713442, -0.104018722567514, -0.0801718998545801]', 124.33); -insert into credit_card_transaction (time, features, amount) values (157879, '[2.17249892419831, -1.19096549444029, -0.0820010124180848, -1.03231844185029, -1.14909029170875, 0.452251201616478, -1.67737188615546, 0.177969627761094, 0.578871096444642, 0.657675214838819, -1.44792273988426, -0.389860158659066, 1.21203122059043, -1.07071820375731, 0.649993197850087, 1.87199488665078, -0.435020210952003, -0.482944058225307, 0.468778278027942, 0.0873642012900552, 0.379627259603342, 1.19511009675924, 0.128584887597207, 0.0843630768514963, -0.279292267411652, -0.0835766872830982, 0.054316729364895, -0.0298474643347014]', 12.5); -insert into credit_card_transaction (time, features, amount) values (157879, '[2.05274728685734, -0.0921879761644723, -1.07581748328731, 0.413504357792781, -0.152692598186371, -1.13971030557606, 0.139878225827251, -0.283681119701624, 0.608005168768671, 0.0779160657351227, -0.767259767413408, 0.219649199574464, -0.389119867253037, 0.370540731637524, 0.136707508528965, -0.142685842533258, -0.20600912126465, -0.903405584650418, 0.0772074304777765, -0.25908874294004, -0.288438541424859, -0.712356227033048, 0.352169010186753, -0.0255118942847336, -0.328717016970851, 0.202547534660297, -0.0705314864338868, -0.0614292578826149]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157879, '[0.0499921391158288, 0.876540077253547, 0.234221984885402, -0.620767325755901, 0.497596967404754, -1.0297796169993, 1.03939385135476, -0.216264705987973, -0.0812897635797646, -0.422088681926887, -1.00690501267434, 0.249624464111733, 0.340016138971994, 0.043358866927684, -0.425613056898751, -0.0638752124109122, -0.479783771655713, -0.736418897207415, -0.0310561164433962, -0.0082480248844283, -0.26505874450633, -0.57388835489194, 0.0544918040615365, -0.109312303386803, -0.458128631712838, 0.146331532986451, 0.247972565389031, 0.0967836731969802]', 5.99); -insert into credit_card_transaction (time, features, amount) values (157880, '[2.18412950325262, -1.17588049487899, -2.49646100543981, -3.05990952731444, 0.0497895904672459, -0.676950084196004, -0.102980791487013, -0.279683520269764, 0.587137340424869, -0.232910913897533, 0.218496124850071, 0.852689399447933, 0.114945152661132, 0.674168499828891, 0.452429361741913, -2.45808301404821, -0.298995865623851, 1.92353413931694, 0.875548245488397, -0.473957268907759, -0.217498156183065, -0.0575001281047381, -0.0744074632049275, -0.210324042823218, 0.429109206351033, -0.698235426900213, 0.0185080178312527, -0.0615865586600772]', 59.99); -insert into credit_card_transaction (time, features, amount) values (157880, '[-1.06141414204234, 0.728974303142099, 1.08044604195431, -0.53029453873708, -0.385430298477668, -0.485635702052261, 0.0165347810990226, 0.395749255245726, 0.244397134188002, -0.748882156252739, -1.22066208931087, 0.659063861137433, 1.18112203101784, -0.318163036737898, -0.195313630606613, 0.344152256796273, -0.484808107220988, 0.137076343601191, -0.387393530591788, -0.0080358257694072, 0.324178699193292, 1.0769959217569, -0.133239824117183, 0.0721063166568859, -0.265658562316117, 0.589497114652848, 0.140525620305627, 0.149831329425266]', 29.99); -insert into credit_card_transaction (time, features, amount) values (157880, '[-0.19940084273604, 0.612922008795064, -1.21906689030795, -1.76966119605003, 3.4850369490411, 3.41450792570283, 0.962793590572686, 0.0625071342201286, 1.06783712241049, 0.758181154263826, 0.460265311078421, -0.594123157223443, -0.476472059383078, -1.98053908513163, 0.437586324694517, -0.0491812386625616, -0.115456079970591, -0.0363571101002415, -0.661538697121491, 0.542658964373006, -0.261391738675452, 0.204753248298129, -0.0592533914170301, 0.624832210996268, -0.621098875236332, 0.274658083866873, -0.220523290165708, -0.5748785245172]', 13.32); -insert into credit_card_transaction (time, features, amount) values (157880, '[-0.41985234564337, 0.618955524398471, 0.507638907398175, -1.09150550964316, 0.817598217643477, -1.04373945707786, 0.959073952698126, -0.0872551994018337, -0.303732294801804, -0.732927476835559, 0.692179944556287, 0.288896432098005, -0.923384603637609, 0.703249973220436, -0.589076403835129, 0.143202589420198, -0.946366646308019, 0.551598952429705, -0.739042484138003, -0.248954097149514, 0.430508818458542, 1.19171137287465, -0.315690086574632, 0.0305521026729413, -0.0996383991449203, -0.287753956974471, 0.134165628875969, 0.162470442333951]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157881, '[-0.939028004949903, 1.26138096622124, 0.723069981579476, -0.110048815111285, 1.13007185102484, -0.901947848892352, 1.81466311432403, -0.333335789704342, -0.786318984402208, -0.809032920158632, -1.22744283894911, -0.25843558856076, -0.635038510079284, 0.390143033393132, -1.07381130681591, -0.557902140313106, -0.34731126441343, -0.539255518277191, -0.750070846515459, -0.252976166214478, 0.0562515738915695, 0.185962275177467, -0.603705345473185, -0.0412560131521469, 1.32848405878253, -0.459214701431163, -0.132159646216888, 0.0312294103684668]', 28.74); -insert into credit_card_transaction (time, features, amount) values (157881, '[2.11304230886494, 0.530154513613536, -2.81664193554979, 0.527859691099781, 1.04269007921069, -1.13524227705307, 0.318297877090455, -0.300986443269425, 0.62550066218622, -1.19703858237365, -0.743395228863856, -0.722311824109756, -0.152322343729143, -2.52960760843535, 1.22842383686647, 1.03292820979781, 1.46277361250566, 1.56159289500729, -0.373073483521788, -0.146046251954931, 0.030844473814821, 0.290235591132129, -0.166683325800332, -1.28615201751914, 0.372326800865178, -0.0314536687874676, 0.0198887532288243, -0.0040164459182145]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157881, '[-1.13257586532279, -0.878240414827419, -3.36433682323203, 1.45537351412798, -1.19158444676292, 0.264668874952401, 4.15572534209539, -0.210224185199998, -1.0089792070866, -0.490214283065661, -1.61796369469165, -1.17253055092891, -1.68772444390201, 1.62876467981738, -0.113151668758188, -0.950419955938666, 0.176847490290452, 0.38877382340554, 0.276706570500428, 1.58712438193028, 1.02239095805706, 1.60690233967136, 1.98535538806822, 0.557287375867389, -0.782758603481381, -0.406985188241554, 0.175998836780809, 0.407587130052964]', 847.67); -insert into credit_card_transaction (time, features, amount) values (157881, '[2.21854226765637, -1.51776618124299, -0.370169379322724, -1.61668373152127, -1.44618001177003, 0.0739980299342651, -1.60974220899998, 0.0433879464774352, -1.20543494083244, 1.64435907351827, 0.768865512009266, 0.572682191305892, 1.69032513727449, -0.846688981875068, -0.924081503617257, -0.228677729536057, 0.0959709836855245, 0.674474124257206, -0.0599748096083292, -0.309485728629236, 0.112441076739675, 0.913536019091172, 0.173551124535822, 0.810038836595524, -0.184917731097518, -0.0488764379725436, 0.0450803192590963, -0.0416526848595496]', 17.2); -insert into credit_card_transaction (time, features, amount) values (157881, '[1.82456579954111, 0.285269548500017, 0.721219666472839, 3.84627996628275, -0.407771752722293, 0.654994177842359, -0.747951656119178, 0.213241618586786, -0.30370546555363, 1.28570448264253, -0.838475557612555, 0.638621441149359, 1.418532399009, -0.669545064432435, -0.51392676989271, 1.31036460244074, -0.98117578004632, -0.185822807704918, -1.89856788105034, -0.171442513117518, 0.0761419676572011, 0.33092497993392, 0.394075743354188, 1.12578339663129, -0.496763384046174, -0.22215459320539, 0.0403964704519625, -0.0065449801991931]', 5.41); -insert into credit_card_transaction (time, features, amount) values (157882, '[1.23183702604858, -2.3078022901259, -1.46566047318755, -0.120914649468717, -1.04590363843117, -0.126741700326513, -0.040480625007596, -0.260674376550962, -0.274983403741572, 0.604619216280449, -1.2727916342833, 0.160966559348715, 0.983578199102177, -0.128526538470212, 0.244778249089618, -1.19130775237141, -0.298535638461135, 1.13434557497372, -0.872896188152936, 0.456180095676669, -0.105465685527946, -0.793743990144628, -0.123276601661981, 0.505905936216097, -0.502236456307837, 0.469469837392391, -0.12403113641271, 0.039003616767987]', 495.0); -insert into credit_card_transaction (time, features, amount) values (157882, '[-1.2074073866793, -0.693632629991395, 1.21953508532021, -1.92585716825867, 1.3050415283645, -0.87537314165601, 0.342976430480777, -0.170424620383533, -1.70606109434515, 0.246901365806081, 0.615140335756935, -0.134258103399695, -0.177955097810702, 0.175511548311642, -0.645184135638645, -1.1368849200887, -0.77757928605749, 1.75489480925424, -1.26297698678264, -0.13944922453755, -0.0560940438463554, 0.0373952142745269, -0.302662454293229, 0.779572627772124, 0.800720336393893, 0.750291881855443, -0.267820190775824, -0.175181399637481]', 32.0); -insert into credit_card_transaction (time, features, amount) values (157882, '[0.119800421480171, 0.788073645063828, 0.365200372933441, -0.387607948010135, 0.452526275847308, -1.03502750517791, 1.1210342297086, -0.278813741248679, -0.264081156877578, -0.612390949116546, -0.880933733434474, 0.352244037536818, 0.428150073716353, 0.0775234136321686, -0.472085098476475, -0.114799458206887, -0.450837275804333, -0.74537237603181, -0.118907046814831, -0.126732439265967, -0.189770144541781, -0.493129438473522, 0.0888197297521361, 0.0419827537903228, -0.494250829041994, -0.0631196228278945, 0.0146975914765788, 0.040745871605246]', 19.75); -insert into credit_card_transaction (time, features, amount) values (157882, '[2.04325553353614, -0.0709706101781754, -1.16661667802807, 0.220060735880992, 0.115631417930917, -0.694287759068737, 0.108691200062379, -0.196149674300795, 0.22692562752008, 0.227948625227471, 0.758284198709351, 1.29182788348945, 0.543025968713628, 0.351670313659763, -0.692851457223477, 0.160541914302167, -0.684034033449312, -0.332389352607154, 0.552835415865509, -0.17146814839193, -0.253047744884938, -0.603627446511822, 0.282616273178655, -0.32211341504361, -0.268476375071983, 0.196645061609387, -0.0715553071700417, -0.0723531804342788]', 1.29); -insert into credit_card_transaction (time, features, amount) values (157883, '[-1.15873971181859, 0.70325899919763, 1.54610220629851, -1.08340041232099, 1.20845991340509, 2.63648193395707, 0.28264858555381, 0.570527981334167, 0.399324870764302, -0.307130721692404, 0.900324061134677, 0.446975555786788, -0.391625613440374, -0.129585035298459, 1.24788507873968, -0.922136717336832, 0.119427491464606, -1.10374659599658, -0.451841929258245, 0.0144621585395087, -0.132966311302209, -0.0661382497524874, -0.280035365996672, -2.43289635816613, 0.0853859945829929, -0.291643109994768, -0.181032211023036, -0.120684777548576]', 23.42); -insert into credit_card_transaction (time, features, amount) values (157883, '[2.06725387544557, 0.0300951826532658, -1.90371091074055, 0.196124745688249, 0.627307449212471, -0.301370626182012, 0.0078489316468607, -0.0052266615751703, 0.408788982385648, -0.18081594107929, 0.538247473784603, 0.179468895652229, -0.867791635714255, -0.491579343032849, -0.3576225571492, 0.697836604644505, 0.0997321929053881, 0.46004852634077, 0.531699925499393, -0.190669164373386, -0.356044909614171, -0.997355464211032, 0.279391073758909, -0.0289500346935749, -0.254738841249825, 0.187474315901626, -0.0730797677539765, -0.0477001236971459]', 0.89); -insert into credit_card_transaction (time, features, amount) values (157883, '[-0.553637154246517, 1.21389938862376, -0.359671774201268, -0.820613714985574, 0.353400974743767, -0.59014161163548, 0.561825996181848, 0.387409362455909, -0.290824487729718, -0.167423003157977, 0.270549964694574, 0.9898573857443, 0.355775410991013, 0.470274803042924, -1.12093161117634, 0.333805786052442, -0.689613009746339, -0.110766666521385, 0.348006157600673, 0.0203625537091664, -0.226731201940427, -0.559406329794625, 0.0492251612222921, -0.494787794265399, -0.373623993288484, 0.156420833069395, 0.235836878624974, 0.0679559755008272]', 10.28); -insert into credit_card_transaction (time, features, amount) values (157883, '[2.19798276313271, -1.58615272836699, -1.1173872536323, -1.72439481773938, -1.05246030475932, -0.071600589496316, -1.21775824272381, 0.0079993281303919, -1.32949335558517, 1.72459878727408, 0.247030596991558, -0.528296458657413, -0.122653750525107, -0.167458001112183, -0.747549278610277, -0.197636255103138, 0.122837522672345, 0.595521156608868, 0.290476888892315, -0.334810510876988, -0.152303944037387, -0.112013772295834, 0.20649138723979, 0.313267500045442, -0.235181154980195, -0.234744920451181, -0.0056608967489571, -0.0484749320583119]', 60.0); -insert into credit_card_transaction (time, features, amount) values (157883, '[1.98589471424635, 0.903630293991162, -1.61326937640463, 3.49413030231042, 1.29863196619582, -0.347734717657882, 0.89673525355298, -0.336033345619095, -1.98468921250142, 1.73790385951012, 0.486091102613236, 0.77967383115114, 1.02681871009254, 0.702829814471268, -1.5178560305061, 0.709613555899111, -1.17010809272141, -0.153768877280432, -1.08406870959026, -0.217098222537903, 0.182073636741283, 0.555706480199687, -0.0666210603501569, -0.382129610727419, 0.432963752803149, 0.144288870372413, -0.082562071875591, -0.0791433501985024]', 2.73); -insert into credit_card_transaction (time, features, amount) values (157884, '[-0.817271394514991, -0.163029128651324, 1.24480415599954, -3.08176098544972, -1.17504789106182, 0.346712011175051, -1.68980352451094, -2.45047461701233, -2.22539903041487, 0.229526532325601, -0.03440632043014, -0.818319871117663, -0.583682311857783, -0.0239378390487275, -0.951436277240565, 0.545308693100736, -0.216297078845865, 1.2148932386441, -0.851938245102277, 0.185441497729212, -1.15044068178039, 1.04346059582974, -0.162060584547279, -0.380489077429246, -0.171248726852229, -0.154039406505358, 0.113180930810204, 0.141991689109871]', 34.6); -insert into credit_card_transaction (time, features, amount) values (157885, '[2.29474835971221, -1.26796842649129, -1.23807448235125, -1.63360450164355, -1.17992909166558, -1.14541413271088, -0.881508095050717, -0.259722463768442, -1.71942612040821, 1.88549170627129, 0.781681308914434, -0.656584797827918, -0.473477209427936, 0.24943691670009, -0.439981701637185, -0.415335812832912, 0.237622010055678, 0.609449646741765, -0.0766511117066568, -0.496330599236015, 0.116112987340357, 0.761466611628846, 0.0820151942167367, 0.0717760964135275, 0.0234135512209999, 0.0483479863054602, -0.0215447093937162, -0.0726288848855631]', 10.0); -insert into credit_card_transaction (time, features, amount) values (157885, '[2.06889405405631, 0.184193167469339, -1.65314657892988, 0.438584356464676, 0.391986155446804, -0.933348429393487, 0.207225083323461, -0.25987061052302, 0.442194254554936, -0.386790759955339, -0.425216772252428, 0.337957653286203, 0.342054015341905, -0.897214217170686, 0.16515985722717, 0.272427212342383, 0.494018001030447, -0.377702661281999, 0.0122031613563231, -0.141302067952325, -0.354733673740883, -0.901203222014449, 0.349407374885248, 0.646722881905736, -0.261674421643166, 0.164324568461553, -0.0605385943916286, -0.0288538580025564]', 1.29); -insert into credit_card_transaction (time, features, amount) values (157885, '[1.85600394494833, -1.09198857180893, -1.09452599576508, 0.536984316414389, -0.460546864408321, 0.257929760240599, -0.548791010118107, -0.0067318584342177, -0.136464831543382, 0.953864575021698, -2.00699492880703, -0.609613117944753, -0.204192272236451, 0.0363150765498185, 0.317903266841066, -1.06335257707425, -0.57955330004991, 1.69862339527506, -1.00779835134191, -0.356007437504851, -0.29101238164635, -0.599191844879728, 0.0851439804199295, -0.0533491535277418, -0.12722555891233, -0.67490374347964, 0.0296650758442623, -0.0061755116305968]', 156.0); -insert into credit_card_transaction (time, features, amount) values (157885, '[-0.320619269371897, 0.605209835079518, 1.27959785240153, -0.122606532184038, 0.196272125471117, -0.628688169009073, 0.591003640009898, -0.193100826403913, 0.55248086100423, -1.12153121083429, -0.734540102060566, -0.657912052841648, -0.623511178077178, -1.49391293570279, 0.788533961520794, 0.230325382547438, 0.444602184834493, 1.1159653865034, -0.0807412751598658, 0.0727742081825356, 0.246302955526387, 0.987062232491391, -0.335734973749354, -0.034227588355407, -0.0978577793765973, -0.100826259237219, 0.0166484845321075, -0.0392570362947684]', 26.77); -insert into credit_card_transaction (time, features, amount) values (157885, '[0.483280098868548, 0.795439601343825, -0.787744160317465, -0.77142686815956, 1.62362135468515, -0.273073210990403, 1.16077119070475, -0.331007229898111, 0.118464561062453, -0.751754380624121, -1.58918979013476, -0.576608871950142, 0.0711928396996683, -1.19970581592359, -0.230940190534974, 0.526751513073209, -0.127094580160387, 0.123352835631878, 0.172251335948822, -0.0480667848623967, -0.347461892671758, -0.766125074399781, 0.0415310529735597, -0.417390729964411, -0.972197386366985, 0.0290584659413162, -0.0633765164996542, -0.0805398822458552]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157886, '[0.312862549298874, -0.743958604005151, 0.559306442736998, -2.31491459505117, -0.690616264717074, 0.03095845816574, -0.282043849795607, 0.0666929473563158, -1.64248409393381, 0.817090839830718, -0.272797965580411, -0.137186894210367, -0.0438920043070187, -0.790076129259981, -3.17544443480289, -1.1693509999806, 0.765536567619508, -0.191493197410778, 0.716991959901502, -0.407079063325381, -0.407974167768931, -0.531850928873852, 0.0582023203039284, -0.42890224334183, -0.412079547241503, -0.390500422480475, 0.0907146866101243, 0.0278977358144258]', 27.25); -insert into credit_card_transaction (time, features, amount) values (157887, '[1.69354481695103, -0.93352272348415, 0.110547292142508, 1.30452360939845, -0.0342203356701667, 3.0311426200953, -1.54263452733846, 1.00249082852558, 1.98406402390909, -0.146762258712861, -0.165041245376622, 1.39042989753347, -0.38849658401662, -0.803075239996122, -1.6046422502356, -0.834430731671016, 0.372854156108188, -0.734465838337716, -0.472053814670556, -0.280424008213518, 0.0109601422966865, 0.547668653413227, 0.205219540403822, -0.951180525077399, -0.313632647362343, -0.56230188901431, 0.150110799094366, -0.038028802810816]', 35.3); -insert into credit_card_transaction (time, features, amount) values (157887, '[0.135027430350424, 0.920278625154535, -0.583663051473421, -0.753509924737852, 1.10726333133621, -0.278478465931337, 0.815269492379029, 0.107700739220223, -0.160075808549985, -0.642841346782861, 0.482734806645038, 0.0116770900703293, -0.779354441357915, -0.692178665658762, -0.822350430810221, 0.692778505013856, 0.0001973632364672, 0.518285317532906, 0.231213271296817, -0.0049790312859904, -0.32763875025139, -0.866721587512347, 0.0391735349368955, 0.069226084226781, -0.418672829244721, 0.124532788887214, 0.212747275554986, 0.0680562312063862]', 3.87); -insert into credit_card_transaction (time, features, amount) values (157887, '[2.10988271481442, -1.78093153732935, -0.953829775470035, -1.59271108628439, -1.42800109805144, -0.374947423416119, -1.23143406139603, -0.0345887024517971, -1.16956543890746, 1.72317244519138, 0.0772248273219857, -0.794689182879176, -0.612448533457307, -0.0988605027703316, -0.666138600432693, -0.107801727963083, 0.112094221016041, 0.745681782331502, 0.261066816593294, -0.310286815632649, -0.0987222147364173, -0.0278900838648617, 0.121329185559705, -0.537242905064787, -0.286710461923956, -0.173410082273102, -0.0061298239093359, -0.0489005622039551]', 100.37); -insert into credit_card_transaction (time, features, amount) values (157888, '[-2.08715181913104, 0.594585924108475, 2.19073193370848, 4.65141314809625, 0.722306275989519, 0.521332136187854, 0.54503775832058, -0.237098441290528, -1.11072352586371, 2.27297768082269, -0.950129942446287, -0.659912694556202, 0.230523623624335, -0.636668203937824, 0.481824828118569, -0.272821003876924, 0.138479472318522, -0.395195128691066, 1.72235797047574, -0.223231024062605, -0.73138037330872, -0.895055696367621, 0.658519224960902, -0.0144153578355398, 0.070155837783745, -0.0030616055276322, -0.594921655033415, -0.508382033286906]', 18.96); -insert into credit_card_transaction (time, features, amount) values (157889, '[-0.677666306601202, 0.110744746525366, -0.306879494512597, -1.06898574099887, -0.0303695995332362, -0.461027109485463, 0.174475281538574, 0.258792034495589, -1.44446230969727, 0.243078418546412, -0.0126966446653426, 0.329523841637215, 0.247774396740235, 0.638390390702429, -0.477942958571961, -1.62777822765838, -0.291827732396814, 2.16689203345562, -0.241512768047151, -0.643773536293986, 0.162818422764468, 0.946824362808555, 0.0014413512349498, -0.452470295312771, -0.404402450445984, -0.063531492107149, 0.0230944434218155, 0.103892980337779]', 51.34); -insert into credit_card_transaction (time, features, amount) values (157889, '[1.89832533749866, -1.50920037414178, -0.743811571585612, -0.840210417716038, -1.17375244960787, -0.282244172485379, -0.995042019649838, -0.0313071823039281, 0.214075191635019, 0.714255078858815, -1.05289002752096, -0.988559388526399, -0.267175182301721, -0.339013334273561, 0.723691653550387, 1.51366788459664, -0.0780876753099101, -0.743078088641473, 0.323372516792785, 0.274473491894428, 0.460710730993695, 0.976621736748005, 0.0231359798900434, 0.602953667107258, -0.23264225192727, -0.103203442124721, -0.0212740003387244, -0.0151065589080708]', 160.0); -insert into credit_card_transaction (time, features, amount) values (157889, '[1.95966876231186, -0.828504027471752, -1.39050658530932, -0.941804233909333, 1.44708931414929, 3.96280004868419, -1.50330977432456, 1.12702195176584, 1.45673537366681, -0.2061528865365, -0.0845074484335585, 0.511729493811233, 0.0672989827932338, -0.0909342624561307, 1.32603246917828, 0.356977723407008, -0.712068001582958, 0.0457410723398313, -0.330862191108304, -0.11531205683397, 0.0552452696231311, 0.233811887470577, 0.324486562816044, 0.7095618749032, -0.423206101977045, -0.0555100711134175, 0.0513990978232612, -0.0374459161865824]', 8.49); -insert into credit_card_transaction (time, features, amount) values (157889, '[0.124200454762395, 0.961385463800489, -1.22065370215572, -0.156712971783243, 0.335791329590982, -0.928452441102013, 0.534084240774119, 0.31189098323403, -0.275499079615578, -0.997715464436744, 0.633087562237307, 0.0028842216291599, -0.909259088274663, -0.263244998077908, 0.0821858523371013, 0.579309946941751, 0.350550903244017, 1.48130258403016, 0.141096397827299, -0.205660517976569, 0.361826442680131, 0.909013633507647, -0.0567278710658409, -0.443308024596524, -0.273943264791258, -0.147538431744579, -0.0889485518362817, -0.0574033679750877]', 42.81); -insert into credit_card_transaction (time, features, amount) values (157890, '[-0.381967377763217, 0.569619565849526, 0.689143181347447, -1.18691951640229, 1.28858030932289, -0.699361649484901, 1.23611353496332, -0.334581244735284, -0.0327251827347307, -0.695167516152613, -1.66777738795247, -0.603358539317978, -0.6407052516771, 0.0386840741073267, -0.481894171200271, 0.175568244102361, -0.849904449637641, -0.556947081263705, -0.264980756741651, -0.108607157814486, -0.306789395675268, -0.77077544629133, -0.201127985159892, -0.797093352843907, -0.187317767980845, 0.115491985589697, -0.126420214119023, -0.100664223940674]', 0.0); -insert into credit_card_transaction (time, features, amount) values (157890, '[-0.0617282834441294, 1.18210247746459, -1.29807569371835, -0.528633954866264, 1.0324392910159, -0.92275296454125, 1.13589380425663, 0.0577158771232668, -0.851292723437338, -0.506591687736834, -1.3471054926443, -0.339845877015665, -0.314175926086869, 1.06013648217101, 0.0884715904890232, -0.367590665016897, -0.168996827991677, -0.318279922833008, 0.321508232511393, -0.221378357510041, 0.27428672742906, 0.69213355377427, -0.0084564022039689, 0.469134436708823, -0.820371533316482, 0.477782169365201, 0.0372189912326145, 0.180105421031703]', 16.2); -insert into credit_card_transaction (time, features, amount) values (157891, '[-0.79761184988351, 0.0890264281673536, -0.297355996257082, -0.672519014708262, 2.26215957335878, -1.54555949606719, 1.02827726991579, -0.334731493287736, -0.742249673570023, -0.607282103333396, -1.08240579390628, 0.186773289705327, 0.465186993112988, 0.385069701442077, -0.772324410384925, -0.660851439777217, -0.256849610911999, -0.62242517190866, 0.0906999534808683, 0.162904944617692, 0.259202148843272, 0.584549138378743, -0.210682980573219, 0.768047874143922, 0.249427547046301, 0.737383729361696, 0.0008452648953466, 0.15554389046145]', 6.0); -insert into credit_card_transaction (time, features, amount) values (157891, '[-0.21529713964505, 0.655655366022243, 0.465820799990057, -0.645669022634821, 0.348884523446231, 0.0037917485997152, 0.177035958170428, 0.233975497918728, 0.299115785401724, -0.894793011162356, 0.788972426797644, -0.0669656099925482, -0.914533925519109, -1.23018903362898, -0.404244817601481, 0.950536395477052, 0.130238906166253, 1.35474175645286, -0.531856693329135, -0.167360701415443, 0.382150226981118, 1.12546067563067, -0.0525686284305769, 0.637486687098099, -1.09023955654171, 0.413035652651385, 0.086689462116785, 0.257176971635437]', 10.78); -insert into credit_card_transaction (time, features, amount) values (157891, '[2.20412820462168, -0.285749296036878, -2.55387738827129, -1.70072885662244, 0.490468153989234, -1.68100610858093, 0.668865942421141, -0.576324764876292, 1.23437045843367, -0.7480413924731, -1.13102117065232, 0.128575266774618, -0.435326457508107, 0.882100136919085, 1.10931593149754, -0.959382367993489, -0.27389628937389, -0.228101887266599, 1.04494510040716, -0.215852085745831, 0.0671675009353499, 0.374811742063742, -0.121130958918484, -0.722964058804574, 0.513003162531862, -0.0256384117699995, -0.0606470169656779, -0.0841856587340256]', 13.72); -insert into credit_card_transaction (time, features, amount) values (157891, '[0.000747765737877, 1.11258043473596, -0.472999174504701, -0.835378697263397, 1.25833100037577, -0.263414792300138, 1.1267300955721, -0.188293900419061, -0.0369267104743596, -0.167414796216749, 0.906065799959952, 0.68199836534875, 0.542786247626516, -1.23783323290705, -0.932426104829955, 0.502215137468959, -0.159845637322139, 0.279609766389852, 0.162726749666034, 0.276108812109608, -0.389427142446033, -0.734536016790253, 0.0052900648809089, 0.189303903840698, -0.359045659764754, 0.0909492289920093, 0.168152356267895, -0.0936801181472963]', 10.11); -insert into credit_card_transaction (time, features, amount) values (157894, '[-0.0909708413648566, 0.767258537189037, 0.23445132084025, -0.492644222263285, 0.807029961359451, -0.500788323759771, 1.20594889939791, -0.260792231891838, -0.424607203763469, -0.601780033042193, -1.49364096026904, 0.152425183572876, 0.844011032816837, 0.050818922799333, -0.162537601658165, -0.138165159657597, -0.519663623391699, -0.465912722540509, 0.791060542804409, 0.0733000171961986, -0.188137902727651, -0.497838683792118, 0.0276260829840275, -0.693375002885843, -0.643201013833703, 0.22434123740446, 0.119941654930354, 0.183733065973594]', 43.7); -insert into credit_card_transaction (time, features, amount) values (157894, '[-0.980127534041516, 0.334524767225136, -0.775471440271509, -4.05868614407756, 0.493698867524761, 0.223560637089089, 0.446767008689881, 0.33266987755895, -0.195251080158663, -1.29107894209803, -0.403931849182272, 0.558896564335421, 0.265450401515436, 0.648017632065046, 1.43684116275618, -3.73657399858987, 1.14293309060415, -0.0555478780289331, -0.814627514192272, -0.791197286683024, -0.0205511900092023, 0.462587010669406, -0.182166015557391, -0.340585942815003, 0.246240469169606, -0.665176279740618, -0.30475790021127, 0.0504671763727687]', 30.0); -insert into credit_card_transaction (time, features, amount) values (157894, '[-2.03204091182433, -1.06488792677621, 1.02900746725203, -0.707950691745042, 0.921131059237985, -0.77234864813297, -0.867647702078217, 0.843596594834265, 0.0949623344275737, -1.04288654525445, 0.482036228689107, 0.304144667496677, -1.19286413491159, 0.795855206935447, 0.167435868142797, 0.674906847650112, -0.621758240840736, 0.668349841791895, 0.0176207113035838, 0.267229856490416, 0.15267108561428, -0.441585457934236, 0.0531446505084496, 0.655022346858257, -0.447528111827238, -0.338537270276676, 0.0057926074152947, -0.189421873949658]', 23.85); -insert into credit_card_transaction (time, features, amount) values (157895, '[0.874137749654705, -2.2585948557799, -1.53758419552037, 0.305294548961614, 0.0392540004228224, 1.98373419044859, -0.0733113384410723, 0.474959724258854, 0.869009997415201, -0.267781267194504, 0.714247155242689, 0.992399281590358, -0.34522000815664, 0.300383581950972, 0.103198348605188, -0.287871898232923, 0.101774560729862, -1.2766824339752, -0.414501438393064, 0.804052177639246, -0.0357181775517071, -1.1187224497687, 0.0451053007809415, -0.950751522504831, -0.970777039077199, 0.171680070039731, -0.105172879023415, 0.0233110152140974]', 534.34); -insert into credit_card_transaction (time, features, amount) values (157895, '[-2.95145750903908, -8.73573413946963, -3.19142730477141, 2.28958951295271, -3.19028213455878, 0.942239616805806, 2.6483306329096, -0.456285154587222, 1.37406078363675, -1.37141284801514, 0.0219770585922259, 1.00977234527812, -0.572858438392427, 0.479282493500472, -1.07714292909117, 0.243019395645019, -0.233661718597804, 0.518359489946215, 0.179549377710051, 4.89736148889273, 1.16752516858805, -2.13662574484399, -1.89536603613023, -0.316139015785521, -1.35926095720466, -0.578141115222792, -0.469111571143466, 0.387144266192967]', 2547.47); -insert into credit_card_transaction (time, features, amount) values (157895, '[1.99524471543149, 0.0478028354206297, -1.78389631026649, 0.566291262184279, 0.390627709715454, -0.439593497864376, -0.0972031322100111, -0.008939082182975, 0.580598520383246, -0.510669564244049, 1.14367161541455, 0.672875123793974, -0.448265216525295, -1.47141885745689, -1.01457568657872, 0.279720143058648, 1.04356686596404, 0.632343443819284, 0.0998898966523721, -0.169950398648955, 0.0167127569916756, 0.298321317672987, 0.0764676321552158, 0.629316448748177, 0.0552932153004491, 0.589562939923034, -0.0468315097484694, -0.0346069473780067]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157895, '[-0.381916014389752, 0.904582120168873, -0.141546969460458, -0.537496749583165, 0.763007312860442, -0.529913958651372, 0.860120857325146, -0.206775159620225, -0.1701873695429, 0.277578285045535, 0.612721978771451, 1.05399594426673, 0.644246431463654, 0.155585390697352, -0.919692041278245, -0.154930793040093, -0.638860823210908, -0.242201227004461, 0.762955401945503, -0.0537200116866628, -0.0841940078416719, -0.0924552780241062, 0.141017451594184, -0.368833443433274, -1.44413410105477, 0.0414779176896924, 0.0890699726447463, 0.32658336770486]', 17.99); -insert into credit_card_transaction (time, features, amount) values (157896, '[2.15499611722595, -1.6336642382552, -0.911913532218405, -1.86491212066969, -0.688111109642097, 1.20093794276144, -1.61756801083601, 0.406422249064719, -1.2056725611387, 1.60232254488955, 0.684554724030332, -0.218634802186758, 0.0930094051838177, -0.236352664284653, 0.0739279098975766, -0.918477765891507, 0.808858365675431, -0.594233105021545, -0.757435930028644, -0.52720565298939, -0.0578634466504834, 0.430217390450558, 0.259312026867836, -1.66060489541335, -0.45468499426435, -0.0627993097062929, 0.0699963425232515, -0.0727435156063523]', 13.7); -insert into credit_card_transaction (time, features, amount) values (157896, '[2.30676850320387, -1.30544402277144, -0.884869842725682, -1.61545749090099, -1.07619691380622, -0.410873067101839, -1.14073858781718, -0.206782284230105, -1.26625373362318, 1.52023902956032, -1.0214862603368, -0.262823041307623, 1.64365810654171, -0.753288061143543, -0.194312068498528, -0.470152690442343, 0.307750699937535, -0.0900594583797713, -0.106598512380145, -0.327445943540135, -0.163568247276504, 0.0775823326844607, 0.249953596209345, 0.586745946113069, -0.168345671495382, -0.205431612936236, 0.0232755453153838, -0.0387018291035679]', 17.0); -insert into credit_card_transaction (time, features, amount) values (157896, '[0.599062585536189, -2.87642397545265, -0.938185941587078, 1.26624325159145, -1.61356731465813, 0.291096359269465, 0.0068046430870135, 0.0729261293467636, 1.82107574441951, -0.443454710302831, 0.0752076867270332, 0.785705698936285, -1.45568139258644, -0.0039056074544981, -1.60529947612682, -0.454145535411903, 0.021332959933459, 0.622705206907382, 0.186118015368104, 1.02421562322345, 0.689605472870998, 0.896439257457367, -0.619434577662689, 0.097221582502764, -0.106915488698315, -0.0585614518598048, -0.0843976412828654, 0.0581543793712038]', 680.3); -insert into credit_card_transaction (time, features, amount) values (157896, '[-0.537065414805345, -0.436391405163059, 1.97920180154175, -2.2681625856484, -0.488086801026272, -0.0243374073113559, -0.531373467429205, 0.277016609949402, -0.653601613245138, -0.146999956905202, 0.0992599209231778, 0.577345420634845, 1.02564549211825, -0.632632207113674, -0.819813950865385, 0.100690388830211, -1.5079140583366, 2.28593289352485, -2.21626737288044, -0.500515475485959, 0.0242742189580927, 0.458293092387654, -0.0014609892151069, -0.332477668001832, -0.831409923505809, 0.34799265915513, 0.152945955806711, 0.183869935178162]', 21.2); -insert into credit_card_transaction (time, features, amount) values (157897, '[0.084622911456161, 0.0497336642116673, 0.235022065158614, -2.5743832009014, 0.689250369714968, -0.873735137381891, 0.835462806417917, -0.355359498272619, 1.27080607314137, -1.39946764777834, -1.05853907204533, 0.0652953424594523, -0.287463591564612, -0.0590608656504366, 0.599634976273762, -0.721137529430174, -0.46728648182462, 0.050837576778913, 0.771678661662824, -0.0044508951762856, 0.0098029393964264, 0.290247620543975, -0.185970191790329, 0.500470672471646, -0.049905916607372, -0.328566826245707, -0.108169680621951, -0.169769219289147]', 10.47); -insert into credit_card_transaction (time, features, amount) values (157898, '[0.249983446354362, -3.28997149534248, -1.89985683045391, 0.567734891641382, -0.279382544403865, 2.0999999918999, 0.35540964245177, 0.39110305748287, 0.830955648141821, -0.41826027930015, 0.718875969618624, 1.00570653336605, -0.287619166968485, 0.373527606533198, 0.143841636808564, -0.245259410606551, 0.111352944520433, -1.21048745540841, -0.517690036618029, 1.46199176271398, 0.1600459586992, -1.28924021775814, -0.239657250149244, -0.934173487302693, -1.08940409209579, 0.137222849088636, -0.166217859717328, 0.0795649732777415]', 857.42); -insert into credit_card_transaction (time, features, amount) values (157899, '[-8.01482331115438, 7.06255482350825, -6.60054410151113, -1.56961768644062, -1.96823317337275, -1.30580242265623, -1.91254738585737, 3.55887351724071, 1.54153780042878, 3.51910523550793, -0.310078945845208, 1.70228017627906, 0.122048900593556, 0.812923974849694, -1.30596206148944, 0.60784968333206, 1.64837377776102, 0.513783260919317, -0.348658187630747, 1.14407788174426, 0.186234207062, 0.106917799127988, 0.390380028899803, 0.112047885592719, 0.84931575223108, 0.566270499626512, -0.263478408468529, 0.747256758963994]', 2.55); -insert into credit_card_transaction (time, features, amount) values (157900, '[0.0737887856018367, 0.795153712567147, -0.110337248221287, -0.941471202551368, 0.96976346592985, -0.216539312867019, 0.890923219723065, 0.0006700998799452, -0.245552313057108, -0.242328691330827, -0.126860567482349, 0.530713441320792, 0.180656812324312, 0.232442820942043, -1.03763957801116, 0.396802218280224, -1.03432418851456, 0.0699724508962404, 0.589487716098665, 0.0092937964706779, -0.275256012098953, -0.640359765422046, -0.0708344479374029, -1.04178597261983, -0.380898915949113, 0.183812881804712, 0.242684774697795, 0.0770338395992733]', 2.67); -insert into credit_card_transaction (time, features, amount) values (157900, '[0.835191573593701, -2.8578949808554, -2.26582845379784, 0.0084519614756108, -0.993843041083543, -0.537559899793885, 0.697331722824314, -0.39486071271835, -0.823185773502289, 0.768634832349307, 0.245595317638252, 0.256056311382268, -0.366730736338625, 0.70651263164887, -0.710182494158098, -1.33680321462496, -0.285545667357253, 1.33849758707585, -0.371243297505876, 0.762247863441567, -0.0889472786487298, -1.28680630021755, -0.358427737986008, -0.401662520776188, -0.474425709385888, 0.413932352749525, -0.208511736774225, 0.0404490489521142]', 699.0); -insert into credit_card_transaction (time, features, amount) values (157900, '[2.18673115914591, -0.65137035084956, -1.21936289949389, -0.426831404124117, -0.687905141355369, -1.23040952136611, -0.342454819867699, -0.330182618372767, -0.475585490190968, 0.994912922190698, -1.00765374006895, -0.562818152374183, -0.458949771571066, 0.410604467131052, 0.646075357328223, -1.45258338028467, -0.128593402446772, 1.1075089576064, -1.0809696921502, -0.673528987164475, -0.142707317397195, 0.157637210506489, 0.148560404935555, -0.0023299875079604, -0.110416645359042, 0.801492577077862, -0.0624217380014489, -0.0670655990384319]', 2.99); -insert into credit_card_transaction (time, features, amount) values (157900, '[-0.493903185082797, 1.48024304290096, -0.460867342096709, 0.817704257181372, 0.786579133296784, -0.346017270911799, 1.02607370130255, 0.286036551507853, -1.104905623776, -0.0721878333927018, 0.209835127771765, 0.753678252825354, -0.0087216633462644, 0.94060922218128, -1.05818950355916, -0.808935770108734, -0.0203992186404635, 0.251467925973858, 1.15799961647567, 0.0062237131161779, 0.195696889100679, 0.725050858504305, -0.262785766225978, -0.374240225624988, 0.0764665506635068, -0.370815342321736, 0.307725945972628, 0.168930825376137]', 22.4); -insert into credit_card_transaction (time, features, amount) values (157900, '[-0.381217565562118, 0.583593116883996, -0.6116031647165, 0.392167901063612, 0.308642390743848, -1.21689699370856, 0.312991288622845, 0.288781213860821, 0.102971114997442, -1.15577174030823, -1.23470889581905, -0.478156602148045, -1.099423691853, -0.755898134039938, -0.622237070212195, -0.0482957761582344, 1.13419890349787, 0.388192378611406, 0.144331105123874, -0.131533414007584, 0.19261780510878, 0.486821369368834, -0.0275773925489235, -0.0180121172454527, -0.517637181374241, 0.400478218276118, -0.0177141513596138, 0.0010334262797165]', 29.89); -insert into credit_card_transaction (time, features, amount) values (157900, '[-1.91755261697316, 1.33017455482758, 0.042396986871526, -0.419234186100371, -0.758114714975666, -0.179526096022429, -0.709981115280485, 1.32279944762951, -0.07330803555802, -0.93892900978983, -1.3089400501036, 0.775350568166637, 0.822592297930393, 0.473230609007015, 0.146304286898183, 0.723312319860541, -0.146715433712617, -0.231926829091941, -0.327051394185408, -0.294985291265425, -0.049569753753946, -0.542340134411873, 0.236195705569596, 0.661619992444514, -0.173667857384025, -0.0404071249013867, -0.522678304330722, -0.125644985718057]', 10.0); -insert into credit_card_transaction (time, features, amount) values (157901, '[-0.658512660952247, 1.04334176746059, -0.0166830967394197, -0.842387962417706, 0.725381920476646, -0.639462994618298, 0.867608236650307, 0.0736767438617071, 0.0062162473671651, -0.384489774063838, -1.75702069831662, -0.43537894268419, -0.505452948334033, 0.316215343476969, -0.231962922119078, 0.0669014760318342, -0.511063706778201, -0.466199103133965, 0.245638923575681, -0.107831147607011, -0.281945719889646, -0.625309249130629, 0.0465811149370318, -0.796971367459351, -0.530516218757201, 0.152770937066802, -0.0584772396019007, -0.0716419957741303]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157901, '[2.0349323910287, -0.712674693723369, -0.979103212262256, -0.382544655899642, -0.858342592361684, -1.26688783855819, -0.274602223694948, -0.330947970473472, -0.97784037632193, 1.11346689831595, 1.37137792364028, 0.998370993506269, 0.69396395814166, 0.380894093213844, -0.28323105315914, -1.41876712058075, -0.305269237011596, 1.35367295353032, -0.954066258753647, -0.506235517053859, -0.0197954186517223, 0.437240923389281, 0.147126281291046, 0.598042673594229, -0.170892489379524, 0.735138005900876, -0.0677417091212256, -0.0609969483276765]', 43.9); -insert into credit_card_transaction (time, features, amount) values (157901, '[-1.71619744078076, 2.19590069722008, -1.43133986110361, 0.826001188809166, 0.0809214640325466, -0.523320201620366, 0.251037184169182, 1.16411936715498, -1.01633330137333, 0.110172104493274, -0.0704250578982231, 0.99270405150433, -0.0812494106723119, 1.47442938168691, -1.07058596912208, -0.583757163705439, 0.309390186332102, 0.313037614177102, 1.09320727774172, -0.0195425979073825, 0.199890206005182, 0.629591421397521, -0.214343368362719, -0.380159132547274, 0.203338776521147, -0.356621893747678, 0.305434316400816, 0.118843965167719]', 21.82); -insert into credit_card_transaction (time, features, amount) values (157902, '[-0.785322122467692, 0.961483115517616, -1.92215447137287, -2.25379214859201, 3.63205140074275, 2.77544765865689, 1.06789336768814, 0.605739377249651, -0.454833872481111, -0.168550879214234, -0.0555833800674775, -0.16659713584695, -0.481114008226962, 0.804271379305383, 0.400025182901024, -0.77099718131868, -0.442948647755501, -0.531110459917082, -0.198971034096133, 0.140356002520428, 0.157532147291346, 0.547436017700413, -0.378912271650549, 0.755593623838874, 0.473436244817106, 0.228935463942859, 0.293699304408411, 0.27292853275079]', 13.79); -insert into credit_card_transaction (time, features, amount) values (157902, '[-0.649231350061541, 1.28898913178982, -1.13708877120126, -1.66612376719745, 1.60602367924697, -0.828609476026074, 2.1546782608748, -0.833475221302612, 0.893431366057737, 1.60440472319773, -0.071330939352789, -1.00320106825351, -2.13524526236887, 0.317781119890721, -0.441229674090099, -0.40261306843108, -1.26667299149117, 0.525064075793738, 0.445182647564266, 0.525663353383508, -0.0848057714050158, 0.69446935503082, -0.422523743328681, -1.04620806039527, -0.131994015251356, 0.0736582098049211, 0.329804864260251, -0.172873221772078]', 30.05); -insert into credit_card_transaction (time, features, amount) values (157902, '[-1.33559506120005, 0.539863142113922, 0.601209660607156, -0.628999427060293, -0.557872953649539, -0.618379492703623, 1.55312653603153, 0.220532686903824, -0.579231812548526, -1.36822916768202, -1.33243072236119, -0.627569760882967, -1.35277731986473, 0.710444704928356, -0.352577602715176, -0.0259568811120971, 0.0297635357991977, -0.484393066721101, 0.174041202371641, 0.222026247676947, -0.118827557633524, -0.903552034161335, 0.258719943017483, 0.002270339249504, 0.60619085086954, 0.474990545994021, -0.266212284906561, -0.0111088856415367]', 229.41); -insert into credit_card_transaction (time, features, amount) values (157902, '[-0.117021325480892, 0.438512439697097, 0.33625718764148, -0.0538105876965149, 0.632122863666363, -0.757626441193409, 1.49883055414855, -0.604552453069684, -1.74778602208135, 0.551229707525331, -1.21502999923672, -0.260624234451585, 0.391720041016906, 0.0402246504199353, -0.82560137560621, -2.56786644657313, 0.102153392566023, 0.851032810724188, -0.591164816821375, -0.32466052812295, -0.228643010483369, 0.0674866065063492, -0.184743430515323, -0.0376716780976729, 0.126002627109249, -0.488867924247838, -0.0015505696851462, -0.0570840012001833]', 62.95); -insert into credit_card_transaction (time, features, amount) values (157903, '[-1.01895693569342, 0.573433181253949, 0.806061738436092, -0.90562051608275, 0.216796894077958, 0.643680805053632, -0.171086510897476, 0.80431242309621, -0.0131796943757115, -0.733141121111047, -0.178652511630448, 0.550619795933532, 0.128705660648942, 0.118426796199606, -0.65170628130358, 0.692855609208508, -0.802817538525621, 0.864414933655868, 0.111227628789411, 0.104702070849897, 0.295614104529386, 0.80424733658981, -0.239934782738573, 0.0931908163348545, 0.015715681517997, 0.623179386616816, 0.204840217414147, 0.094269198265361]', 34.3); -insert into credit_card_transaction (time, features, amount) values (157903, '[2.11250674460611, 0.124453365564863, -2.48815948601055, 0.320593939176355, 0.889049805139394, -1.13833176480141, 0.796966062689835, -0.381165478141393, -0.260768068822949, 0.469902937431072, 0.723915101344203, 0.182422991632372, -1.41394249440071, 1.25447120089002, -0.806249882919377, -0.543653217828135, -0.300349862713011, -0.0315710926320397, 0.298066252560275, -0.297376700865476, 0.300420853055377, 0.941334195588568, -0.138177245356098, 0.834716891972212, 0.629566386284558, 0.671163374349601, -0.139195997549872, -0.0986853729154215]', 0.0); -insert into credit_card_transaction (time, features, amount) values (157903, '[0.245458649760057, 1.06542020571345, -1.46650845140007, -0.252925553679658, 0.75862951975372, -0.753788439277694, 0.570667673876605, 0.20926954423767, -0.0495699752016178, -1.1314106169566, -1.59114110895577, -0.54887613648666, -0.07395135895906, -0.520545442976051, 0.802776870326066, 0.469823178668022, 0.278727117758228, 1.00434179940077, 0.0707913842822678, -0.208481502534964, 0.268542741878845, 0.753951158705625, -0.183038658877185, -1.14199807087522, -0.14920671987347, -0.0812299246007023, -0.0727396636679443, -0.0576412845557827]', 21.75); -insert into credit_card_transaction (time, features, amount) values (157903, '[-1.56117308741516, 1.64990103489131, -1.16256107048878, -0.803774238594438, 0.198197452056755, -0.409049821905381, -0.142759543233837, -0.24593674464463, -0.24879054174963, -0.19866395879008, 0.699638635500335, 1.30250140877807, 0.529999734258827, 0.877815546237471, -0.400597621683801, 0.151565009014956, -0.512720316843324, 0.469426157330296, -0.227981875872939, -0.734471750018317, 1.28374654881286, 0.845108478223971, 0.107712061009612, 0.73104144487092, 0.0595796084275727, -0.292639139864585, -0.973545660286161, -0.138012663241048]', 3.49); -insert into credit_card_transaction (time, features, amount) values (157904, '[-2.25703474764583, -2.452066486735, -0.952998791848426, 0.689593231867508, 4.56921498529072, 2.64676856927825, -0.895836003994044, 0.916504135325729, -0.517579058722481, 0.388894323189424, 0.100947883275083, -0.0553359506868724, 0.0875441404530024, 0.528294027463233, 1.88135595237381, -1.22045162364543, 0.550988509182496, -0.394821120746533, 2.96309373574462, 0.0825354145041859, -0.291520376442678, -0.321498871608976, 2.03403196225141, 0.700295746018922, -0.321293600937591, 0.68342797032638, 0.266453219757414, 0.101977896714882]', 4.47); -insert into credit_card_transaction (time, features, amount) values (157904, '[-0.980911170983152, 1.37121012118107, -0.559525112034686, -0.550990041471289, -0.0463310330961797, -1.16101399545253, 0.383224959502767, 0.613515412348663, -0.275316848960592, -0.778752087659786, -1.5606500434433, 0.201408672782287, -0.27826762746971, 0.794198461237844, -0.748719796481105, -0.0154493167152493, -0.0132394393918369, -0.573763458656846, 0.0869651585900584, -0.280637287993738, -0.0693480758469666, -0.305566138030473, 0.144366834523028, -0.107082592256806, -0.785703155543112, 0.153121773333652, 0.0139600775815906, 0.119783998280052]', 6.48); -insert into credit_card_transaction (time, features, amount) values (157905, '[-0.254038986112246, -0.150368410161423, -0.38415410346338, -0.930157156013426, -1.30222271559157, -0.645647368229031, 1.34086792948199, -0.494491463326635, -1.24404062286028, 0.8237262368369, 1.12030559072902, -0.962106496776634, -1.88481725306932, 0.360155215525693, -0.912561789425541, 0.115748489947065, 0.869571731892819, -1.13739692101667, 1.90406045091532, -0.283630185679304, 0.211310138416589, 0.764197801992011, -0.127018977972646, 0.580006029754394, 0.261898153975394, 0.0679359153045664, -0.333060788963968, -0.103230700439352]', 238.0); -insert into credit_card_transaction (time, features, amount) values (157905, '[1.97999336554606, -0.142044948535131, -0.703849781227801, 1.34345121368236, 0.158572533861169, 0.331878234956497, -0.199008369791474, 0.0060108194440058, 1.12184362928976, -0.0449915160102269, -2.05189365373729, 0.850441438260074, 0.801719391694577, -0.487676042620765, -1.1828602401452, -0.217452384437668, -0.419751095203964, -0.732192108229198, 0.526117340526063, -0.193106806878799, -0.571728070667003, -1.31492180434125, 0.296523228838472, -1.12473755996578, -0.169760500752762, -1.04098692168015, 0.0600951513983694, -0.0377968242276434]', 17.87); -insert into credit_card_transaction (time, features, amount) values (157905, '[-0.0516352638968041, 0.98050290589871, -2.27477364037747, -0.532868040044273, 0.949273408797316, -1.11834903705716, 1.56498170085685, 0.0839099515100263, -0.80827030136609, -0.0852607048162529, 0.214571835651573, 0.0448990005906746, -1.46489610801555, 1.51398107985028, -1.52859233736862, -0.449187891811337, -0.345523466333364, 0.222036585485296, -0.0027806810655068, -0.11884690761192, 0.591864478964928, 1.62604788111902, 0.204959343085669, 0.817311778977049, -1.16485461322391, 0.335357324996459, 0.334548097294036, 0.321496487977308]', 88.21); -insert into credit_card_transaction (time, features, amount) values (157905, '[-0.585138574634772, 0.554392797846965, -0.533852624863726, 0.152928746715669, 2.0517956790642, 4.57433519490335, -0.177844862220581, 1.56702391162216, -0.153262839347354, -0.742601713873033, -0.82778006764288, 0.417979090672179, -0.359725465815216, 0.258317361925088, -0.632132314125478, -0.824807511083985, 0.355036177820579, -0.626668377868553, 1.07352996770334, 0.0597885070590277, -0.325538016716953, -1.04380728227758, 0.423007943933086, 0.619722085246048, -0.723452126711582, -0.987658492063803, 0.131846603450899, 0.150504208891102]', 89.4); -insert into credit_card_transaction (time, features, amount) values (157906, '[0.0465931987457306, 0.885543809065956, 0.271404015853055, -0.614044460656422, 0.500334810654438, -0.995489108580857, 1.00960491918688, -0.192576617686994, -0.0825707902631356, -0.425735144346444, -0.891728643704836, 0.282676887161694, 0.296401226597962, 0.0579836432229254, -0.38158442492019, -0.144746526559487, -0.393608818194222, -0.849543088109048, -0.130594302914531, -0.0307394276951737, -0.257699801885398, -0.537556222389651, 0.0583491706256812, -0.0827868174337551, -0.486584202937646, 0.146924064540632, 0.252989399340288, 0.096507833349973]', 0.89); -insert into credit_card_transaction (time, features, amount) values (157906, '[2.01390375331608, 0.0827776541425267, -2.10430779002471, 0.39780737967145, 0.559252419012978, -0.999448147451114, 0.328952259605552, -0.350386143413494, 0.589149768178417, -0.550796847357519, -0.89925134354605, -0.033535800935122, 0.413198410553575, -0.918931053995973, 0.985744562636534, 0.391661587847706, 0.241392602529502, 0.678598975780997, -0.249491068783377, -0.0745737561188518, 0.176491501605903, 0.609064519323158, -0.152753553596954, -0.837791091597327, 0.33284171041776, -0.0568820407150537, -0.0056292950502836, -0.0286165182927772]', 48.75); -insert into credit_card_transaction (time, features, amount) values (157906, '[1.13797666981808, -1.69344624399708, -1.09067182058295, 1.35595681014061, -0.55215539585825, 0.60490969933164, -0.0994259144511083, 0.190002739783328, 0.969441322934145, 0.175525796279448, -0.460429269359792, -0.22031243001196, -1.62805353933732, 0.584155864826226, 0.120235445140114, 0.970238933912401, -1.13066305708445, 0.941754580081028, 0.0448603287374758, 0.540912032776538, 0.0561830879830368, -0.801958021126795, -0.129766475313135, -1.26068484036493, -0.497367357776644, -0.926388566398691, -0.0377187998129315, 0.0252369570474452]', 438.0); -insert into credit_card_transaction (time, features, amount) values (157907, '[0.0247705606032034, 1.09097958001963, -0.528967932008397, -0.605520807628633, 1.02890270141006, -0.707369624669997, 0.989771564310705, -0.152346114348203, -0.0086363886519808, -0.733513882828902, -0.823778851166164, -0.0354061215341754, 0.337785215169639, -1.12423299976171, -0.24647426636738, 0.369449482882631, 0.264252339235132, -0.188641832553441, -0.145504473084704, 0.0256222258437457, -0.336562644950979, -0.848612460962225, 0.0955877022829466, 0.376690305251935, -0.388507719895016, 0.112511254005237, 0.0916862327139131, 0.077890608279672]', 5.49); -insert into credit_card_transaction (time, features, amount) values (157908, '[-2.42765447777068, 2.30887834156243, -1.29472055152809, -0.49192177545785, 0.34129639487533, -0.42506860103783, 0.0609060051655076, 1.09704104437298, -1.05140079101845, -1.63900965993603, -1.32666148942587, 0.663720001185731, 1.88986714769002, -0.258809432019079, 0.780034642769215, 0.520700225331663, 0.734846299552925, 0.893135989976126, 0.366015593703541, -0.311140729671428, 0.328644142901115, 0.531112322474409, -0.661398635144403, 0.0312696916656398, 1.15118947030638, 0.035724955713893, -1.11011498388287, -0.473302418468432]', 25.0); -insert into credit_card_transaction (time, features, amount) values (157908, '[0.0926357201473769, 1.24502659579819, -1.32996795922569, 0.0162000757520552, 0.881710593584294, -0.243087876272779, -0.426771099182833, -2.76779067460179, -0.166681792207206, -2.24643613704431, -0.578056093020906, -0.148209488146708, -0.581185345290101, -2.19342043502059, -0.662685601756719, 0.586875430226292, 2.04227132520997, 0.663702830144735, -0.780632966414863, 0.586372262257694, -1.27882194169557, 0.536998872601288, -0.264142204116178, 0.456993611287235, 0.893745113546679, 0.731997964039419, 0.0860093874833085, 0.324464391838056]', 12.31); -insert into credit_card_transaction (time, features, amount) values (157908, '[1.99324833203318, -0.83319912010525, -2.68769780748939, -0.369608362338447, 0.186569506050947, -1.48068293354212, 0.748629385505938, -0.679114881138996, -1.10250175989748, 0.975818606981075, -1.36787389593569, -0.483666560715026, -0.19495642539827, 0.764836450181156, -0.261422163946881, -2.19995350949636, 0.125469277514611, 0.70480493868789, -0.631609819621673, -0.358546973689111, -0.0398415642938354, 0.198095705248245, -0.258970463341371, -0.345437776889043, 0.478851486383427, 1.0332507476481, -0.148630033752764, -0.0718456343220761]', 154.98); -insert into credit_card_transaction (time, features, amount) values (157908, '[-0.25080783252098, 1.07246180826257, -0.873690545826931, -0.151194103426197, 0.273120150895431, -1.05780137900395, 0.558517846599771, 0.256869034454488, -0.34560288207957, -0.897386537832912, 1.03803808108836, 0.253692091136194, -0.7765158281827, -0.188952254036643, 0.0753340571846981, 0.313864801674154, 0.46639741027085, 1.19456704633898, 0.0093102442504786, -0.307477743381429, 0.407393820533666, 1.10717297727466, -0.0195888452209443, -0.0676259598157408, -0.408615198007465, -0.17906945006243, -0.118683052997159, 0.0079366148534008]', 29.18); -insert into credit_card_transaction (time, features, amount) values (157909, '[-0.0947391909592723, 0.375172534723615, 1.24680005456955, -0.195607113359925, -0.153787639501474, -0.457432176308868, 0.179266175082623, 0.0340459979987299, 0.701563939674269, -0.720415346832911, -1.32736972550344, -0.111173961760158, -0.304984083930414, -0.163316268766993, 0.29430112621322, -0.1181198013219, -0.433636407590132, 0.494517554519687, 0.140064425456671, -0.109058163407614, 0.331100771425887, 1.14184928527388, -0.0870346754838411, -0.0032903403959216, -0.830756209934015, -0.269584981811816, 0.270869434257416, 0.238445158218471]', 9.99); -insert into credit_card_transaction (time, features, amount) values (157909, '[2.13594297883431, -0.0004015969276476, -1.47783967272336, 0.161963278578655, 0.458716579522584, -0.593329307546439, 0.23590393813479, -0.329735834085398, 0.44950568363661, 0.0430689063464959, -1.4869529095715, 0.668967887294012, 1.32425266224343, -0.0014529232428345, -0.002248691477363, 0.147395166233377, -0.727551244947571, -0.662741491954791, 0.530555422274653, -0.12127426577678, -0.345102006055858, -0.802317115185071, 0.198618879646868, -0.974142969559776, -0.123251323607733, 0.256761877496172, -0.0650824806319844, -0.0681305970956919]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157909, '[1.99469208315303, 0.336003820218472, -1.54330430092413, 1.27080614832155, 0.313781509756749, -1.51172076884198, 0.70880536285969, -0.407782017595857, -0.398269940354268, 0.555721220112759, 1.38814040080625, 0.859398105678084, -0.640914719390795, 1.10846021273329, -0.524689089065201, -0.366261164020548, -0.464614005399254, -0.0712609541476403, -0.30372901102756, -0.323066353087508, 0.203998944889394, 0.658310826604845, 0.05093690518782, 0.539239907299545, 0.358090224890124, -0.537288169666052, -0.0366296700876039, -0.0691747883797682]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157910, '[1.77247027069035, -0.439409688459886, -1.84459850519985, 0.352019683927497, 0.100150031056696, -0.500590546853668, -0.010740575037245, 0.0356881143434952, 0.969075825741137, -0.687168719048782, 1.01167659471481, 0.183333884318202, -1.71845411001624, -0.930393156517682, -0.562986990470135, 0.219635324291018, 0.962479424289317, 0.652316535065338, 0.319939712853861, -0.0344384266060296, -0.146370970177332, -0.53718995005491, 0.145167736881368, 0.551771519521099, -0.184263721389302, -0.144994843560502, -0.0420902455317882, -0.0095115280963436]', 115.36); -insert into credit_card_transaction (time, features, amount) values (157910, '[-0.657531455719813, 1.39973864909325, -0.425651200869176, -0.287011476856892, 0.529657440979324, -1.09706836262121, 0.690547761082501, 0.254158968786737, -0.134009358843976, -1.48376798697574, -1.01556634581355, 0.0528000428356162, 0.205399860468476, -1.58427434761282, -0.940263713599507, 0.207665179725233, 1.24256466406546, 0.372761739266948, -0.20294651667422, -0.0390709726029234, 0.0645482040580051, 0.428463629146299, -0.265972285428651, -0.169294895830524, -0.129878069924786, 0.588831963203196, 0.258116027570852, 0.192858204681211]', 4.74); -insert into credit_card_transaction (time, features, amount) values (157912, '[0.211131284422336, 0.286675685766003, 0.0627090090937991, -1.88897655137908, 0.0633350820659715, -1.15404286427866, 0.604951089749858, -0.425154905151124, -1.32637468946505, 0.266804134201603, -0.653672270888109, -0.395185926813384, 1.18042111203098, -0.339730459160403, -0.17790111927084, 0.804348776440014, -0.0054832817301665, -1.37502408904382, 0.178865706371488, 0.0334164029520285, 0.532915014563483, 1.52217277363081, -0.28529728601461, 0.0014425489403848, -0.0286294926824956, -0.014257600977176, -0.0836128641165237, 0.0243603678246047]', 15.0); -insert into credit_card_transaction (time, features, amount) values (157912, '[0.0197874103213681, 1.30621737962263, -0.81197185216138, -0.0874597716901431, 0.458784793550026, -1.33311873394097, 0.67514398179196, 0.0827573678323825, -0.376122901940923, -1.20335807844291, -0.488359432384472, 0.354392365742054, 0.830973026365255, -0.653366328511352, 0.597686388817002, 0.0684912877349065, 0.613308869388673, 0.540309298210897, -0.266879867386791, -0.198053942608, 0.357228200169644, 1.09518069874693, -0.152568891454972, -0.0550575896138856, -0.330932413592807, -0.152717490463572, 0.0083527485961637, 0.0395816766884335]', 1.5); -insert into credit_card_transaction (time, features, amount) values (157913, '[1.91066126162459, -0.211159238566408, -0.528439855371583, 0.979040826479544, -0.0110939115680447, 0.465083511553869, -0.535637622860092, 0.203841985114149, 0.582293313531761, 0.344121502099147, 0.393468961284806, 0.880351764181356, 0.275166470433681, 0.182067909767296, 0.140468161598655, 0.898058819091774, -1.25602942439591, 0.675330411934491, -0.0855681488377849, -0.133652281124354, -0.0903288336337876, -0.292904086229648, 0.297358275889729, 0.122598194707521, -0.336875554665426, -0.948067664208927, 0.0432490617214345, -0.0272122038307616]', 31.0); -insert into credit_card_transaction (time, features, amount) values (157913, '[1.79225832698467, -0.0849760704575839, -1.95970148529606, 1.36185163991992, 0.431960880304172, -1.37463637986497, 0.983158255406124, -0.53694791270602, -0.136749052862529, 0.309013907912058, -0.741518976703376, 0.0752642666322282, -0.314208931214831, 0.89186980199522, 0.269010953586832, -0.443688593783608, -0.365164040989799, -0.457252889660962, -0.499139910365335, -0.0231352174738422, 0.209158832699302, 0.40013374941257, -0.127093396910719, -0.0120829018603704, 0.399993131958951, -0.49539645335707, -0.0566006465537482, -0.0401141192067391]', 144.0); -insert into credit_card_transaction (time, features, amount) values (157913, '[0.94216456027253, -1.79992339818104, -2.40273944625159, 0.740017248261139, -0.33933215380822, -0.538472437740158, 0.643437851418059, -0.160503872502217, 0.92095826997913, -0.948998183305172, 0.735444899300075, 0.189370656023334, -1.38094644573399, -1.0294960514447, -0.529687943281462, 0.41040836774365, 0.945202783414781, 0.881937170295514, 0.304679432272243, 0.861499829155589, 0.0923205937190821, -0.794328805016838, -0.335409139091891, -0.601652322434349, -0.300420312178591, -0.131953148870835, -0.117550815061413, 0.0592940295343889]', 554.8); -insert into credit_card_transaction (time, features, amount) values (157914, '[1.33955399554668, -1.57009902692414, -0.736502129989807, 0.58064038521, -1.17958785297662, -0.56575375497292, -0.204163927508693, -0.114901819941184, 1.18538447595711, -0.0790128327249399, -0.972340417482769, -0.265959559841319, -0.725192191260264, 0.19225159442834, 1.07735270662446, 0.58411020319591, -0.543699684376732, 0.18057838709201, -0.527540956582624, 0.452119040508396, 0.376768473567353, 0.406788253940842, -0.101811522002397, -0.0395474071137182, -0.516522562974818, 0.625650187892035, -0.104042929177585, 0.0083551164989929]', 352.32); -insert into credit_card_transaction (time, features, amount) values (157914, '[-0.297960415038452, 1.72596629591149, -0.586200685572207, 3.19595486162759, 1.04206429765504, -0.688006075746141, 1.12231290877593, 0.14132723035833, -1.97230618978181, 0.961474058720724, -1.83953404836843, -1.13671157175163, -1.38444086389626, 1.02815320061198, -1.37918673772152, 0.241865804025122, -0.266971574155994, -0.33600812567418, -1.05456642448721, -0.422516830755513, 0.272682124344865, 0.581673074901658, -0.142270982893622, -0.0530857165943762, -0.245326696296474, 0.111658227514345, -0.20147868455937, 0.0236174975751608]', 7.02); -insert into credit_card_transaction (time, features, amount) values (157915, '[-1.25411039501246, -0.0649692910440273, -0.701484926917165, -2.0137089669258, 3.91257117737602, 3.0084350491042, 0.317902205279048, 0.631811715004565, 0.0796131568708577, -0.187705811660144, -0.230528196910831, -0.0486252227695603, -0.501636393505328, 0.0379061536368099, -0.402998046344604, -0.242755884930695, -0.663790464917861, -0.971644772332455, -0.534067215422928, -0.13102200029208, -0.310168123391017, -0.634984691782627, -0.273068506205573, 0.729149660763609, -0.0950745162621681, 0.162974959299789, -0.0490179350343842, 0.0073919212221497]', 13.35); -insert into credit_card_transaction (time, features, amount) values (157915, '[2.07314050495194, 0.160444533888299, -1.92773981403612, 0.463771784916458, 0.452010631212701, -1.07165320911927, 0.289097027096728, -0.265643615317733, 0.480442465197333, -0.373277032869777, -0.575307344560624, -0.23564207659069, -0.662466926432632, -0.719435986571659, 0.203848788235053, 0.219958539336777, 0.666670663070596, -0.192796974171176, -0.0076825016110446, -0.195157443255181, -0.270750900837503, -0.698427563731026, 0.263745395503125, 0.633327298257517, -0.129101270497182, 0.294110340159281, -0.0772520743222654, -0.0341864203657847]', 5.94); -insert into credit_card_transaction (time, features, amount) values (157916, '[1.9897483178861, -0.223330504600318, -1.04491162019632, 0.331111915571817, -0.217006469308533, -0.880371750891401, -0.0084863098212759, -0.0964788283521086, 0.467794787379438, 0.267843642464905, 0.864910545243809, 0.493568434878492, -1.31998250030777, 0.739487281883822, -0.477672246443677, 0.0691316291020421, -0.378319527459128, -0.331938283830813, 0.338337342243589, -0.28981400913784, -0.23652124140144, -0.656256550604291, 0.353963873281439, -0.016798716630704, -0.400826560364293, 0.181900621423771, -0.0810070673723202, -0.0713197766781938]', 8.99); -insert into credit_card_transaction (time, features, amount) values (157916, '[1.56062905603918, -0.716724649050804, -1.82197651429573, 0.592674213883093, -0.286196644253949, -1.02625855477543, 0.222704049916073, -0.128578787229013, 0.935391202205827, -0.784466686853299, 1.11212858932586, 0.292280905200238, -1.57122910201697, -1.07148191194073, -0.649688231404452, 0.283744027659032, 1.06063654114159, 0.747910067762574, 0.297911804491932, 0.169550971911224, -0.0838371998722528, -0.555272928223719, 0.0132387961735952, -0.0765468985238263, -0.230231921303395, -0.131869871524722, -0.0573828158375352, 0.0066724989919832]', 221.3); -insert into credit_card_transaction (time, features, amount) values (157916, '[2.00047993671758, -0.121883269346704, -1.11192409826635, 0.238849362300104, 0.117110730008115, 0.0610137947047535, -0.534223473268728, 0.158218895397177, 0.723379207723015, -0.304064935245308, 0.781764833705914, 0.668316513646892, 0.101123908745036, -1.09368976154752, 0.0043578023505527, 1.1619110379149, -0.0647448170286013, 0.741493049892432, 0.25422219765741, -0.107685118270648, -0.31370866711294, -0.852833437382745, 0.377936192955871, 0.0733888448462453, -0.560395101943095, 0.098532375664288, -0.0251509086342257, -0.0245952961988179]', 5.5); -insert into credit_card_transaction (time, features, amount) values (157916, '[2.06744234907365, 0.180664572524214, -1.81408279048141, 1.26178223504015, 0.638117857640997, -0.769467932568533, 0.527781532476666, -0.287250068673222, 0.340185903898516, 0.289371450333883, -1.30622006713612, -0.271229657284828, -1.14680752510323, 0.689518362231553, -0.411823821434058, -0.575497632807276, -0.198110208043693, -0.383588248893993, -0.0863699877141649, -0.332918812285031, 0.015966793058212, 0.198756619411277, 0.0290265846303137, 0.640953044200207, 0.478791639732923, -0.517606673028781, -0.0278839615022978, -0.0586915594560799]', 2.48); -insert into credit_card_transaction (time, features, amount) values (157917, '[-1.3811801670671, -0.0110199570090237, 1.6187258326839, -0.789666963552105, 1.75572953441951, 1.11029397124941, 0.521056442426509, 0.288928458325404, -0.438860244480903, -0.555567676392488, 1.33844299885313, 0.895514146501095, 0.0942530042715619, 0.0346926867792677, 0.211127686494395, -0.622843429443675, -0.0105354554558779, -1.57012871041032, -0.537415763506381, 0.0162029388516364, -0.379769697713028, -1.00975114510212, 0.0447805992393896, -1.46136013684093, -0.0212727913427164, -0.054734924590897, -0.29572457100272, -0.0787510504711053]', 32.5); -insert into credit_card_transaction (time, features, amount) values (157918, '[1.90834206460806, -1.74202025372547, -1.23501217970743, -2.20059012917225, -1.09521156185242, -0.497750772699442, -0.698003889949556, -0.144100917330474, 1.1888409238861, -0.215154540491498, -1.76412617679087, -0.0336870769428297, 0.0670911911982854, -0.0285279905038496, 1.23092512837873, -1.59816069013561, -0.323164742123862, 1.44743613353295, 0.299701357477478, -0.261284069498962, -0.555165891807501, -1.31279071130434, 0.187838635043034, -1.127406407645, -0.481465675897489, -0.506746764482113, 0.0188074774386466, -0.0162776564189558]', 176.11); -insert into credit_card_transaction (time, features, amount) values (157918, '[2.08429755832433, 0.103235162466998, -1.61361555890563, 0.485971291788574, 0.264824231190334, -1.41185653162505, 0.598777333538508, -0.504130253158685, 0.496313007988332, -0.0788293085333469, -0.784750615478738, 0.783872174148628, 0.424062917113364, 0.35956500549993, -0.384584739945419, -0.843042744261262, -0.117171998634464, -0.71984337622377, 0.226709340552929, -0.23967285370069, 0.0020007712082624, 0.29396484734589, 0.0296908966250725, 0.0905369947593913, 0.38323670117106, -0.224995693625922, -0.0312610900509016, -0.0657430711526309]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157919, '[-0.26959871730005, 1.00204601186873, 0.353983119582744, -0.524324689068921, 0.195451095588173, -1.37294833640204, 1.07074845419106, -0.259101703364395, 0.0423116891689439, -0.123173436746835, -0.438670575873667, 0.554314605572607, 0.447463335944319, -0.0338829236437851, -0.469034604365884, -0.254854134946186, -0.295459358150351, -0.961104566821315, -0.27532016019649, 0.11314411278435, -0.257930502730128, -0.474437897055473, 0.161304648570382, 0.462782454030735, -0.467900470489219, 0.116095262676174, 0.360871923068357, 0.167584895059721]', 16.84); -insert into credit_card_transaction (time, features, amount) values (157919, '[2.09197169136571, 0.0687219450774321, -3.8188375150935, -0.652842000157968, 3.14274578217089, 2.63383431381525, 0.139801174064295, 0.53522830440046, -0.196245790875915, -0.239075344722302, 0.473904382455054, -0.0718214917982835, -0.325591434711489, -0.248767140037801, 0.815179843740933, -0.0375959810913961, 0.528569745432951, -0.280729046744247, -0.338025403835938, -0.111579824373858, 0.0123578893869716, 0.0263296010496553, 0.0550755644958474, 0.66103493935876, 0.271985819138783, 0.636178815286168, -0.083020013827179, -0.0604894970669956]', 7.5); -insert into credit_card_transaction (time, features, amount) values (157920, '[1.62483403246282, -2.24269797395034, -2.82386739165679, -1.17351838422963, -0.838943532483226, -1.78340421968327, 0.58913379142438, -0.810782632237686, -2.06130494180128, 1.58184664513257, -1.03518416701662, -1.28397525989883, -0.374307944265847, 0.503858184859234, -0.576524952121808, -1.37015604972209, 0.863043538542929, -0.267593956372813, -0.140826509408091, 0.302040095349845, 0.354444651285977, 0.637110120692926, -0.49520294973277, 0.110386315691532, 0.483409140673369, 0.258089300649623, -0.149933100959815, -0.0189630836004605]', 417.0); -insert into credit_card_transaction (time, features, amount) values (157920, '[-1.32974466339768, -1.4508295166275, 2.18600925993499, -1.82624161451296, 0.451298905998421, 1.08660586997725, -1.18945840609869, 0.614540247518562, -0.261847050172193, -0.372205095453535, -0.74079450700664, 0.0993901203691936, 0.722639145458476, -1.36804070025507, -2.17309050851372, 1.25990733608638, -0.115023249708138, -0.335576326065161, 1.55720387641174, 0.589540958165436, 0.223916754100598, 0.427397538252894, -0.199027786387784, -0.302409062568658, 0.697672589540845, -0.046943915672199, 0.0278676827698158, 0.0745410246254846]', 70.34); -insert into credit_card_transaction (time, features, amount) values (157920, '[2.08133949677623, -0.761712376602396, -0.858707345032282, -0.0374845362501132, -0.84299267684175, -0.892698700724695, -0.463015834331284, -0.319803279023863, -0.348509267104929, 0.896894591549453, -1.0544663244373, 0.329699652559688, 1.04416168263655, -0.200348195745272, -0.0203110902126511, -1.5713502021745, -0.183547090235792, 1.21848062108527, -1.08939192477731, -0.513842752573541, -0.0063431778331387, 0.649222366426924, 0.0187114313492941, 0.109604300807661, 0.047182392895006, 0.613509827906607, -0.0174451581753065, -0.0491872826849357]', 39.96); -insert into credit_card_transaction (time, features, amount) values (157921, '[-2.37570629382808, -1.04995863193441, 2.07604531045681, -0.807229985379467, 1.08474989966145, -1.0960588121922, 0.493954715192259, -0.318310909199382, 0.273134776809935, -0.61459747117965, -0.610760381329007, 0.140840810078379, 0.655169145397799, -0.626378873556277, 0.441671901985843, 0.670600034263735, -0.994564066909666, -0.403395298258754, -0.651618397975362, -0.49852969328415, -0.368564851607881, -0.35590977213292, 0.81138039220605, -0.0084219094805577, 0.482435792051295, 0.335093259566536, -0.240414267605951, -0.155891831117611]', 32.0); -insert into credit_card_transaction (time, features, amount) values (157921, '[1.38834229189561, -0.388268819883058, -0.401905090977022, 4.24114276500166, -0.119271577596902, 0.38792100919243, 0.25364013450123, -0.111083582731924, -0.50288165969927, 1.12245784571971, -1.39644097799082, 0.821426950025301, 1.38728501374022, -0.558687497890179, -2.03926870637376, 0.279001420849993, -0.40790763529645, -0.695422717220419, -1.42850628482773, 0.283336656765931, 0.261126085557606, 0.544270143098555, -0.15599877337842, 0.0478875801794117, 0.045308984122726, 0.105473464231047, -0.0381406711443492, 0.0001012789782845]', 256.59); -insert into credit_card_transaction (time, features, amount) values (157921, '[-0.502112973235413, 1.35186603328416, -0.412836920357391, -0.2615558778689, 0.467122897046593, -1.23791813112278, 1.16580854006253, 0.0446847769772345, -0.444110246444329, -0.7393545570311, -1.127309041561, 0.512542557742862, 0.360845245890352, 0.609044759599614, -0.592587851281732, -0.949769044025727, 0.135711529408129, -0.448722187933098, 0.56145111836586, -0.0468475951403699, 0.12007664745922, 0.543318160639334, -0.183263483858848, 0.0909354118908938, -0.0115440124805144, -0.219742904983597, 0.283016279869387, 0.181147342922975]', 19.99); -insert into credit_card_transaction (time, features, amount) values (157921, '[2.14977318513032, 0.0918546589971934, -2.48539435685465, 0.011082315857333, 1.20234423792827, -0.485703100158384, 0.696580403794684, -0.37595348220969, 0.0849770975413368, 0.144088582594547, -0.233900185769754, 1.02298046458883, 0.750042246861589, 0.614021397682603, -0.896903161861583, -0.335743698856402, -0.894274044783687, 0.270438328350434, 0.958145900928726, -0.159903610467402, 0.105323062181276, 0.54569712210562, -0.2717591164204, -1.31324847552732, 0.738292679928578, -0.0061735505435438, -0.0538232332469688, -0.0960391310016814]', 7.74); -insert into credit_card_transaction (time, features, amount) values (157923, '[0.144854668144045, 0.942795884614655, -0.616418344695841, -0.781397453720165, 1.19497757998435, -0.219874196555399, 0.81984880343284, 0.0991589007847242, -0.195286383124, -0.648184510692283, 0.439947920968067, 0.132401190305614, -0.472892716264366, -0.755977814134993, -0.846583646033655, 0.708518590146123, -0.0534080723981094, 0.515331742586739, 0.268809084576554, 0.0112938211942947, -0.332538187196344, -0.862024914655354, 0.0166797699176292, -0.0255676789916286, -0.396233036781039, 0.130041264196013, 0.215407740467439, 0.0674893382702629]', 0.89); -insert into credit_card_transaction (time, features, amount) values (157923, '[1.76794676949225, -1.3317884743186, -1.81390309537759, -0.778302902112833, -0.36067864548818, -0.12158355832951, -0.513622636667698, -0.017555021146143, -0.401912016961426, 0.320425716721317, 0.894189184261683, -0.250111873563193, -0.0412585705092759, -1.29250076137025, -0.440902737498159, 1.66897950273209, 0.826840167764128, -0.28890062993788, 0.772643032446014, 0.452530429634523, 0.243860284072686, 0.237728354398629, -0.0429106778502691, 0.140346897973324, -0.173091873199418, -0.244046219434171, -0.041094952254558, 0.0009445960115419]', 218.35); -insert into credit_card_transaction (time, features, amount) values (157925, '[2.06612409234861, 0.149124262884596, -1.69485014591972, 0.415536143517643, 0.431440051287345, -0.811468848112239, 0.166703470687372, -0.208972068821107, 0.499038603910471, -0.384722274298209, -0.505306774608129, 0.145939917620932, 0.0026536363261812, -0.826880873628236, 0.256620594620613, 0.253322010510034, 0.541493710627918, -0.39796047478566, -0.0272882746234939, -0.168195058334121, -0.358328464876924, -0.920589980050934, 0.350864829724375, 0.507042651410159, -0.277817463850434, 0.175586004307004, -0.0596769873963704, -0.0310382416608503]', 0.89); -insert into credit_card_transaction (time, features, amount) values (157925, '[-0.469927368026209, 0.681071126186689, -1.21057057165811, -1.64019103503306, -0.0452686023708123, -1.13371102044959, 0.243489695007196, -3.59311561575316, 0.0704217064755982, 1.50230778198256, -0.585439928322057, -0.540175022475834, -0.515417190945755, 0.424215596731098, 2.00601585834365, -3.90967508691696, 1.05942396178825, 1.43159240382367, 2.68701634861656, -0.88618933102057, 2.15417831768358, -0.151035698785869, 0.279019326375889, 0.0465086732777118, -1.268932962529, 0.0616609012282296, -0.530081562099901, -0.103633299281977]', 22.18); -insert into credit_card_transaction (time, features, amount) values (157925, '[2.03798409859368, -0.107904287351189, -2.2134741931746, 0.284251169697136, 0.861885585767768, 0.105492458142275, 0.0152618285931339, -0.0266753694179184, 0.562015102087528, -0.315493098591407, 0.0470049034370809, 0.523385053513287, 0.0328599834904463, -1.07213506524223, -1.13083891487648, 0.389608705876798, 0.262801718585189, 0.842614443417707, 0.624837980719691, -0.0716681060532197, 0.0532330445778965, 0.363661241709029, -0.143960173513846, -0.309169799901015, 0.325451888604953, 0.733226556750844, -0.0674276729432825, -0.0537980248281564]', 28.75); -insert into credit_card_transaction (time, features, amount) values (157926, '[-0.149720031210442, -1.29947671081083, 2.02159688784832, -2.51844685789081, -1.04558831530504, 1.90806545577602, -1.61774428375973, 0.624424924848313, -0.638222959495195, 0.496819186791492, -1.27469442222772, 0.204533175024581, 1.47255254524403, -2.06406183073973, -3.12707780329266, -0.349028465809798, 0.149612869201718, 1.14652588975338, 0.682683957223623, -0.177374548345525, 0.0366306720757109, 0.911385983475427, -0.178041636891683, -0.288273405218505, -0.469451968225097, -0.0448956568338422, 0.277215773089255, 0.191103641067075]', 31.8); -insert into credit_card_transaction (time, features, amount) values (157926, '[1.9795778736571, -0.0628243311654117, -0.801145033525763, 0.429915507498614, -0.331972236085698, -1.20402428218077, 0.116049582576774, -0.242515096543534, 0.194024894151914, 0.231712898076633, 1.51719058007952, 1.4860179666106, 0.205326508986029, 0.44125888752274, -0.737272159311528, -0.0884109523365345, -0.352401335637593, -0.598001143221396, 0.220898416506869, -0.210420842369034, -0.196652433595654, -0.456300566777828, 0.39340865192979, 0.557670916520259, -0.39282097127563, 0.142403130544455, -0.0717247944041733, -0.06366750739952]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157926, '[1.67225192237509, -1.67184066639985, -0.78690565921556, -0.71283191897065, -1.07475689136153, -0.149468662167204, -0.602240865497721, -0.0581022270524489, -0.220055242376447, 0.676282310115501, 0.724108066847037, 0.751219767809571, 0.84039135057236, -0.429802304306782, -1.14830086393876, 1.14431773520427, 0.0334859208353034, -1.3913084441712, 1.17342778428317, 0.489415862483088, -0.024771797436085, -0.515639856585539, 0.16354849555215, -0.398703372753287, -0.543406467511388, -0.594296156357309, -0.0317175746725137, -0.0144454796375164]', 246.42); -insert into credit_card_transaction (time, features, amount) values (157926, '[2.06327052064031, 0.6332167225651, -3.16169090593985, 0.614965472820401, 1.25925880130661, -1.3590697924574, 0.70652267672436, -0.327700599453414, -0.199335992216013, -0.869560880333858, 1.7312478121582, 0.244128501610669, -0.572848671895177, -2.16855584459408, -0.67542427667193, 0.523879433659684, 1.95689558843626, 1.06305703240325, -0.0273398567463443, -0.133516068658077, -0.0183601373573682, 0.105097181497664, -0.0466043617170252, 0.587523290926874, 0.35710594172373, 0.659627191027381, -0.0870417683732725, -0.0231235931601989]', 0.76); -insert into credit_card_transaction (time, features, amount) values (157926, '[1.89249428551278, -0.126636355157507, -0.269777503092203, 1.59414794585428, -0.346948353572951, -0.262272167246693, -0.157656720106602, -0.0709524219453199, 1.02794768206607, -0.0539594756059052, -1.09023926843527, 1.27120612926327, 0.759433012836665, -0.45104598593821, -1.27398935659502, -0.528824285411609, -0.0464234198283567, -1.08995304056593, 0.127766751761212, -0.203585489958346, -0.496868851816582, -1.11414829401264, 0.418152845346167, -0.0705564610178097, -0.307551134633643, -1.10722847425256, 0.0610376203425599, -0.0256228531566949]', 25.0); -insert into credit_card_transaction (time, features, amount) values (157927, '[-1.49950278065785, 0.198544987027778, 1.24902345373812, -0.228124591498957, -1.28602824063477, 0.175765469678459, 1.32019922670457, 0.359833114676594, -0.334021624874887, -1.52211713677469, -0.957003189839956, 0.0888477030312176, 0.298160977009357, 0.300753694659534, 1.02372674417847, 0.241951134912847, -0.304956838512993, 0.213557377093191, 0.197082971472968, 0.613954136944857, 0.105898619377152, -0.394461650590835, 0.57259484395786, -0.157633209706208, 0.444455062193257, -0.410752007972983, -0.163469144579092, 0.0364531341705004]', 340.0); -insert into credit_card_transaction (time, features, amount) values (157927, '[2.00999773155784, 0.0780338456022838, -1.61652155075309, 0.339618048335816, 0.386999813090905, -0.581690901989414, 0.0487643151932074, -0.0555420652167005, 0.272619965813547, -0.208061364054128, 1.28223767750235, 0.731158673223781, -0.399539294696636, -0.562925756847489, -0.423129728284929, 0.418383688994817, 0.36364542753353, 0.0828018930751454, 0.205517583317011, -0.178528913716366, -0.299133408303439, -0.803996640628812, 0.360080791148288, 0.600858565849764, -0.338815187405455, 0.1493847773877, -0.0653980436276464, -0.0400808384428196]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157927, '[2.07242834951376, 0.170784467937744, -1.68610985974446, 0.423844711265842, 0.414162742968445, -0.895834796696281, 0.197905432085552, -0.248225625592589, 0.466426547731218, -0.38322948831772, -0.510169448179327, 0.246294227200491, 0.225832110174649, -0.875674627951868, 0.184517595215887, 0.299102369995215, 0.475778461449691, -0.338786076466451, 0.0394066526440644, -0.145858681175497, -0.36042757844679, -0.925081656658464, 0.341634212111376, 0.572669773498015, -0.256878969460669, 0.169051407112824, -0.0616025591092564, -0.0297246080302685]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157928, '[1.22668843949932, -2.44462223269125, -0.893435787102717, -0.647262341835603, -1.09395247475253, 0.851845331530816, -0.783713700846096, 0.200736534870435, 0.059334956177401, 0.432998865157126, -0.0574662532598882, -0.210869192014289, 0.424701382728348, -0.314012591159239, 1.43569115866562, 0.496097419483148, 0.86516185477645, -2.31918846005751, -0.9936610104215, 0.724262791781626, 0.734734972051411, 1.35268564644745, -0.141984034597083, -0.97126974001279, -0.578356232595922, -0.0124460184139842, -0.0078255562590056, 0.016010141695998]', 425.0); -insert into credit_card_transaction (time, features, amount) values (157928, '[2.30177519907839, -1.25629502042441, -1.08308622456662, -1.61083860571318, -0.926888538614509, -0.497754813926663, -0.971889813375486, -0.250068274408717, -1.41090337045908, 1.53118295388869, -0.88988163800387, -0.246967156747601, 1.55576017518623, -0.626213276958146, -0.245237573021508, -0.678501193569506, 0.448204858123719, -0.304258605922677, -0.153860201316035, -0.337322004793529, -0.161210061954408, 0.0788369253966963, 0.238571415146495, 0.615831920613947, -0.111112415612536, -0.188268182255441, 0.0133491261760834, -0.0428505536525869]', 20.0); -insert into credit_card_transaction (time, features, amount) values (157929, '[-0.996633663542127, -1.53229451325185, 1.62348838460276, -2.63569910929782, -0.209817581830176, -1.10360305331492, -0.644968275106295, -0.0210492973107727, -1.94672763390834, 0.480837015985327, -1.04008182540377, -0.599111544266612, 1.14441585333425, -0.82533057089345, -0.65210905684967, -0.17732662692614, 0.133720385012858, -0.204826628163015, -0.852801296886538, 0.0284644717629053, -0.210680180576877, -0.598114124687074, 0.361205503811889, -0.0802641885349423, -0.364965441564858, -0.574159276451151, 0.0914888529202736, 0.166600535479948]', 79.95); -insert into credit_card_transaction (time, features, amount) values (157930, '[1.88667080042368, -0.337838076250316, -0.543728986890066, 1.05161430647845, -0.17983096641759, 0.396881738709101, -0.628385290693623, 0.220266513283861, 0.732336098545478, 0.386322363202457, 0.328422780778863, 0.502116781623136, -0.37866923712037, 0.269425124734399, 0.206780981821633, 0.821881907666493, -1.17185177836571, 1.06809811152382, -0.325963303513875, -0.160025368211387, 0.260342100363387, 0.733663635780487, 0.0910736279044898, 0.321768392159181, -0.0793627923311834, -0.593850042078899, 0.0380393160990945, -0.0319022611131042]', 40.0); -insert into credit_card_transaction (time, features, amount) values (157930, '[-0.748864800183258, 1.21581870775893, 0.705935748097067, -1.08183091938693, 1.24553069749271, -0.588250921000645, 1.34620588621373, -0.120517533308124, -0.680443752040808, -1.58025959317457, -0.613394596538767, 0.0006792452833486, 0.416059829725375, -1.08656005646751, -0.401013749240097, 0.393404291661908, 0.295977691832879, -0.374662895282829, -0.576872091533141, -0.0202856534745011, -0.34510109111359, -1.04574096880025, -0.303818005533999, 0.520637078608609, 0.615090837935169, 0.211693664237025, -0.0505382067459184, 0.0673700622401467]', 11.28); -insert into credit_card_transaction (time, features, amount) values (157930, '[-1.21657246910893, 0.568843673348446, 1.64876509383322, -0.557792472045414, -0.273298988445341, 1.78012172857568, -0.314914711962459, 1.02305282145287, 0.548210456703622, -1.1787380420447, -0.681266913112478, 1.05521178688015, 0.70408647872069, -0.515858965926757, -1.13395623276089, 0.165666011204449, -0.463233693722475, 0.945998889103085, 1.19095111017846, 0.275452775193575, 0.0029476309373415, 0.141420541878362, -0.258955781536889, -0.333517955042215, 0.694632028148933, -0.128919900332844, 0.208011628336672, 0.0701955704622153]', 83.57); -insert into credit_card_transaction (time, features, amount) values (157931, '[-1.58155892330988, -2.77860440658372, -0.510734456627402, 0.603838683866386, 3.89006771657355, 0.0235024593207987, -0.812579162743547, 0.403818636148781, 0.104050386646725, 0.166804211343967, 1.24375204069339, 1.54249834202393, 0.531271557425058, 0.252255191565789, -0.33017965465238, -1.95937488442042, 0.750646956754927, -1.76834461224154, -0.420762944125979, 0.765336181770929, 0.584801954267739, 1.33307390203306, 1.03633300114502, -1.63511855907707, -2.0942093176399, 0.200851894259616, 0.125664788857475, 0.167508926127598]', 111.75); -insert into credit_card_transaction (time, features, amount) values (157931, '[-0.999705470695706, 0.661781016640732, 1.01828728393128, -0.805451545376523, -0.755428099574746, -0.493924324642999, 0.0950675491652153, 0.362861604732441, 0.703607190076796, -1.03793544696967, -1.44266150499005, -0.183107631747373, -0.651545299893335, 0.0643111205055434, 0.118615058128725, 0.215812897625593, -0.366418166689673, 0.447597698769094, -0.272673444317152, -0.398274096834139, 0.359274398785639, 1.0693916355755, -0.0893035191721659, 0.0816305850691395, -0.2779978596893, 0.114368958483053, -0.17717216923088, 0.0730964430666244]', 49.94); -insert into credit_card_transaction (time, features, amount) values (157931, '[0.100148282414153, 0.676166286838082, 1.04349439642276, 0.962489552506196, 0.365100836667361, -0.261914242227575, 1.47077152220227, -0.639380199211605, 0.544084425402585, -0.0411579775358732, -0.923983833654127, 0.888923002165709, 0.552844354748019, -0.902308723167735, -2.07147922941979, -1.45113845494642, 0.124450560151414, -1.07566358426091, 0.37047770840819, -0.0508854197968171, -0.210678083560212, 0.155222398984881, 0.108502729656684, 0.402514909981623, -1.15401443881916, -1.04309538805417, -0.107650934684726, -0.176566228168035]', 55.0); -insert into credit_card_transaction (time, features, amount) values (157931, '[-2.36984159154914, -2.06708959177853, -1.672846441851, 0.207226862282187, 2.09357274384398, -1.92823856607067, -0.0183104403338608, 0.286660233107773, 0.720045768536136, -1.33038276403666, -1.0858394197759, -0.0851601176976521, -0.545261412278518, -1.15329237694464, -0.569572615417847, 0.222130835308653, 0.978158714747765, 0.342694602056529, -0.0428267414226355, -0.617810009419051, -0.0987121863144065, 0.340048359096145, 2.43002557793095, 0.5041642980143, -1.43884015852876, -0.40594440083711, 0.425397261169659, 0.0821332529257892]', 59.15); -insert into credit_card_transaction (time, features, amount) values (157931, '[1.56316419522887, -1.92237851048437, -0.286649942076551, -0.289824700789892, -1.6573304828314, 0.0923729497343368, -1.06135356222741, 0.123180954115099, 0.105007234380892, 0.858124473367227, 0.242249897991142, 0.382766851217087, 0.0108929719067542, -0.118073309622936, 0.028971629509992, -0.504475324346855, -0.706804464266619, 2.04814054847755, -0.730959283968476, -0.0638560757163427, -0.164109422940277, -0.502639121143212, 0.135547486134662, -0.355356367384818, -0.813823143364726, 0.439412438879461, -0.0449778542810493, -0.0024370835543427]', 270.0); -insert into credit_card_transaction (time, features, amount) values (157932, '[-0.160297074648054, 0.709094115878877, 0.148480596231733, -0.516943573360998, 0.311319747315188, -0.965599269386475, 1.06040374899812, -0.279752378143138, 0.15143058394144, -0.399156586790789, -1.12079995666747, -0.359456328175633, -1.00125455513815, 0.232275012925142, -0.49926874390349, -0.265317902442354, -0.215536334494666, -0.751266053430272, -0.0432339711763388, -0.326989621419416, -0.160986762101509, -0.439158590079785, 0.109031352133516, -0.0284253278190202, -0.499343484232979, 0.186041583443561, -0.240397385572595, 0.005166309357732]', 28.29); -insert into credit_card_transaction (time, features, amount) values (157932, '[1.99399610750816, -0.441073379295851, -0.550121635450938, 0.17594495130319, -0.40664065146016, -0.162611661834131, -0.556174657533116, 0.0240606336825749, 1.10933758232747, -0.0185502218286165, -1.09789316881293, 0.221083335413362, 0.132876082197357, -0.120905585088131, 0.610275311059643, 0.565137812534681, -0.643151468420928, -0.276170973023189, 0.0482427268632735, -0.114947435540659, -0.231593211683458, -0.635637013098799, 0.403971896481946, 0.46582289294961, -0.587699144423881, 0.254587372305099, -0.0440856276239011, -0.0354787063757335]', 27.5); -insert into credit_card_transaction (time, features, amount) values (157932, '[-0.923743711077661, -0.0815436012816398, 1.01890830747789, -0.631155831821731, 0.728647896683211, -0.545908250536857, -0.0939054900012241, 0.0480129080617804, 0.405543215330192, -0.343967733273209, 0.413113050146179, 0.803599670305774, 0.377403376991828, -0.0429060416387811, -0.157090461258343, 0.504934899689507, -1.1877927210154, 0.995809183479603, -0.0581101183273862, -0.241519417589196, 0.378695637017941, 1.18094221007507, -0.0907052791267418, -0.30363944506113, -0.741254881426649, -0.391510645595408, -0.0277062511770515, 0.348112927089877]', 0.01); -insert into credit_card_transaction (time, features, amount) values (157933, '[2.01048079100994, -0.163105237744151, -1.02358735609447, 0.331409065401812, -0.208549339987795, -0.962479551905495, 0.0269321823599938, -0.145556666765375, 0.404757178299718, 0.26670775381077, 0.895190191312959, 0.70354411542486, -0.891431446637449, 0.64788656446437, -0.573382353222288, 0.104241874415154, -0.456065049761307, -0.299636396288245, 0.405997076630764, -0.269284330987692, -0.240721748817081, -0.639920425027522, 0.348765906065566, 0.0541082025664383, -0.370181167062733, 0.175461551385254, -0.0801851374028922, -0.070848969242833]', 2.69); -insert into credit_card_transaction (time, features, amount) values (157933, '[-3.21445000084446, 2.91673744080652, -1.8096405745232, -1.02585432790887, -1.27548416232014, -0.547802031402771, -1.37006921340876, 2.08578685226851, 0.707730213691018, -0.96840079874447, -2.1415280814966, 0.347935421516118, 0.331449363036786, -0.313308457981825, 0.40258689024827, 1.42739849619037, 0.766457367589872, 0.835274228448777, -0.0676473357997088, -0.198901135849425, -0.148731851764974, -0.949253091373133, 0.129468696040402, -1.16027957012113, 0.179760019683015, -0.23109155793543, -0.713593054679059, -0.0136291798134445]', 15.33); -insert into credit_card_transaction (time, features, amount) values (157933, '[1.94031432169939, -0.544233624273246, -0.49048247028825, 0.421451359399117, -0.572816447416609, -0.127636909255188, -0.656312416187755, 0.0523169392621075, 1.53107533206318, -0.169331051888316, -1.19524283021061, 0.179578229085371, -0.234706939293981, -0.141673839022606, 0.573752806042991, 0.145934777337158, -0.542353763513583, 0.383136279159721, -0.212045315922458, -0.15593370018846, 0.247900267122131, 0.862970103588059, 0.0837531939331197, 0.686706300720079, -0.0359092549126385, -0.184701218054395, 0.0287115852983715, -0.0275239764750578]', 37.78); -insert into credit_card_transaction (time, features, amount) values (157933, '[1.49409021870911, -2.71278067203835, -0.834707535825328, -1.39735154620108, -1.84857565145707, 0.067364911155527, -1.1105904628073, -0.0455454425153687, -1.32691992068007, 1.54581476644946, 0.843089267257774, 0.140911334245054, 1.15913838191924, -0.470123964905989, -0.250684384426538, 0.109188499842649, -0.0477974859861319, 0.916211583361146, -0.32269850765727, 0.43095587827675, 0.323305498570045, 0.534731173237921, -0.10025923838944, 0.792810112691794, -0.450799514016043, -0.163215685259759, -0.0354466759780227, 0.0256698237320813]', 396.5); -insert into credit_card_transaction (time, features, amount) values (157934, '[2.05051487153934, -0.045836353913454, -1.65988411541739, 0.512492674387287, 0.1312427574889, -1.43688696506041, 0.53251091544426, -0.434171636489779, 0.692519774103628, -0.0482950603998944, -1.00774577985129, 0.0883755183090037, -0.881945406855815, 0.623926151907753, -0.238823561021906, -0.779397570357765, -0.0418641476062158, -0.555759180390315, 0.230120983103104, -0.288944095592865, -0.0027552192544852, 0.177790555018511, 0.0304282345799942, 0.0555684837406786, 0.332706399608959, -0.222421038755834, -0.0430287956281118, -0.0655962020111639]', 17.99); -insert into credit_card_transaction (time, features, amount) values (157934, '[-0.852475802121942, 0.590264681919447, 0.871489937947575, -0.308073286188237, -0.207866690565924, -0.0318295487406609, -0.19742958178507, 0.631285062995786, 0.541966296567461, -0.862467179835533, -1.52030087729121, -0.100929432409838, -0.299295041043022, 0.108546750818018, 0.414708459726021, 0.0343875692949917, -0.266055585255675, 0.655586153914652, 0.157511855513372, 0.0673548312953131, 0.347247701556557, 1.0317434120918, -0.142737614428176, 0.686748511239331, -0.169087002484128, -0.133578656190316, 0.317826877483763, 0.150153259257448]', 29.96); -insert into credit_card_transaction (time, features, amount) values (157934, '[-1.64937504465849, 0.912264588784204, 1.25975654945296, 3.02071593705283, 0.434721587872998, 0.137396270373949, -0.290408942202668, 0.42950993834176, -0.970614790780346, 0.870068741642854, -1.61961161665048, -0.105361275079481, 0.560566436468923, -0.273708808065161, -0.972386978305047, 1.24352826411273, -0.854588187637739, 0.0165976480759262, -1.9511340864707, -0.607226772013721, 0.290573653321462, 0.727866317439068, -0.619974484563451, -0.0428794870960244, -0.211598561201863, 0.0072911947834407, -0.400901041151647, -0.23138405620086]', 8.27); -insert into credit_card_transaction (time, features, amount) values (157935, '[2.00676454566572, -0.710237833925383, -0.755293639141048, -1.62640302113185, -0.625136090845934, -0.546715596537143, -0.572969286306591, 0.0222630902156835, 1.81197066995996, -0.801281967783048, 1.17818691204433, 1.60266326364236, 0.17779544035028, 0.193881783687797, 0.50573184799523, -0.179786831224149, -0.560710817796427, 0.254741303998895, 1.07250517903783, -0.124507887887863, -0.170966816749237, -0.367460029516793, 0.389125186637656, 0.752546762498424, -0.430053917412824, -0.617594779104801, 0.0169297836474716, -0.0390176525159983]', 15.88); -insert into credit_card_transaction (time, features, amount) values (157935, '[1.8152957925141, -0.678746107553952, -2.4025418562889, -1.43217797689056, 0.189442851410343, -1.79984882565986, 0.966507796699274, -0.687095186406237, 0.879442466848056, -0.88253682092583, 0.128477328269856, 1.32638365201651, 1.04606747098471, 0.648284921621648, 0.914678732102231, -1.31133661582044, 0.0192164467973231, -0.721059530122926, 0.572362750797546, 0.22209128467019, 0.254297739029505, 0.56845770814564, -0.11372004482326, 1.19104973989717, 0.376835687297965, -0.152228177039608, -0.0850118732729521, -0.03333362981648]', 180.29); -insert into credit_card_transaction (time, features, amount) values (157935, '[1.40763673596149, -1.15439092717661, -0.708486205639558, 1.34639535383586, -0.682613754301022, 0.108297439154889, -0.281614886873305, 0.095803598225612, 0.801085416968342, 0.294608217861467, 0.173787872122009, 0.246645864162601, -0.856057353747963, 0.43704032539123, 0.257295442992941, 0.879562777910484, -1.14625461407603, 1.17766454346156, -0.376059919468366, 0.280278052594373, 0.402834049353601, 0.600409279993243, -0.167526867690392, -0.521844412501431, -0.192937035480397, -0.578062878500199, -0.0069689442486937, 0.0017792140438377]', 286.0); -insert into credit_card_transaction (time, features, amount) values (157936, '[-1.99960160045057, -1.03097007345002, 0.868237358401827, 0.159978909198401, 1.17580569884783, -0.990404086795604, -0.685854705757231, 0.514693219225114, 0.056373920060499, -1.07163812635335, -1.50081370185409, 0.595907505912696, 1.29591216281519, 0.243759142194074, 1.18529877612739, 0.144926263315029, -0.504452084329012, 0.494566931743183, 0.912768704477751, 0.59130621640204, 0.133479871242145, -0.35503856343963, -0.0808384568878395, -0.723466007608803, -0.169443315890385, -0.760528326090835, 0.0952557361345498, -0.206094254441784]', 42.69); -insert into credit_card_transaction (time, features, amount) values (157936, '[2.12568821011582, -2.03436515358675, 0.900202268696414, -0.968166346990035, -2.6112160839556, 0.422304123376147, -2.38345416590547, 0.220293158533413, 0.414358841966527, 1.13416758777087, -1.7220770903612, 0.352467934575303, 1.54098711939885, -2.11660112855519, -2.08647577744429, -0.870003571468066, 0.92170646437955, 0.0775580207928043, 0.111972634866761, -0.357992637821618, -0.0495320504133747, 0.842973027979845, 0.17722166441416, 0.115382047613715, -0.320203625457979, 0.015381260417291, 0.125359724286661, -0.0226058418312986]', 27.5); -insert into credit_card_transaction (time, features, amount) values (157936, '[-2.36520761815987, 1.96212555829729, -1.0475985119509, -0.225612525608671, -1.0468606891665, -0.377309573552944, -0.930375761538982, 1.72723574494781, -0.0404905057234974, -1.33488885852872, -1.04455162856296, 0.726296637077188, 0.82939946816477, -0.539656098018437, 0.258189525507556, 1.26277629478531, 0.947665603120058, 0.310601639128592, -0.585832049133921, -0.302597616939814, -0.13703350222999, -0.794172260731257, 0.273110299296714, 0.553542125236304, -0.0545949643094026, -0.0293110286785042, -0.541870079163803, -0.173437350956433]', 35.0); -insert into credit_card_transaction (time, features, amount) values (157937, '[2.07073180799526, 0.227550669120164, -1.31574927009334, 1.7266136652626, 0.600045853741118, -0.313731494787029, 0.271924383258325, -0.241764100953671, -0.879137142565208, 1.14052757613183, -1.1357505243856, -0.0246882636798341, 0.703436711202168, 0.0737396200929519, -0.81072903270696, 0.825323047645772, -0.556323780519571, -1.25861827629337, -0.508339505980047, -0.103105497707805, -0.251511327456123, -0.729932964108987, 0.326644059692305, 0.560588901806596, -0.442805340472907, 2.04715086625208, -0.223480358423593, -0.0800168737441402]', 8.63); -insert into credit_card_transaction (time, features, amount) values (157937, '[0.0358113165050554, 0.740719159308204, 0.0944803876090328, -0.804778045505724, 0.608162459433124, -0.543976232764819, 0.847261450713584, 0.0196422143850203, -0.137734274500655, -0.216900516730717, 0.194597805908088, 0.195452382433387, -0.880324521923666, 0.45721000670016, -0.971497775211918, 0.284121323720517, -0.781786981714732, 0.0117086063544979, 0.390657152543995, -0.0677282260485649, -0.250026015762826, -0.619151811566777, 0.0111216423588114, -0.524065779205352, -0.485622877828517, 0.153284567765541, 0.23665543092961, 0.0804886050444655]', 4.49); -insert into credit_card_transaction (time, features, amount) values (157937, '[-0.476661841557924, 0.815895421808081, 0.678821390969839, -0.773410961827341, -0.656031551252051, -0.720742936161877, 0.0194006714821521, 0.34139181427534, 0.642837592119663, -0.891209223898404, -1.16651077440555, 0.153350383618923, -0.28678857807104, 0.13576682716239, 0.248841608411489, 0.351327041714304, -0.440560201340703, -0.0763517143944299, -0.16485121004736, -0.354658954760584, -0.0511691387550822, -0.295775297330079, 0.200184229821621, 0.0039487510590451, -0.765040643508011, -0.384960260404724, -0.302855669408198, -0.0165209291067946]', 19.95); -insert into credit_card_transaction (time, features, amount) values (157938, '[1.93484338219189, -0.389694760094884, -1.44706099169778, 0.0081580551269274, 0.654437771578433, 0.877317935558023, -0.283677918179636, 0.371407993418918, 0.575884941463277, 0.159969186058513, 0.731405267405812, 0.252166929923869, -1.67358051629264, 0.857794902005322, 0.338035963070511, -0.515780456701549, 0.155230586091055, -1.30115197132758, -0.381920279310698, -0.396723132694109, -0.21795942486648, -0.505271720674369, 0.354032768254475, -1.67830397851102, -0.516607247183201, 0.315750393161434, -0.0368376229698279, -0.0909043683195387]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157938, '[2.06253949386552, -0.0822292638845887, -1.13743899601745, 0.375135616510582, -0.0569003504536342, -1.04451125851927, 0.152887861239511, -0.286738147441077, 0.584283724077538, 0.0711448717282764, -0.868474100617354, 0.288731855052136, -0.134677609621868, 0.316160479489972, 0.123341061964316, -0.107611065615564, -0.275826598985267, -0.880057623368549, 0.134407694463371, -0.23801453525169, -0.295679061276576, -0.722962455760098, 0.329472155146491, -0.175943785007295, -0.300425549242861, 0.211411610435611, -0.0693891777777187, -0.062403053465718]', 2.7); -insert into credit_card_transaction (time, features, amount) values (157938, '[1.91797632096915, -0.101480181368795, -1.88891369173568, 0.219718858249453, 0.485723915735256, -0.445284860351535, 0.133246981730833, -0.142217479149238, 0.6567373613872, -0.728637586332209, 0.78093714116065, 1.31836526330095, 0.914956352571586, -1.47653195752055, -0.836017995056432, 0.28794654937039, 0.564584930214796, 0.542679419618553, 0.593760076707005, 0.015706653401832, -0.192899092760535, -0.385347462359433, 0.0308762411111002, -0.886188461346622, 0.0029976297248518, -0.0666178805549832, -0.011731425286745, -0.0278809193377484]', 63.35); -insert into credit_card_transaction (time, features, amount) values (157938, '[-0.379371239477643, 1.42202910728327, 0.555737702645311, 2.65069604526932, 1.82774672661635, -0.826461077005383, 1.86598897579944, -0.495449616913309, -2.16549802584117, 1.01202000210432, -1.29621767841865, -1.18180443670675, -0.857239426525845, 0.563673244455897, -1.01374778800874, 0.44347054819045, -0.896588812741444, -0.425102964327577, -1.63692782825568, -0.122771351962183, 0.149774019942872, 0.40317545822151, -0.289864964219639, 0.0104582479333766, 0.0495879528771649, -0.0128977106344409, -0.102305218786961, -0.0675495373159021]', 13.72); -insert into credit_card_transaction (time, features, amount) values (157940, '[-0.0973246006848609, 0.592255028709971, -0.0593528667094778, -0.999360298185324, 1.34393876660967, 0.972694936639742, 0.598442885728545, 0.433777452146986, -0.188697472685601, -0.354892657515838, 0.750370890438897, 0.592604956044477, -0.526043600274106, 0.456610998569303, -0.236193949937416, -0.561329838420221, -0.0332325350564239, -1.32745966807357, -0.619219806360956, -0.132283383013645, -0.174622051990059, -0.280580073186863, 0.0691620640734305, -1.65217111766122, -0.666513702622147, 0.254181093996747, 0.288765340549955, 0.0693795945108346]', 0.89); -insert into credit_card_transaction (time, features, amount) values (157941, '[1.66346628332977, 0.0161565033823855, -3.07944715005947, 0.963218641136904, 0.563971985156584, -1.90183911484916, 0.850783612408749, -0.448028586100193, 0.649786689981896, -1.53742228341976, 0.11071062410117, -0.820379309597694, -1.42190781779088, -2.48126093499951, 0.926818814135502, 0.483620732209474, 2.39707423193273, 1.25805342436726, -0.580975052675977, 0.148274702822015, 0.0344739992572245, -0.168687215772104, -0.18997868982085, -0.309280568531209, 0.248661464461843, -0.531051579455465, -0.0093241156849915, 0.0457075792705235]', 200.24); -insert into credit_card_transaction (time, features, amount) values (157941, '[0.135284262260185, 1.04293772891261, -0.416184305175535, -0.558121056674973, 0.978586839717608, -0.723364610572361, 0.991677983344454, -0.102323404973826, -0.0966378332773202, -0.854621436384597, -0.615363971553324, 0.0609620225525676, 0.329660925254782, -1.07707145820707, -0.224448681588369, 0.268308657069071, 0.391878960842543, -0.332201804502183, -0.290976293642326, 0.0405190764221664, -0.332610248695567, -0.791248653198165, 0.100974025454756, 0.507926277898433, -0.419543953441283, 0.118221122502486, 0.226584727952845, 0.0843743373490887]', 5.99); -insert into credit_card_transaction (time, features, amount) values (157942, '[1.97490836803606, 0.393454453047863, -2.41811749805605, 1.48453125920707, 0.990454022478434, -0.895208127169753, 0.683416138108996, -0.310635893075828, 0.193750090274313, -0.363908216620832, -0.72348345756227, -0.25168414960463, -0.688610488281047, -0.909783993477505, -0.264881854143427, -0.169342326113957, 0.985606320752739, 0.1300561812146, -0.394645700129386, -0.183293805900527, -0.0317886345857304, 0.0222016725534007, -0.0289695944596609, 0.46938804748557, 0.470085849727597, -0.517057395486755, -0.010272556184309, -0.018587905753234]', 40.31); -insert into credit_card_transaction (time, features, amount) values (157942, '[1.72709379859789, -1.01136616711475, -0.747801514904899, -0.797741731916275, -0.633602209930809, -0.19572117697175, -0.424757716464845, 0.0378939284983705, 1.14748749498058, -0.359052658044124, 1.19424267713631, 1.52570547620699, 0.56033600530047, 0.081696641711565, 0.165045661037726, 0.265515219958242, -0.600558439255539, -0.0876576340650845, 0.583289876599488, 0.180549874235881, -0.11807198142173, -0.562324397426176, 0.333897501956626, 0.731700219345021, -0.700264284981191, 0.219022163514518, -0.0703824020252954, -0.0248764219847886]', 149.0); -insert into credit_card_transaction (time, features, amount) values (157943, '[2.06256465300189, -0.113800312255569, -1.07906987892629, 0.426818207976473, -0.229405431683488, -1.24121665746299, 0.121577002191013, -0.283253521750122, 0.67995808293897, 0.100613207746825, -0.88964623228307, -0.046501348752039, -0.855279289386214, 0.458389062081293, 0.139934344239305, -0.0648617785902098, -0.232415432788744, -0.760129372296675, 0.149218311915294, -0.285130677852012, -0.29971944138635, -0.772174932416073, 0.353041343265542, 0.021145176792245, -0.330326371385632, 0.198543551712851, -0.0765679942228843, -0.0619574687154276]', 0.99); -insert into credit_card_transaction (time, features, amount) values (157943, '[-1.00298903988335, 0.448279245453895, 0.363189892687094, -1.11913961953647, 0.0746410757383499, 0.826992641139967, 0.225250396939471, 0.195542176646352, -0.625701615546153, 0.337394336729985, -0.569133572553786, 0.854696114843583, 0.50249519787009, -0.451760679167143, -2.41962636921048, -2.35598949395017, 0.159175299773122, 1.26834020851451, 0.899528515021976, -0.601018693779465, -0.594246112531821, -1.02125511451609, -0.157182992757536, 0.0687629632825386, -0.106747921894385, -0.525962391932538, -0.62686298493347, -0.139486810535574]', 41.47); -insert into credit_card_transaction (time, features, amount) values (157943, '[2.035978765894, -0.139826291843228, -1.17926292158945, 0.477305222606146, -0.387395038548044, -1.56998722096494, 0.114790812664978, -0.292384620741237, 0.872958808373716, 0.0659956478481336, -0.61968559757071, -0.620533016547673, -2.03117327131294, 0.920031668107667, 0.979279036220855, -0.300974116881926, -0.181015951699458, -0.0409106241044171, -0.445349442843656, -0.396402736873195, 0.254432267665787, 0.810429066219608, 0.0825417299561031, 0.382230677710144, 0.129997938573399, -0.124265498722336, -0.0289474352578498, -0.0594777282540789]', 0.85); -insert into credit_card_transaction (time, features, amount) values (157944, '[0.788862936884592, -3.04565148607129, -3.39551671570616, -0.482369484962375, -0.598364148176146, -1.12007271042563, 1.3323266198968, -0.658607050266915, -1.19469017018191, 0.806631125091535, 0.29598207068673, -0.304522907977219, -1.19973554188776, 1.27035457607765, -0.725079557234848, -1.85953981174207, 0.0565422537298613, 1.28198069724227, -0.363226343805397, 0.862955734283772, 0.351615251353681, -0.16012130109623, -0.760862009229204, -0.284160038152073, 0.0445157762607068, 1.56899718527254, -0.322092913734916, 0.0135365458158489]', 767.42); -insert into credit_card_transaction (time, features, amount) values (157944, '[2.2247339060952, -0.547757734233112, -2.1876093230173, -1.08099387281946, 0.158683403528739, -1.28431658845409, 0.223246873894394, -0.494699838214966, -1.26559358718774, 1.08394834699888, 0.828088341186577, 0.108196337468257, 0.38558685467575, 0.480652090502045, -0.784113081226796, 0.724452198781507, -0.0539360213942737, -1.13092079134102, 1.08075385437449, 0.0269009463208562, 0.388756782939088, 1.08279926971293, -0.14894357746658, -0.330636426748462, 0.476938941938762, 0.0812935262547588, -0.0842732720707869, -0.0911736507510116]', 31.0); -insert into credit_card_transaction (time, features, amount) values (157944, '[0.105594051612785, 0.703077089454517, -0.328690847034737, -0.682187079645388, -0.0861378796993685, -0.313565198905864, -0.183136736480975, 0.628059185903104, 0.386986591404143, -1.29363774431946, 0.900224828758362, 0.763906945607677, -0.210321236195683, -0.893366097248943, -0.407593744762373, 1.02207620774566, 0.188579028076001, 0.964624918268661, -0.19199331175244, -0.24644719675246, -0.0603887340285353, -0.293264608984256, 0.406177975164764, 0.612798137079515, -1.20682641480751, -0.507086803089229, -0.0384005111085055, -0.005160054617516]', 19.95); -insert into credit_card_transaction (time, features, amount) values (157944, '[2.15882107276873, 0.0672033902971921, -2.46745610957006, -0.286997913078949, 0.987287139411816, -0.925136528460553, 0.704506589363936, -0.419539556456763, -0.0060082426456556, 0.188074732557845, 0.186389684363328, 0.679733592925371, 0.120249946394557, 0.925744525543234, -0.269037696793083, -0.158688303474839, -0.879099015902365, 0.261972000266964, 0.776480272122734, -0.190316941159601, 0.135103021022454, 0.513434259404438, -0.183041943693169, -0.973979138027272, 0.548543844484155, 0.283543870034046, -0.0905307651193947, -0.0987909008606479]', 4.99); -insert into credit_card_transaction (time, features, amount) values (157945, '[-0.378964511848937, 0.826849377938675, -0.683916714340929, -1.74996169087068, 1.85603070551767, -0.483341574532047, 1.66067194888337, -0.170798784997141, -0.778342401148782, -0.81830346188037, -0.011086770877865, -0.139930258272346, -0.971479480849696, 0.991653123975052, -0.829308733069321, -0.0352480560805225, -0.994535364203421, 0.354237020103077, -0.0074373443191504, -0.148893695903613, 0.231692108956715, 0.536859567938602, -0.475605140891819, -0.0847553463209244, 0.536033739382578, 0.130203141173249, 0.012593976191889, 0.102923599818434]', 24.6); -insert into credit_card_transaction (time, features, amount) values (157945, '[-0.313217955594952, 0.73747532025499, 0.45966750648723, -0.340453267413719, 0.59865698394617, -0.956593916617101, 1.02301582668903, -0.300513051001248, -0.274660334685805, -0.434122820760681, -1.04733175980579, 0.0321632366816343, 0.114594309367895, 0.172399395131392, -0.11931600673934, -0.294355305389584, -0.270491634474764, -0.610391943020039, 0.585111184091816, -0.109356005005994, -0.171266819503274, -0.443359488337592, 0.0140958882189854, -0.0958245961127248, -0.77365117926379, 0.179071073955915, 0.0205661989546631, 0.179934830072784]', 26.99); -insert into credit_card_transaction (time, features, amount) values (157946, '[2.10658433499552, -0.899434286531931, -0.877984999888084, -1.03265077789218, -0.724032863863578, -0.602462192582267, -0.672341208515899, -0.0639997775455318, -0.482232422855861, 0.919249073841108, 0.848649182371891, 0.0143281499956217, -0.21296551615959, 0.116553905808525, -0.305879426040542, 1.41899864306025, -0.149151050417918, -1.31387141470207, 1.0914498227478, 0.0055989985215785, -0.209032647860257, -0.774348324618356, 0.423174130265085, -0.466670353837505, -0.579679277076974, -0.684108963916703, -0.02103524243581, -0.0543011098382413]', 37.47); -insert into credit_card_transaction (time, features, amount) values (157947, '[-0.886016715016289, 1.37676521094932, -0.967773147172531, -0.904033884025408, 0.322858772695137, -0.269374647688134, 0.132164386455579, 0.902942499970542, -0.356171419899533, -0.38480796604756, -0.393523952634104, 0.764554241551988, 0.0866108210986516, 0.845551573490893, -1.02410273463972, 0.578351120336471, -0.640543464134904, 0.0717209241285589, 0.481366328710058, -0.0927208518264027, -0.21618508964891, -0.687300522260755, 0.0449990537437834, -1.1109991324545, -0.305811756696405, 0.198852461770972, 0.106255680250153, -0.0027566255583733]', 8.99); -insert into credit_card_transaction (time, features, amount) values (157947, '[-3.04079644739058, -2.236770540545, 0.221671143534587, -0.0223217929811176, 3.36689327699981, -1.52448292942163, 1.65245264676324, -1.70586190070209, 1.07314411119735, 0.794209586086788, -0.168956074815494, -0.547423030918042, 0.341870228912209, -2.44462270380443, 0.265810903169252, 0.133944121257501, -0.376111227882183, -0.436333649630669, 0.474778301666447, -2.0942098833859, -1.27759556866483, -0.195109489005391, 1.68154120174616, 0.557845376761826, -0.156721250881129, 0.078611137865343, -0.258690439189911, -1.45710991217636]', 1.79); -insert into credit_card_transaction (time, features, amount) values (157947, '[1.8607942516299, -0.540762000644369, -1.78069408615946, 0.476085632546504, 2.06270874946893, 4.16965961371771, -0.845752554916739, 1.07479626766169, 1.01977291183612, -0.0071215774271098, -0.541614402276259, 0.746139305286182, -0.370388649394624, -0.0621618996325374, -0.792569331100199, -0.494367868934238, -0.133430100928321, -0.999469298942959, 0.0775175617555802, -0.153063237494011, -0.507833864657946, -1.35164933118721, 0.450330143050021, 0.618057630715561, -0.293384462976927, -1.08770027024535, 0.0680708084576619, -0.0313558716761439]', 38.78); -insert into credit_card_transaction (time, features, amount) values (157948, '[2.09948742710708, -0.0723304809880295, -2.08452148675059, -0.520152956159295, 0.596570568297551, -1.02271375857664, 0.512217819561838, -0.354910915775572, -0.216298732010906, 0.271063819155825, 1.24351245140305, 0.984810216881798, 0.191941620162796, 0.817835823376287, -0.312040765470398, -0.160812422555638, -0.439005920473822, -0.458838054389003, 0.412550065172733, -0.125723367880543, 0.109359660080548, 0.348307565097075, 0.095340788520112, 0.815200867628221, 0.05608979192927, 1.29720130956434, -0.176303261775073, -0.0936412265282741]', 9.99); -insert into credit_card_transaction (time, features, amount) values (157948, '[-0.558444816726526, 1.02516109411149, 0.11585061564408, -0.641842931385032, 0.402920192709823, -1.03338293601231, 1.0365551230057, -0.314423869004569, 0.283755428912727, 0.113365296509313, -0.805620334099738, 0.16398871231851, 0.0857674997778871, -0.107885804488577, -0.308866429747884, -0.226577245095246, -0.419994285110336, -0.883678609482764, -0.133281839548949, -0.0958132770093471, -0.279363621856357, -0.493078638216871, 0.153631437270877, -0.0214390210804245, -0.54254505191404, 0.0544298113000256, -0.597997409807539, -0.406484082294649]', 9.99); -insert into credit_card_transaction (time, features, amount) values (157949, '[1.77401029907377, -0.964541473301166, 0.471470389702876, 1.66119607871983, -1.01594689476908, 1.26782693096402, -1.35782671154769, 0.408293153893965, 2.4357518644739, -0.221120039690317, -2.76182225870542, 0.63773448994186, 0.407277779996956, -1.36646829462487, -1.55528102709713, 0.0716012595424843, -0.433852312127229, 0.493508941781845, 0.216290013899203, -0.0823922580907394, 0.0957696866487306, 0.727275421454148, -0.0727016677224375, -0.965205684093965, -0.0064972251142685, -0.420145574707014, 0.122265786307215, -0.0150236979468001]', 79.5); -insert into credit_card_transaction (time, features, amount) values (157950, '[-0.423520377918017, 0.827751763827349, 0.948301268576159, -1.20928507363995, 0.320333829310019, -0.0444008599529219, 0.406071163704863, 0.0098824855236115, 0.712587553372695, -0.621659039475971, -1.74973522159798, 0.118643627542081, 0.764636326825837, -0.474384134273564, 0.320929265933132, 0.479082881079385, -1.01556340238723, 0.0956355901290112, 0.216058885550763, 0.0422920732578327, -0.236627688890152, -0.581785389944286, -0.161793290786122, -1.02145993254389, -0.0358385006275781, -0.220274198166634, -0.0008060829022785, 0.0663980010078263]', 0.77); -insert into credit_card_transaction (time, features, amount) values (157951, '[0.496037026629713, 0.65944480111628, 0.22668038602162, 1.05837304294214, -0.162900031337561, 0.631368206594806, -0.757595651202159, -1.48091716673546, -0.236372645807891, 0.522093629394776, 0.961021609917019, 0.337796040866756, -0.808596924758335, 0.803022455486797, 1.03773155684655, -0.780132452285254, 0.547147392967212, 0.438028027649036, 2.62941151283694, -0.131786434079001, 1.55033451739738, -0.349278574787741, -0.0217778029763379, 0.740996443917679, 0.274548606407144, 0.915365458808303, 0.233196440969967, 0.260685844148833]', 1.18); -insert into credit_card_transaction (time, features, amount) values (157952, '[0.0417179464419774, 0.991665811300549, -0.315676676833978, -0.589918417564405, 1.1703273966254, -0.748375845411038, 1.07304584806938, -0.169409496686861, -0.274405125870813, -1.0565427914781, -0.735179755577625, -0.0076517233896974, 0.25461376404232, -0.959900525227061, -0.32929290469182, 0.198832868820715, 0.385929856406705, -0.266800149892477, -0.190746182526778, -0.10223891267919, -0.194172906451181, -0.488502645051792, 0.158430944209381, 0.517364179975973, -1.17174831563608, -0.0031964190520522, 0.193261241754412, 0.267822880912105]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157953, '[2.06406885643051, 0.150635885588552, -1.69463987261267, 0.415752070586226, 0.436513734322261, -0.809437405166869, 0.172824186322012, -0.213169110813451, 0.488478219491403, -0.387253513691962, -0.493541758935384, 0.182626731862901, 0.0717446747231818, -0.840345400819593, 0.249198566229186, 0.250233971047554, 0.537588965601217, -0.406189945618679, -0.0281015722307661, -0.161561069166073, -0.356875855235615, -0.915522786246576, 0.349077140294913, 0.508984914116324, -0.275886527740446, 0.175238875565013, -0.0594325449988992, -0.030700485371586]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157953, '[0.714940572199113, -3.14668263623907, -1.34434487660362, 0.217049747142615, -1.56005133529814, 0.301011658371958, -0.0488747600953272, 0.0439457304276764, 0.126920201375223, 0.465165165688082, 0.321647290647655, 0.194042720768047, -1.35226912355935, 0.463556765165538, -0.545864333206366, -1.35919762120867, -0.107326869757454, 1.50118620927985, -0.496764743355698, 0.687190515731497, -0.302260626621068, -1.92147881169346, -0.0435509802378034, 0.590779965747819, -0.870201179977087, -0.867746078635534, -0.0945408734752064, 0.0839035920931845]', 700.4); -insert into credit_card_transaction (time, features, amount) values (157954, '[0.155418307516308, 1.06706434723187, -0.48481027577188, -0.595345271948942, 1.05995324376574, -0.69618112444826, 1.02719156490691, -0.134820316180118, -0.130704881846982, -0.855978375030594, -0.773260307513653, 0.148318348731243, 0.679235782005899, -1.15591524647323, -0.293050756379983, 0.36486091932644, 0.252055949109237, -0.222681079951058, -0.153624697657035, 0.0749240763359663, -0.346126150982433, -0.8223736016878, 0.0705879624032651, 0.386768119529358, -0.369429957544625, 0.123170670555335, 0.224879452927972, 0.083855946494632]', 6.99); -insert into credit_card_transaction (time, features, amount) values (157954, '[-0.196502757734091, 1.16898915678427, -0.849597998100463, -0.509445858436981, 0.511294864528861, -0.85440863008484, 0.541155971886057, 0.399803873512338, -0.0019894003933657, -1.02216226206132, -1.17181220211394, -0.726982413256965, -1.28736000983712, -0.433439881473624, -0.118932597226696, 0.551503052980536, 0.572686532779407, 0.0294828625111178, -0.184168060374324, -0.160983721261086, -0.318611723597352, -0.979355941307693, 0.168741647778025, 0.433562019792299, -0.425941530016154, 0.125898939143942, 0.0856947812225393, 0.0178164666878912]', 10.06); -insert into credit_card_transaction (time, features, amount) values (157956, '[0.0377772803522289, 0.70962218327457, 0.0864418754332224, -0.800975092723469, 0.569095784878146, -0.557730600670006, 0.809661890486252, 0.0474975725899271, -0.064148208054088, -0.201476531495999, 0.112354291836447, -0.0606904076434513, -1.36287933759573, 0.553051806748703, -0.918675698124949, 0.306447342008864, -0.754113779140093, 0.0703189871241063, 0.394262288253137, -0.101714862122309, -0.256401448714307, -0.65855332774574, 0.0135945303269278, -0.537100794157204, -0.502521253462503, 0.154945695942483, 0.233993514328793, 0.0793502352551405]', 3.08); -insert into credit_card_transaction (time, features, amount) values (157957, '[-1.1533613827591, 0.932987101708906, 0.48045437717297, -0.870664604454561, 1.15532047793528, -0.272714026478393, 0.653182141793233, 0.341698259938587, -0.832812406520562, -1.1585319859078, -1.60089314184079, 0.237305386151913, 0.896601615072072, 0.30486901147015, -0.198617376087359, 0.160272508089655, -0.431583996078477, -0.464461210289953, 0.497237386445524, 0.035288240450506, -0.258800648208347, -1.00785916201138, -0.330518975359237, 0.0592199476554792, 0.652257881414818, 0.33950538883829, -0.162612073504426, -0.0771535111803993]', 3.59); -insert into credit_card_transaction (time, features, amount) values (157957, '[2.2180935602798, -1.53035153822686, -0.317128421398909, -1.46561865678762, -1.75563905259586, -0.690470025280416, -1.40183164203569, -0.13050866808013, -0.892344207175662, 1.5027266981516, -1.10143004252507, -0.737906927183276, 0.53962226703376, -0.649660619510824, 0.0979250652193446, -0.17015743484654, 0.313826503900443, -0.0380751087507016, -0.133131167343187, -0.377336804247485, -0.351987830707386, -0.578394351495228, 0.405817594026537, -0.173512728876944, -0.591207504129514, -0.438335884957371, 0.0377173735606557, -0.0308092751175787]', 40.0); -insert into credit_card_transaction (time, features, amount) values (157957, '[-1.82881711077753, 2.11312659067489, -2.70565184336161, -0.54153561530829, 0.731924581784389, -0.374141156646679, 0.15535042930654, 0.927011680491262, -0.527661852500732, -0.551689726799319, -0.107838426519603, 0.934997174046555, 0.567860760022302, -0.265117418402258, -1.45447591940341, 0.591221396737469, 0.564917860578733, 0.658942234065919, 0.383968912323998, -0.478203261993345, 0.130738242552403, -0.018221886983316, -0.0412233035868095, -0.199102001432269, 0.132807536795369, 0.240592185964573, -1.07951201656348, -0.106838544641023]', 14.95); -insert into credit_card_transaction (time, features, amount) values (157958, '[-4.02657350667, -5.13560536462968, -1.5864618861875, 0.0941755372627182, 0.974338929331611, -0.966912739299797, 0.244006478523435, 0.528526651618191, -1.30475522306458, -0.0350002009185114, -0.385043193117391, -0.0986670882749319, -0.317581123418741, 1.07350350509879, -0.195445048951483, -1.34910305933578, -0.329507186230072, 2.77815919288323, -0.354919578805565, 1.95093331041854, 0.780323837289314, 0.346111473754255, 1.22927528135008, 0.14114986513322, -0.151104723972879, -0.12736453442329, 0.199719304433133, -0.342208805188658]', 622.0); -insert into credit_card_transaction (time, features, amount) values (157959, '[1.91953715091255, -0.471146959708282, -0.320106645181777, 0.601097301413454, -0.835077125809063, -0.734047928354754, -0.518424895960432, -0.0957156123104241, 1.07059091091028, 0.0907413834248014, -0.868845943698411, 0.100389024563389, -0.106496000192297, 0.0037175001806409, 0.885153359040691, 0.529199247915558, -0.656365226688879, 0.16559305974002, -0.486358526050581, -0.136452357176805, 0.210846112570921, 0.652100651225731, 0.148336542646621, 0.0772832556770693, -0.312687840507206, 0.350449133613549, -0.0224136341360181, -0.0373309252509812]', 47.2); -insert into credit_card_transaction (time, features, amount) values (157960, '[-0.0167360401228981, 0.810738944735208, 0.355029310089414, -0.676065908875726, 0.440162878835009, -0.857533498939415, 0.916115351854028, -0.0736257898032115, -0.330993667562361, -0.246225940656005, 0.879015707445893, 0.932000089670094, 0.0494625929457461, 0.28743401008896, -1.12529848962295, 0.069387888935094, -0.633282014640039, -0.2996954348626, 0.169315109125263, -0.0152865792779525, -0.19921028254512, -0.431198443657408, 0.0727977822393492, 0.0741640559815099, -0.525949544897579, 0.114541701178317, 0.243445371604533, 0.0888514582812736]', 4.49); -insert into credit_card_transaction (time, features, amount) values (157961, '[-0.288430758943871, 1.1761184792378, -0.274976284059367, -0.487969202837398, 0.380054252799194, -0.996524999108536, 0.820886750713392, -0.0051980429193138, -0.266273361801721, -0.0182501803760934, 0.832854461447437, 0.846211681348274, 0.13430664824925, 0.659119532552508, -0.276540910368016, -0.25971396022472, -0.642692576994192, 0.602162377021445, 0.292947547820401, -0.0566156281481256, 0.438254825919884, 1.50260277667472, -0.121849611352243, 0.121701483434302, -0.842153712356565, -0.28523646197213, 0.0813906084501782, 0.0266894948907803]', 0.99); -insert into credit_card_transaction (time, features, amount) values (157961, '[2.09290324082901, -0.730497275359928, -1.50531614308008, -0.543655223555024, -0.269337145186302, -0.592985462827389, -0.214852690835621, -0.165536108814146, -0.817315789199893, 1.06254472540993, 0.63240086627314, 0.433252390015448, -0.338430538278368, 0.527780119751134, -0.801942781219551, -1.52964058287603, -0.186471294628776, 1.07624581460366, -0.309604254558122, -0.554345241954112, -0.465126769858491, -0.900308326429664, 0.310258392841819, 0.739283254021243, -0.262809067567763, 0.423214015772059, -0.0867210143559728, -0.0628768414644909]', 37.9); -insert into credit_card_transaction (time, features, amount) values (157961, '[1.98651690903976, -0.139920953249173, -1.22167073159544, 1.10572731956866, 0.380750700607988, 0.159883856957599, -0.121391119674426, -0.0291394706956704, 0.740649189462826, 0.204143454685721, -1.67260884543788, -0.0618065517600697, -0.033166497338101, 0.145482938341498, 0.326379639625274, 0.183373879224712, -0.756952042628467, 0.201046317285517, -0.284100890073826, -0.173399734571779, 0.120733016065792, 0.449711546875324, 0.0016483431145024, -0.0361652431070216, 0.227096215905187, -0.511281513506969, 0.0211840151418421, -0.0386575984148595]', 35.0); -insert into credit_card_transaction (time, features, amount) values (157963, '[1.92586657185659, -0.529199897825763, -0.145934081922038, 0.407499013270104, -0.852249746320965, -0.253461272631271, -0.783740706196698, 0.121908830054698, 1.04034849985091, 0.175818146958595, 0.796274705305816, 0.950495068631654, -0.235514764413005, 0.0016555673681376, -0.282653116738965, 0.441921138342107, -0.628450030537591, 0.405241925340875, -0.0812666600594878, -0.204680555384908, 0.222583252125102, 0.820361857130425, 0.171198417328548, 0.0689213514847251, -0.348035094063476, 0.549624539782602, -0.0217428139219938, -0.0568157268137682]', 11.5); -insert into credit_card_transaction (time, features, amount) values (157963, '[2.00197341186197, -0.0172307442925724, -1.64275823561917, 0.366268061048751, 0.2460725341237, -0.694711143797763, 0.0003371610921903, -0.0222232977718137, 0.437400782277952, -0.171344087115177, 1.05423556519694, 0.135601556549636, -1.4841644910807, -0.349638172636094, -0.35073834928678, 0.526481044376817, 0.372939483126367, 0.303997272438385, 0.278840412835517, -0.225970933401332, -0.312090235909307, -0.919347783750754, 0.360463204469865, 0.631000460271372, -0.364709537527224, 0.146498823595791, -0.0771886251285026, -0.0403737012696964]', 9.99); -insert into credit_card_transaction (time, features, amount) values (157963, '[2.23329085170967, -1.69144957004062, -2.38852352523168, -2.57775518701614, 1.14357603227901, 3.44120524904476, -1.59216074049841, 0.792470005925062, -1.40654405612625, 1.58306681617355, -0.219105097606072, -0.72149325368834, 0.319497581175934, -0.199904882985085, 0.190592814035743, -0.705043949806864, 0.436370723424263, -0.28236885133011, -0.267079526457362, -0.307510351202207, -0.153174906605346, -0.0879417958761224, 0.24366905982448, 0.688319130860332, -0.138447433908701, -0.143262405698555, 0.0234166575446106, -0.0528976874640977]', 42.76); -insert into credit_card_transaction (time, features, amount) values (157963, '[2.06061496870053, -0.156284236095448, -1.09142693069339, 0.432823959876221, -0.279383963397353, -1.25404226803778, 0.0852441350379371, -0.25214813872615, 0.763319834145534, 0.116429050236064, -0.983629963233745, -0.339603746069908, -1.40631030793986, 0.568260569676601, 0.200508182190628, -0.0389018268800775, -0.200895232220781, -0.692343078840531, 0.152684097703824, -0.318815489395252, -0.305571856906352, -0.817737025228242, 0.358951935447387, 0.0060955699278855, -0.349269370803907, 0.200305251874558, -0.0803223083692439, -0.0630019181852741]', 1.79); -insert into credit_card_transaction (time, features, amount) values (157964, '[-0.683709087568444, 0.296121340959055, -0.0955113777931461, -1.2550420516208, 1.7980614388856, -1.07052776194258, 0.723038003165735, 0.0645548494880929, -0.304991075599898, -1.19891304728934, 0.864145353564404, 0.429619901952159, -0.673540572341577, -0.668428435856265, -1.6088100795599, 0.828233303204743, -0.190711716532288, 0.137954253253225, -1.12743751521058, -0.132893476778697, -0.117760205640354, -0.584333003295222, 0.20305618239447, 0.58267152100511, -0.875528720569339, -0.18218308689086, 0.103228961477245, 0.236036279574716]', 0.99); -insert into credit_card_transaction (time, features, amount) values (157964, '[2.02130568911583, -0.106107709910944, -1.20084756442329, 0.281772587584589, -0.121881897198451, -1.07775051389328, 0.0659526767523445, -0.21512396209524, 0.457800287680914, 0.1975893681161, 0.98272077547269, 0.708544100597675, -0.602225929242185, 0.774793782408752, 0.131014026070172, 0.0167631777718205, -0.70461822143883, 0.513506321629264, 0.0033918647002959, -0.274404744385071, 0.310342814099609, 1.00210823602601, 0.0063998012102415, 0.0998522895067879, 0.191878317094332, -0.125108888402155, -0.0235576952413561, -0.0680629970014868]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157964, '[1.94366108760167, 0.0703544863727542, -0.234683907704162, 1.213840155994, -0.273840024699517, -0.388226066015964, -0.298323876406533, -0.0644292612161531, 0.484245148416809, 0.185720446368747, -0.192325810062568, 0.973848991690798, 1.1882329159931, -0.0289223593377505, 0.947882302676674, 0.410145675180216, -0.755566268841414, -0.338091720088588, -0.824687681992613, -0.167115353117578, -0.102525251501971, -0.232049153569127, 0.459978035806903, 1.03121996132453, -0.423349117850612, -1.0229454956366, 0.0552017116479644, -0.0114940290400824]', 5.0); -insert into credit_card_transaction (time, features, amount) values (157965, '[0.0618368245157055, 0.4483744464616, 1.04829352135028, -0.689349628492269, 0.027718517500259, -0.139601613945344, 0.256464318295674, 0.176728361401527, 0.386447036418693, -0.666355004345517, 0.340995702239376, 0.60887760941688, -0.346742018435612, 0.0838006682968273, -0.438480531382187, 0.518189637476565, -1.00700481776491, 0.577671547860521, 0.139963577180324, -0.188523239862826, -0.0775430078048705, -0.188789911476871, 0.0603362051988515, -0.394962657111677, -0.679616108439498, -0.695610561994836, 0.102996861051272, 0.0501463876644225]', 6.95); -insert into credit_card_transaction (time, features, amount) values (157966, '[-8.20861607046392, 7.37438337575459, -7.27861422233577, -1.58731815284072, -2.54426450916029, -1.46068366809213, -2.4790315506221, 4.01317742453994, 1.67973389284029, 3.77148782546918, -0.208375008960203, 1.8976982770544, 0.349559564072912, 1.10875832305077, -0.679037513878558, 1.18956829557332, 1.49829449008219, 0.584858967553385, -0.657513312446231, 1.1255989106054, 0.0926279389971332, -0.322768577173434, 0.729107876787504, 0.0616525555932529, 0.431632698418571, 0.315398120433926, -0.317099171194962, 0.671549730637482]', 9.91); -insert into credit_card_transaction (time, features, amount) values (157966, '[2.03074519293165, -1.82421226674575, -0.842893521766777, -1.3591542575788, -1.64055091794564, -0.816550692012471, -1.0341445802757, -0.228270578295579, -1.03773647555012, 1.50661258175424, -1.10245293885893, -0.999853874525731, 0.0215815259605607, -0.378167815989221, -0.0100557220788719, -0.504199364188025, 0.532745175777142, -0.0375582081079738, -0.271434439059458, -0.211618019875968, -0.0841071148614551, -0.0147917204142604, 0.144424327215541, -0.109219880883719, -0.321099113164504, -0.182734933012596, -0.0028958577287816, -0.0261790050932126]', 144.4); -insert into credit_card_transaction (time, features, amount) values (157967, '[-1.3784842823001, 0.836253834230049, 1.63717317041987, -1.20071491939441, 0.527644893227459, -1.77579789806105, 1.25498691340279, -0.354095145686627, -0.402204168980457, -1.02661290907531, -0.153022395433992, 0.446609211033295, -0.0676794093851433, 0.0222814426804166, -0.969469984042873, 0.0121020226413929, -0.43827060073736, -1.19207121977984, -1.32918557326521, -0.322040407099317, -0.22033880481446, -0.734717698602182, -0.180544963056035, 0.932185359473056, 0.535121113540519, 0.0597898872485901, -0.333964586234657, 0.0766867456795813]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157968, '[-1.24653037207163, 1.61597217458955, 0.244828166687947, -1.13583620890234, 0.290600998547033, -0.277997466652597, 0.208438651740384, 0.437277772839563, 0.553872373950403, -1.11505185844921, -1.53997855517165, 0.0067690854324076, 0.740821830023757, -1.42730475314938, 0.413160125865243, 0.91978816710802, 0.115996718396721, 0.686650231945729, 0.0798408241824044, 0.12430123539442, -0.264394638855443, -0.719232726523527, -0.166029629130133, -1.12622350196224, -0.0570402514170426, -0.217427583838379, 0.0832706734666287, 0.209989193164973]', 0.77); -insert into credit_card_transaction (time, features, amount) values (157968, '[-2.80578689320652, 3.18227555712877, -1.47614502675081, -1.53660983322885, 0.141134715594812, -2.47624569791166, 1.81158285016513, -0.621928403233836, 2.20391805995782, 3.65204796924155, 0.156020230434811, -0.219408848739783, -1.21050585621525, -0.225078188425433, 0.0632504934267331, -1.27663910838827, -0.278438787722901, -0.82023297146283, -0.825669868224927, 1.50573809404652, -0.168393595649716, 0.832980234782807, -0.0583151977485832, 0.91537600363269, 0.107405315360701, 0.0036909808853293, 1.02379478709671, 0.292022168207763]', 0.77); -insert into credit_card_transaction (time, features, amount) values (157968, '[-3.32785612880507, 3.74284510416295, 0.102989548867145, 3.97111691483664, -0.728104965006497, 3.79597592120345, -4.29874619762918, -8.58254391834837, -1.09042034656957, 1.79912538035272, -0.594137276188149, -0.15270804588819, -1.85649493482985, 1.23201794284558, 0.0014976443443785, 0.765055733710974, 0.656003827904937, 1.53779613655893, 1.07317578536359, -0.704741094863117, 5.90984726047862, -1.15689810111434, 1.16848513492925, 0.0298377843500019, -0.567869957203603, 0.468192279368689, 0.484931877775832, 0.294533594512196]', 7.75); -insert into credit_card_transaction (time, features, amount) values (157969, '[1.83888766917069, -0.0764128151632818, -1.91552240711566, 0.589749279799011, 0.251281511505436, -1.30615268042018, 0.474585548635681, -0.441664967747948, 0.447131099126887, -0.601661262658675, -0.253432849433953, 0.493651440339286, 0.930408803323264, -0.988655718223063, 0.883178547264484, 0.19578891969138, 0.42828357631568, 0.420531050493752, -0.503419484606504, 0.0850612676544874, 0.264941175479925, 0.734106150308426, -0.145991179407594, -0.212111048038646, 0.247577074495147, -0.103751822866401, -0.0138415781165598, -0.0091967906204431]', 117.54); -insert into credit_card_transaction (time, features, amount) values (157970, '[1.99906299189977, -0.182999504001492, -1.41118544263677, 0.17129269748625, 0.142312903104677, -0.618549789669981, 0.0267283870013384, -0.115330456666407, 0.45939086039813, 0.183746195372574, 0.898934223749624, 0.604277946676819, -0.650047353156469, 0.777154534868393, 0.191082906139417, 0.0677892325764169, -0.74495448692418, 0.582858789277018, 0.0318782089146311, -0.208511029149992, 0.311209711200393, 0.917589129172324, 0.019334819169837, 0.783955514081871, 0.208751363202549, -0.157442177067247, -0.0327373137870122, -0.0584867539139868]', 19.95); -insert into credit_card_transaction (time, features, amount) values (157973, '[-0.964697326988786, 1.41240741952048, 0.317744622511331, 0.640112635012405, 0.672533533660404, 0.0832064691547012, 0.922455970627585, -0.103988682643461, 0.577303800940569, 1.43903553953967, 0.0691064181769118, 0.194498194238766, -0.652630172459585, -0.217654061733043, -0.993600691000042, -0.800421001015771, -0.448893335028301, 0.601793037202568, 1.1559904295511, 0.523317155288731, -0.0308664772711088, 0.888297928902851, -0.366397755654084, -0.489442935283755, 0.0277478050148657, -0.401094304549291, 0.17191200784603, -0.297837266020055]', 5.0); -insert into credit_card_transaction (time, features, amount) values (157973, '[0.896239917425564, -2.3524076549197, -1.09776116060742, -0.0536660982707264, -1.32098979070395, -0.512299813897651, 0.277680586957759, -0.169480141078878, 1.11208257624998, -0.471410049385005, 0.982463638752311, 1.4066503863401, 0.0216716761713687, 0.191734635425939, -0.595136392285055, 0.129464931569796, -0.32928816935155, -0.313355953724628, 0.691015763444587, 0.974251588541518, -0.0388073775816171, -1.2387639008878, -0.0153672863972512, 0.112121008085071, -0.916627170365452, 0.308516962925865, -0.17090229324426, 0.0369939533772284]', 572.84); -insert into credit_card_transaction (time, features, amount) values (157973, '[-0.773645036856289, 1.14187839052569, -2.00940865038627, -1.87509281164653, 3.26322750501122, 3.13732617124828, 0.876309721177129, 0.375236025125563, 0.765330580112903, 0.921625349615873, 0.48336524899578, -0.597282768638666, -0.369529597464575, -1.48685750262332, 0.870007051112978, 0.117532727040786, -0.0878655833859465, 0.192498517247581, -0.899118828825117, 0.552102325160159, -0.0467304889982395, 0.724459417401952, -0.192384890643433, 0.651937193841015, -0.270887785737543, 0.493429791322173, -0.25446941428238, -0.599785151013234]', 28.21); -insert into credit_card_transaction (time, features, amount) values (157973, '[2.03536273310752, -0.943719083880541, -1.6543236034095, -1.12360489314325, -0.369077687889891, -0.896880377877599, -0.0853312327084431, -0.306179388538316, -0.967566809935332, 0.998889513736933, 0.666910758864691, 0.549159250972956, 0.385138853715296, 0.546512740454178, -0.18584784488346, -1.20046824382935, -0.422553520043883, 0.980838397363322, -0.212556147899113, -0.385025651205767, -0.473531876927823, -1.07479683932682, 0.25306790939445, -0.455122496945265, -0.48017084553966, 1.02592757733018, -0.137747205086342, -0.070883453110854]', 93.0); -insert into credit_card_transaction (time, features, amount) values (157973, '[-1.2231026879908, 0.747107929053307, 2.80214650407355, 3.99627623969058, 0.357225429950914, 2.1725594914511, -0.390945064091217, 0.405706616293283, -0.491755197952139, 2.65627889114601, -0.186385481189706, -1.60905952691208, -1.63618327367767, -0.484837363250144, 1.12867741863864, 0.878685400346291, -0.749518725460162, 1.79198609953037, 1.39285173420542, 0.50646901803822, -0.0762430850511763, 0.611070310549528, -0.0051384965965158, 0.0282711363089857, 0.152619508290004, 0.531819296340161, 0.391843575457727, -0.233223744015689]', 18.15); -insert into credit_card_transaction (time, features, amount) values (157974, '[-0.688928417572515, 0.52099901390324, 0.395567619354803, -0.331300364117948, 1.39362783310617, -0.622543630287477, 0.565202622116405, 0.130661531453614, -0.61684536408945, -0.878499649972557, 0.997136930107938, -0.085437364104921, -1.21433079640909, -0.449622649788725, -0.404991670390028, 0.208240284489818, 0.549792261933334, 0.413011220123731, 0.658948663453891, 0.0734436553507974, -0.205214246670432, -0.793544288280305, -0.0106664964016563, 0.588260901841865, -0.245564503640268, 0.243204839633853, 0.0371667603083719, 0.146906238567966]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157976, '[2.05255860617653, -0.146485271082057, -1.0913619403651, 0.42071438983787, -0.220140821205693, -1.15780974843096, 0.0882087281638287, -0.240576393541553, 0.722779520810923, 0.100263684633919, -0.89650587948911, -0.183419730186877, -1.1470175075041, 0.521322003721498, 0.219834254413959, -0.107161052887001, -0.1627070902376, -0.810463735724028, 0.0823848993445511, -0.308032392564461, -0.297267263550314, -0.774323258046133, 0.361433079793668, -0.0462712968190888, -0.354289984806009, 0.205107453833142, -0.0754499268192803, -0.0630899877827614]', 1.79); -insert into credit_card_transaction (time, features, amount) values (157976, '[1.95902759736612, -0.133766212551384, -0.869202857218849, 0.111340955201187, -0.157188983100066, -0.197125238276084, -0.57122878629977, 0.13833885858806, 0.949763158412604, -0.563658170249103, 1.40817056111254, 1.15663758717233, 0.321211851585402, -1.17641972357424, 0.153946566289958, 0.747368682978227, 0.220958829236181, 0.652766691730082, 0.0670623633560689, -0.129696144276046, -0.20708937652179, -0.471969775505063, 0.403459391312989, 0.581554287808335, -0.516300356368384, -0.334192792482777, 0.0221991324256461, -0.0126040789588429]', 0.77); -insert into credit_card_transaction (time, features, amount) values (157976, '[-2.66383205908704, 0.174647496723316, 2.11245438541986, 4.51203303814439, -0.520728886617058, 1.50565562360304, 0.0284231801402955, 0.368720147951529, -0.260473043667203, 2.52234222111307, -1.76959789252947, -1.66403270284149, -0.564439767882363, -0.661016234185204, 1.78953233942014, 0.869842683271945, -0.42794206813361, 1.1634192063946, 1.13521894413423, -0.0003465240527101, -0.322476804007028, 0.670453093518308, 0.502409326852764, -0.601407228296095, 0.428083813958631, 0.628127647596657, 0.661857951182953, -0.275026934135342]', 174.6); -insert into credit_card_transaction (time, features, amount) values (157977, '[-0.745517800584415, 1.48280525331285, -0.987091490228214, -1.28141472894969, 0.865436916990643, -1.5046921777319, 1.4916251334676, -0.235320134468621, 0.103140170151472, 0.647988136404069, 0.757329236023915, -0.0617024406297733, -1.71943731917457, 0.984448574219067, -0.649475788029373, -0.555900121039057, -0.513164650122404, 0.109545096436624, -0.0303703315452879, 0.218888229966171, 0.203379493314934, 0.906310389151378, -0.182634344980966, 0.0231816475550947, -0.253059055927106, 0.0871014257313095, 0.700361236264471, 0.442312947133834]', 0.15); -insert into credit_card_transaction (time, features, amount) values (157977, '[-2.99301653467851, 2.29490924392415, 1.98918498607115, 3.83052499870375, -0.392687116576311, 1.50772049443603, -0.483294472730568, 0.434057551711502, 0.924517829992485, 4.62133005658301, -1.22245913790506, -1.47827211800812, -0.622738361654396, -1.21444578536491, 1.80050666717643, 0.415035298030138, -0.383297527182699, 0.900670634466261, 0.687245561219846, 1.38455285253594, -0.310005896107521, 0.425598385458306, -0.531065600998571, 0.543647263529668, 0.36163297872204, 0.499858522066366, 0.789114965482187, 0.0533434675252892]', 18.15); -insert into credit_card_transaction (time, features, amount) values (157977, '[-0.661593711822078, 0.652793423475606, 0.7673908873748, -0.606041778157361, 1.40739059966363, -1.2556945740505, 1.96355758509504, -2.56736973479898, 1.16884489287547, 0.677118757460659, 0.406201562086944, -0.896522251183681, -0.841017956570658, -2.16037242723745, 0.816026837925164, -0.43528020829686, -0.0744183346191714, 0.26507889395609, -0.810455329336394, -0.129294645207376, 0.73764004562111, 0.681506765324107, -0.314302195307962, 0.302195877665518, 0.281824623896969, -0.339694125950599, -1.70572620737748, -1.09107489559943]', 8.6); -insert into credit_card_transaction (time, features, amount) values (157977, '[-0.890719367974028, 1.37084429023364, -0.296669602897132, -0.993757582426446, 0.368370299867898, -0.686870802913754, 0.766229821121271, 0.0826705604294247, 0.685632517923621, 1.03123275061918, 0.290090616041666, 0.0360645619834591, -1.31930082364347, 0.264438250192654, -0.86949543196661, 0.195337341623331, -0.7624748554422, -0.0283915466226299, 0.242330694479769, 0.410957294622519, -0.371288575262615, -0.724627709889998, 0.0907228117984926, -0.466184143965356, -0.29930323241112, 0.16799226402743, 0.64474601567674, 0.349551873089223]', 2.69); -insert into credit_card_transaction (time, features, amount) values (157977, '[1.82325499195386, 0.19622352726535, -0.11935235707208, 3.62620320746891, 0.573495535185885, 1.79681532344717, -0.501690293526354, 0.394622872162896, -0.459783497446441, 1.29552595513065, -0.446200520787739, 1.36698946963065, 1.51713164579045, -0.672789746850831, -2.62440287030406, 1.00977208070635, -1.05743830841439, -0.272972863692372, -0.521953696778539, -0.106977397750954, -0.369304399521242, -0.889433673932337, 0.327546338061398, -0.248345886348167, -0.348104763227304, -0.412827696020526, 0.0207524755124976, -0.0336437819003199]', 26.47); -insert into credit_card_transaction (time, features, amount) values (157978, '[-0.666067754181954, 1.18819791522328, 0.311066547972187, -0.374017287707467, 0.516044074148531, -0.301691499397619, 0.80992397446302, 0.0482586188691898, -0.156417828254936, 0.28019302509348, 0.6889287221767, -0.406857836977868, -1.70949565200734, 0.847823975052059, 0.58010173439227, -0.436476684801031, -0.319676483862379, 0.929367317338259, 1.07758737140569, 0.191012188096813, 0.277619435010711, 0.90350995007144, -0.375449413549478, 0.7636470160597, 0.316156815676701, 0.0403100759112164, 0.318440459403248, 0.241267991241012]', 7.99); -insert into credit_card_transaction (time, features, amount) values (157978, '[-0.462584526224977, 0.74980261149664, -1.01508453157879, 0.0471592679975883, 0.918350659413925, -0.846999475015829, 0.4355738020709, 0.16722179466712, -0.0780622681935225, -1.08599154534344, -1.43280450884057, 0.250677382842168, 0.782693910771039, -1.1629523038356, -0.76490146091398, -0.0950920608610851, 0.89819571376613, 0.239944985049191, 0.386180275585579, -0.161847461013527, 0.202388589803986, 0.753929336889137, -0.0711966664037763, -0.635777010745609, -0.287629921024362, 0.704843516717623, -0.140024528649442, 0.0270525121906098]', 5.69); -insert into credit_card_transaction (time, features, amount) values (157979, '[2.00442329518763, -0.103757942606191, -2.02206078759673, 0.493910355657102, 0.296153933286302, -1.53910924067694, 0.740031396852728, -0.486761152292382, 0.535016096820338, 0.001424060861036, -0.985286725012501, -0.213285685381904, -1.32059707246963, 0.89669973267183, -0.0331943825254506, -0.894092036588173, 0.0210925545466615, -0.516037751233991, 0.0806101229238717, -0.258495155808709, 0.152985422284505, 0.529285106239231, -0.0977007381687096, 0.0091200322090107, 0.490317362656807, -0.0664916908535324, -0.0655705897062785, -0.0693121098769825]', 50.0); -insert into credit_card_transaction (time, features, amount) values (157979, '[1.92666675492338, -0.195582478342884, -1.17826293848127, 0.238473764956231, 0.508606096230559, 0.350103136695233, -0.0557243483417705, 0.107414532314776, 0.505204557931785, -0.0752001297508144, -0.0480394705165628, 0.794246688733908, 0.199331878944025, 0.326012387379621, 0.840272043822156, -1.04344266830493, 0.580458884801121, -2.32702012885371, -0.992919471009605, -0.312833762940224, -0.201582849105492, -0.324585991677623, 0.425714010351967, -1.02830422375004, -0.519722026843405, 0.295394250122115, -0.0162052054596585, -0.0711881360104416]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157980, '[-1.61297691007714, 1.56104420562487, 0.748769507905986, -0.993980974046741, 0.126316760589102, 0.283377439558068, -0.162779713371469, -0.913077734158791, -0.458297961851394, -0.627040582657327, 0.46751348110298, 0.312584660367103, -1.09484198169594, 0.758289258416562, -0.617531945652306, 0.287521058187268, -0.223316086482307, 0.29843455483529, 0.131557372829886, -0.391505520770848, 1.53766889713242, -0.57742478319376, -0.118904999269506, 0.686669242741798, 0.679646169784791, 0.557079975757182, 0.145107669563328, 0.051238754166178]', 3.59); -insert into credit_card_transaction (time, features, amount) values (157980, '[1.94575336427642, -1.10746611063971, -0.38161402794336, -0.266821928565136, -1.32610828898409, -0.749354577663574, -0.745672665731535, -0.144669424091363, -0.0129254778314704, 0.773805669913565, -1.01501425895293, 0.0320462724809392, 0.260857726053945, -0.15606274123976, 0.388821724832114, -1.07884244765892, -0.224936714930868, 0.871012493723425, -0.827646651099286, -0.430201391688745, -0.573028442322667, -1.28328081191214, 0.45058302463433, -0.0089054532443411, -0.796885802682008, 0.222794674116536, -0.0309006496499365, -0.0237329612937065]', 96.0); -insert into credit_card_transaction (time, features, amount) values (157980, '[1.87184930947792, -0.259915838579638, -2.54104246908075, 0.177836240074178, 0.778426112810201, -0.535660063214527, 0.419192095398964, -0.178353484440636, 0.132389738566986, -0.221411927841926, 0.634866606916482, 0.0643745711098544, -0.727815293623028, -0.437267074972362, -0.203059123566239, 0.61236047665476, 0.198037174417328, 0.768672979084602, 0.323025256602774, 0.0734234274875721, 0.0562649931241585, -0.0553143629936731, -0.0853529003818045, 0.0359183772413752, 0.0954082854036176, 0.671223854473251, -0.124085298098747, -0.0384948090849152]', 122.0); -insert into credit_card_transaction (time, features, amount) values (157980, '[-0.297038125811158, 0.762610438101774, 0.730339890280684, -0.596276261475649, 0.615714601295896, -1.12566428119967, 1.03930759137958, -0.227584485706682, -0.317098420128097, -0.702442833356434, -1.00172687761946, -0.0750492055055783, -0.273768606535085, 0.247807207178697, -0.338469149433701, -0.158404063215292, -0.333861519089508, -0.668446522429342, 0.100800293527853, -0.120964948204753, -0.188363961228007, -0.535614912774125, -0.0176234596026, 0.0428371776117388, -0.516012917906981, 0.150407374551543, 0.0842337861392922, 0.159141028830275]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157981, '[1.86926884946311, 0.413058711140049, -0.572303743423866, 3.7604492874234, 0.218277694004166, -0.0405909268757412, 0.0284560119484586, 0.0190435833520761, -0.991206135710436, 1.66524869677438, 0.329371574217789, 0.0311256547437708, -0.878857968792483, 0.526688978922034, -1.4702065703776, 0.912528325484498, -0.921608557841306, 0.356867398453975, -1.38365728980941, -0.328716244875331, 0.338361480774963, 1.00800215203024, -0.0004779004906996, 0.0701951008988325, 0.146426465546607, 0.220831410102284, -0.0430859143860707, -0.062346108810627]', 10.62); -insert into credit_card_transaction (time, features, amount) values (157981, '[0.206060594953811, 0.807815773425009, 0.769807708980104, 2.41107272681782, -0.0917582319751275, -0.776406818271336, 0.572877006997071, -0.18775055589271, -0.358332025591123, 0.307231218582176, -0.477880868581443, -0.138682849846432, -0.877309754605858, 0.450803643362897, 0.44343798106244, -1.99696931449746, 1.18821908834196, -0.0708335785398571, 2.06098119594949, 0.0750030647814684, 0.389942538651507, 1.47005256021261, -0.0715339655219718, 0.91708637455169, -0.753174959470877, -0.116267216186615, 0.315513952991209, 0.252121847375306]', 10.0); -insert into credit_card_transaction (time, features, amount) values (157981, '[2.02436237603537, -0.293730788550126, -2.08411219154586, 0.121534138179134, 0.670296415672217, -0.227201023315928, 0.271028793534234, -0.0844098921308814, 0.363953056051184, 0.289564356796266, 0.0238461231945178, 0.0394588634398212, -1.5069048219135, 0.854261674667014, -0.84714069480227, -0.143876083822952, -0.441334312016314, -0.0116841999157678, 0.669983520000323, -0.203029062441929, -0.0212187036159191, -0.0598477695060261, 0.0140094625483717, 0.0543326869656147, 0.177283920207652, 0.553323077445849, -0.119150398247176, -0.0839871028600665]', 39.95); -insert into credit_card_transaction (time, features, amount) values (157982, '[1.03454846822727, 0.915873955029731, -0.778864844472036, 1.166481929245, 0.827127599192127, -0.273605125167718, 0.731468634595371, -0.474851711119359, -0.184661164380683, 0.230231303659996, -0.404474446770238, 0.129227567034488, 1.18580843506561, -1.22244286123264, 1.23599123409444, -0.796675003349985, 1.12357016816963, 0.0541532284841868, 2.60387364690589, 0.302229671207166, -0.257466115784235, -0.35618742097819, 0.287616617200605, 0.429186323516502, -1.50328057885806, 0.382681936043292, -0.154550355993643, -0.1224949312475]', 5.99); -insert into credit_card_transaction (time, features, amount) values (157983, '[-0.130366442031847, 0.712577670059276, -0.297719730900554, -1.0054853332461, 1.22166908103954, -0.0659941373862591, 0.849569199725631, -0.0177541513489372, -0.161807880520032, -0.12806524967738, -0.409825401339099, 0.477956091357462, 0.366440037390018, 0.14942209065554, -1.00892632704129, 0.48565073238296, -1.17801356454006, 0.166181143543691, 0.735403726729126, -0.0084641466526045, -0.289105858444239, -0.68323603186344, 0.013317154422042, -1.39079583478784, -0.311320000147051, 0.197458816019289, 0.124741613879059, 0.0568751015590167]', 0.99); -insert into credit_card_transaction (time, features, amount) values (157984, '[2.05269311103296, 0.0832291750212749, -1.29963681382918, 0.319329160730435, 0.190586891271607, -1.03891055540037, 0.274840025695008, -0.375561108243263, 0.376040836425049, -0.0361706507085913, -0.139771919621809, 1.03323404059433, 1.22467579188652, 0.259968927221364, 0.674129858259793, -0.407568804281939, -0.410891741117796, -0.381166876545931, -0.433151217096556, -0.157134606833929, 0.281863973713935, 1.00672960583387, 0.0724497417901615, 1.15590752441511, 0.265709827167777, -0.165664124585168, -0.0129351274570088, -0.046091589598825]', 0.89); -insert into credit_card_transaction (time, features, amount) values (157984, '[0.81583530027683, -0.135741872269979, 0.410949138436555, -1.80124886333432, -0.974179003182342, -0.915719732679837, -0.295548566414395, -0.936574701573116, 1.2708519660587, -1.14499402886989, 1.77626595190362, 2.23927946535372, 0.946650207071043, 0.125260831791892, 0.237268823166167, -0.432256428436072, -0.335418471019247, -0.0157564977461659, 0.842744825885943, -0.160982196995703, 0.659120484482723, -0.419533642855097, 0.320547791407024, 0.557733796674746, -0.0336864066761128, -0.553766936135689, 0.172173027814975, 0.168069916805165]', 32.74); -insert into credit_card_transaction (time, features, amount) values (157984, '[-1.1499923777044, 0.59625694895982, 1.74801909207187, 1.05768707484915, 0.490737741281965, 0.473117785397453, 0.44844040725259, 0.25666885341858, 0.209536022831864, -0.370252654103923, -1.43731632747189, -0.154487374945779, -0.809666313030499, -0.262462484169826, -0.616880806821511, -0.893279132813805, 0.401463388114945, -0.550878637613737, 1.31146800622303, 0.114973040826894, -0.568831258861779, -1.36939612294812, 0.10587011625502, 0.58298796794886, 0.433680213662218, -0.813375616852775, 0.235455766292334, 0.162920778082918]', 34.96); -insert into credit_card_transaction (time, features, amount) values (157985, '[-1.038324774473, -1.04420226793028, -1.68550813350863, -1.98020284108057, 1.30026242196773, 1.52857894655716, 2.24569625500273, 0.266297135236602, -0.488183289920301, -1.23386295035756, 1.17415300662843, -0.126389608625717, -1.78268755461073, 1.36742723965976, 0.727297107708839, -1.52428315117596, 0.599308925335549, -1.40121348069582, -0.815527972818355, 0.656271834043813, 0.645011675347473, 1.12862593403377, 0.86919482378899, -1.06325491003779, -0.459294682096277, 0.82408723326341, -0.0195542401536002, 0.187682143489534]', 415.6); -insert into credit_card_transaction (time, features, amount) values (157985, '[2.0377230312721, -0.174405502571658, -1.22816497916937, 0.206601285172922, 0.074077311518071, -0.593325367022731, 0.0088500123189233, -0.0946503788706294, 0.419257557677737, 0.255815665355955, 0.525467624858113, 0.623510102551369, -0.691837255641971, 0.600497313881401, -0.502984651044866, 0.183593936145614, -0.585344223819071, -0.242537465570877, 0.519042953742118, -0.25352661418887, -0.266279956717685, -0.696941769874464, 0.293863534208587, -0.486260032314027, -0.315324684483836, 0.210791657197925, -0.0767547818030606, -0.076271359205579]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157985, '[2.33711541867659, -1.32241285641572, -1.5076316497485, -1.93901752550013, -0.414174669647993, 0.269720384779131, -1.05899156802788, -0.0808658994993204, -1.617465734983, 1.71725026880438, -0.104273546944298, 0.0941080483826006, 1.63945724094246, -0.483336059308375, -0.944640291093014, -0.181981381030383, -0.194555936984752, 0.630365977235737, 0.545655194623276, -0.288842100983413, -0.122488349226662, 0.162934022046668, 0.0594114496811898, -0.326713086903993, 0.0665098816809244, -0.0883627524016086, 0.0029763057924077, -0.0639523456880933]', 20.45); -insert into credit_card_transaction (time, features, amount) values (157985, '[0.272183044850092, 0.804097011214754, -0.236366736323444, -0.262365483658319, 1.16912262938236, -0.678473710241877, 1.12331938626959, -0.317212171216718, -0.152698317271657, -0.734420029626425, 1.0381150524124, 0.702601803491696, 0.23333273080958, -1.06398771710766, -0.561929474229747, 0.0087268526745382, 0.25282793348098, 0.520090073955388, 0.605443161418944, 0.0167722477592292, -0.211633701238631, -0.33743240145056, 0.024118167848894, -0.523397041819117, -0.766463522219622, -0.662480266592223, -0.0143824717134726, -0.0961654418816045]', 9.99); -insert into credit_card_transaction (time, features, amount) values (157985, '[-0.141331897398899, -0.205877050453299, -2.73231436952907, -1.33800297970994, 3.85317203835303, 2.54885158789366, 0.0039433333060001, -0.267734900098729, -0.661319767070645, -0.858174576856784, 0.381171445672259, -0.140006854855413, -0.482621300868651, -0.116694741736131, 0.547170237186007, 0.0943155603040334, 0.547478157470998, -0.283419381095407, -0.810195930667418, 0.238404045325131, 0.923845311542132, -0.635754497915462, -1.63346067045926, 0.733959578965911, 0.633797618105617, 0.739604654364438, 0.114416244960481, 0.319937286330274]', 252.9); -insert into credit_card_transaction (time, features, amount) values (157986, '[0.147051840027449, 1.0830396660897, -0.402870389789097, -0.553268602776946, 0.97253869603613, -0.803215528516796, 1.03177008707257, -0.149294644474044, -0.150102084846622, -0.85660535615362, -0.596710198204915, 0.234367756322204, 0.690211237125984, -1.15373282921449, -0.311969388429648, 0.307477317658837, 0.318226280880149, -0.29043368300994, -0.224784459518234, 0.0675472943503132, -0.334343624340973, -0.78363297823318, 0.0893149404561686, 0.577336269654958, -0.393884221899291, 0.11135399453266, 0.226049670491634, 0.085689181091412]', 5.55); -insert into credit_card_transaction (time, features, amount) values (157987, '[2.11236262467254, 0.654754740525139, -2.81924754830598, 0.476959073914732, 1.27080918013566, -0.932040025725309, 0.390901979939392, -0.341114630529116, 0.350278023810418, -1.24376005266223, -0.269915077847392, 0.170098147999943, 1.42912959605036, -2.85236305446325, 1.02703319295645, 0.956498495682944, 1.39874219383979, 1.39191006984878, -0.412732080257681, -0.0156889288911087, 0.0572854712568602, 0.396408456467406, -0.119900536060807, -0.148248625557752, 0.420761880114656, -0.0947176854940052, 0.0226409426344049, 0.0100758634306431]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157987, '[2.04109782099017, 0.350940189056597, -2.10090814768339, 1.08312542190863, 1.04431954194898, -0.866813357501284, 0.887324124816537, -0.499160372491717, -0.327876686419373, 0.318842067036512, -0.846729877011878, 0.657916710982758, 1.15757045599222, 0.547625404122294, 0.12020511562162, -0.347763444754248, -0.642043189599288, -0.426426187636703, -0.274215912853205, -0.103771952899864, 0.128494173257471, 0.434767724325055, -0.0586906490835362, 0.506267126674545, 0.562184550941427, -0.508893151213243, -0.0357005330978196, -0.0512525870505582]', 36.92); -insert into credit_card_transaction (time, features, amount) values (157987, '[-0.394788448107399, -0.894404876691071, 0.979298291075818, -2.53714149861398, -0.483413827960082, -0.840846478443589, -0.245646929680381, -0.0436200901853771, -2.3458008188704, 0.921203537073684, 0.48372448980412, -0.654391319780736, -0.192391706438135, -0.177761989410496, -1.31899854386112, -0.470671553570291, 0.243554912097002, 0.542999885746448, -0.0071167943493756, -0.205083088356636, 0.0201852017064449, 0.277830546908711, 0.0185608934538624, 0.0447062630395892, -0.291131078889448, -0.22834421975755, 0.120528098915956, 0.152882165428069]', 50.0); -insert into credit_card_transaction (time, features, amount) values (157988, '[2.04712004532606, -0.0178533596278358, -2.30606043977286, 0.12799513631335, 0.968767552806877, -0.510501224883777, 0.623160392803822, -0.277374653477536, 0.112727612633072, 0.137937194438245, 0.493305890164093, 0.927393102116149, -0.0937839584347398, 0.804422500414814, -0.791809467196635, -0.596497685073425, -0.490340506852817, 0.0114111308590317, 0.553261186536863, -0.168578834552216, 0.169514320625628, 0.611486035994919, -0.12613908189907, 0.273767721234261, 0.589176448678518, -0.0915406984112753, -0.0629072823343511, -0.0782769675353617]', 28.16); -insert into credit_card_transaction (time, features, amount) values (157989, '[1.80864033170131, 0.0383821145193868, -2.10464260599799, 1.32557117246225, 0.679213923068398, -1.38480715246024, 1.18298160916691, -0.677137221825468, -0.420948059601586, 0.279909812451714, -0.660041306284505, 0.847408958726595, 1.31442093840839, 0.595582894060089, 0.0007835281641163, -0.491826764589974, -0.539881906722786, -0.507336674768713, -0.386302958973705, 0.101245975785915, 0.267422876895862, 0.63890420341079, -0.226338950259919, -0.0530879289663113, 0.577839269028708, -0.428649055843689, -0.0560485764108666, -0.0398602234387406]', 150.0); -insert into credit_card_transaction (time, features, amount) values (157990, '[-0.854089720396774, 0.802951390473658, -1.01687286859822, 1.11067043625121, 1.60872665710188, -1.70323665346098, 0.915498549602817, -0.0437809583997831, -1.25753591894454, -0.0029950921809338, -0.976889475975735, 0.658609895800632, 1.34541328550971, 0.911258546231316, 0.109320718155876, -0.85631239084077, -0.0711339201918452, -0.172068187169231, 0.567298833231111, 0.274310119314279, 0.407298693521455, 1.05198250542721, -0.231318535127903, -0.0427353025377282, -0.255749090788623, -0.389403549442357, 0.379763104243126, 0.0892658521914443]', 3.6); -insert into credit_card_transaction (time, features, amount) values (157990, '[1.83886779621712, -1.26584212554491, -0.713061595464002, -0.344034471235008, -0.773010627780886, 0.386865708550394, -0.887792599528705, 0.0665193044653516, -0.419159788590151, 0.979460795527683, 0.383055652385181, 0.952046783923038, 1.43898769303676, -0.215104118489459, -0.0110305587787033, -0.662098721303236, -0.908310963582548, 2.06090999612596, -0.813681582319438, -0.205022834033805, -0.0611147386381165, 0.0968051302793067, 0.0949946174797474, 0.304822366746747, -0.368648957472589, 0.314097076469585, -0.0166541633355801, -0.0203895822173477]', 147.0); -insert into credit_card_transaction (time, features, amount) values (157990, '[1.93090892696115, -0.480163126614668, -0.850093142552679, 0.107091373620853, -0.131368959289603, 0.0223979395098992, -0.402617937018541, 0.0103154252520142, 1.32766637867618, -0.266015098899084, -1.38553406656163, 0.276500735832294, 0.354160197554477, 0.0168838879056778, 1.15126696307505, 0.462141538725997, -0.952514217800872, 0.27471647162802, 0.134714480553858, -0.0464755268238872, -0.14137610620748, -0.45383383126495, 0.239722571272779, -0.0235600514082925, -0.271392155578471, -0.92997705778748, 0.0403439789231055, -0.0155516589263575]', 69.24); -insert into credit_card_transaction (time, features, amount) values (157990, '[0.143560596001966, 0.587314009216495, -0.0358333786338847, -0.869775533398348, 1.48280698016015, -0.007579073573562, 1.25983492837551, -0.521463698895298, 0.112014393995214, 0.168550814434153, -0.380956644934996, -0.417639703496914, -0.606826944035918, 0.226212668865572, 0.0974728408286391, 0.0484235646200726, -1.37795844984772, 1.17687285786284, 0.914286199545073, 0.0059582263924113, 0.265857825739496, 1.13844429340141, -0.469287571340013, -1.36081072102547, -0.416918454332601, -0.163319329918721, -0.254136657921484, -0.251555960560955]', 5.55); -insert into credit_card_transaction (time, features, amount) values (157991, '[0.259173746741467, 1.21386157141849, -1.45677103146647, -0.309308665209166, 1.01141101130299, -0.564735445666399, 0.612991719993012, 0.171974000960478, -0.321304504666245, -1.17031859600834, -1.1176468120284, 0.345709791087465, 1.50577618664901, -0.84415287766274, 0.600815481283695, 0.391552779300015, 0.2154017809313, 0.831188730963809, 0.0332985675473074, -0.0972804972681595, 0.289830437479287, 0.860718920941663, -0.156833013547339, -0.0030439976012819, -0.10437263161415, -0.144214785685948, -0.066941447769097, -0.0441856406478188]', 13.0); -insert into credit_card_transaction (time, features, amount) values (157991, '[0.0526809203754026, -0.190089867648071, 1.16208526769314, -1.43366348623236, -0.0801315553798603, 0.25010675315447, 0.0718004188821336, -0.198956884811732, -0.736003702781692, 0.39457143822218, -1.71664956559432, -1.35836540867604, 0.379508741991065, -0.766917053915528, 0.583058223186984, 0.843678275913349, 0.0619489268911854, -0.617608384467588, 1.81773342259392, 0.380878279362272, 0.306566709153659, 1.07361667105095, -0.341761480134881, -1.01211296537181, -0.156709849468961, 0.115647155119122, -0.0008530734809258, -0.0792043979122315]', 39.9); -insert into credit_card_transaction (time, features, amount) values (157993, '[1.85288475952639, 0.473710003884223, 0.310970769467465, 3.81760877567988, -0.125462595975344, 0.129680799942635, -0.248698938000325, -0.0166052221847358, -0.701846642724368, 1.32082671729537, -0.925746094513927, 0.744912574080614, 1.73230665990834, -0.437725567136392, -0.590151872929491, 1.23354929136605, -1.05131375888487, -0.561850926201894, -1.60242488288064, -0.159511743907691, -0.174755285657351, -0.432877685499437, 0.412669118182352, -0.0008895695501572, -0.517112847841033, -0.389886619043593, 0.0188498459005466, -0.0196453401288847]', 13.99); -insert into credit_card_transaction (time, features, amount) values (157993, '[-0.188385880285044, 0.213025385938357, 0.78071255521591, -1.37766341933504, -0.493586682173149, -0.0939470703203497, -0.318464839691432, -0.158508131738335, -0.592652387483716, 0.808193806973832, -0.82214943402255, -0.68537288238289, 0.805566419124682, -0.680552987090326, 0.722933748676302, 0.977471777736693, 0.150010963232088, -1.03705837254047, 1.49019012883415, 0.0752863788038008, 0.244302949786818, 0.55967743528884, 0.156345833461641, 0.672306340526743, -1.47409896473772, -0.495173717129364, -0.213566937468262, 0.239556787718746]', 24.15); -insert into credit_card_transaction (time, features, amount) values (157994, '[2.05167392990316, 0.272887523213804, -1.57395460342605, 1.39371941781976, 0.40762053361259, -1.23997685023916, 0.656515123923081, -0.45037159663884, 0.187040071335283, 0.26691239792518, -0.996227869510808, 0.365150932324821, -0.152766039228104, 0.50519378601389, -0.579675718953309, -0.689585294556884, -0.18624073605008, -0.58957012403175, -0.153441896914621, -0.304302826092369, 0.0413032450335258, 0.365279323191869, -0.0020650531763521, 0.0544707478920734, 0.478429123340327, -0.494707561537863, -0.0156669199767425, -0.0624594589471261]', 1.0); -insert into credit_card_transaction (time, features, amount) values (157994, '[-1.42147860971256, 2.21360707933308, -1.85054206422684, -1.67631304380085, 1.35780249285282, -1.03240924232746, 1.60596892880081, -0.286426300030681, 0.964090810678693, 1.57745524909955, -1.49921721436163, -0.59217689062349, -0.541604865101477, 0.224648757261934, 0.071242482005685, -0.576106969027422, -0.762409271701829, -0.165780929679948, -0.0181828757511213, 0.760434519614119, -0.0500193611678655, 0.608940100226333, -0.254804956349742, 0.0481006932642992, 0.0748600603920638, 0.0723379210297193, 0.563302480702816, 0.120452282676504]', 0.77); -insert into credit_card_transaction (time, features, amount) values (157994, '[-0.389578141229863, 0.965798289868215, 1.06405285907439, 1.12011687424355, 0.627132063843454, 0.188575024004209, 0.786271785520629, 0.0250913248703534, 0.0554194135958932, -0.366664888836034, -1.69891931248837, 0.660891202826879, 0.679885960339591, -0.490851304205345, -1.51273988200752, -1.30982957197075, 0.378128000333287, -0.676583540883496, 1.39176799240482, 0.167438521860015, -0.309836716429563, -0.379238572723551, -0.194083477413766, -0.413646925559684, 0.0752375390139664, -0.612144503906447, 0.449281857159036, 0.217958986364404]', 10.78); -insert into credit_card_transaction (time, features, amount) values (157994, '[-1.03834629001417, 0.980823096831625, 1.13169386902647, -0.965596494322759, 0.977842027054246, -0.554693848572675, 0.99023266502701, -0.0615763088584925, -0.718198697228029, -0.456005664710077, 0.649272018854922, 0.900761122073184, 0.537575177052452, 0.151056722133844, -0.965661561623348, 0.102450898101333, -0.71373745664673, -0.213664917369033, 0.511309133552619, 0.0842441648458802, -0.289983643887679, -0.761898723191137, -0.397129864457753, -0.311402125020374, 0.581507724734275, 0.323495541398553, 0.0872730595077866, 0.0833171739683947]', 1.78); -insert into credit_card_transaction (time, features, amount) values (157994, '[-2.18655778922673, 2.55338991628287, -4.05731999713177, -1.22917092542734, 1.5410592698886, 2.85245864086152, -1.47630610751728, 2.8507407794835, -0.5190090362882, -1.1609868002415, -0.428427490095631, 0.493050112478783, 0.0100472096973589, 0.640308697444481, 0.971030816304602, 0.522734621982998, 1.24385878671091, 0.76951887452415, -0.380507516641941, -0.378266202672716, 0.506290602255772, 0.784137868585688, 0.145798851350069, 0.612597581596902, -0.167759567091009, -0.153299530316839, -0.663251731511976, -0.0723573504426223]', 2.58); -insert into credit_card_transaction (time, features, amount) values (157995, '[-3.24087328373638, -3.04250014375305, -1.52905280617537, -1.54341703522962, 1.75569789099543, -1.42438211500702, -0.224384618618197, 0.240723645552957, -1.16172489175815, 0.205560279822645, -0.259810707826992, -0.546038513640202, -0.863699060298001, 0.604588956066458, -1.80197983685328, 1.23191819343331, -0.0385130490162624, -0.906240308679344, 0.736034445375585, -0.0603431288503041, 0.248804759089803, 0.377166624157001, -1.11842850205233, 0.232663664758924, -0.13663541370527, -0.241819312812789, 0.674763536286375, -0.669739164955096]', 219.0); -insert into credit_card_transaction (time, features, amount) values (157995, '[2.02410564755048, -0.239977221069602, -1.17552969284413, 0.546774190209576, -0.136380867800517, -0.829512139643842, 0.0355426306707878, -0.232416679923116, 0.826196917864315, 0.031921019907592, -0.831811809453729, 0.354451700025848, -0.382637426253395, 0.109604038786624, -0.624148423976021, -0.594347279076859, 0.0854363644874066, -0.609000878785836, 0.0028679005035407, -0.218079905313213, 0.146532568407121, 0.671720718941477, 0.0780787130449502, 1.23109509337488, 0.164595435721947, 0.6668067861417, -0.0756149114581401, -0.0601502729104189]', 12.31); -insert into credit_card_transaction (time, features, amount) values (157995, '[1.96531979162672, -0.604376981009271, -1.73674372868077, -0.678321855171807, 1.81561788620994, 3.77925610393906, -1.09947973164136, 1.02682028217507, 1.1205364396116, -0.14822086025553, -0.0410258631561172, 0.553902400274783, -0.0455777581470326, 0.157776530378819, 1.06905477711207, 0.119232218242606, -0.629752334109814, -0.318907944379756, -0.201247779928948, -0.142166209012562, -0.180360210617679, -0.490728830618942, 0.409368393747652, 0.657382492668504, -0.391700640161588, -0.60176744559643, 0.0539876134028559, -0.0366980694787675]', 10.0); -insert into credit_card_transaction (time, features, amount) values (157995, '[0.153383664773214, 1.13745490472237, -0.386275232320806, -0.56152742735665, 1.0334692725835, -0.791439789543417, 1.06601991271845, -0.183836682480236, -0.243090973724566, -0.87261561561599, -0.490942401876628, 0.564639350036639, 1.30967196749328, -1.27748556035014, -0.380253988916206, 0.277878452396739, 0.282970449360879, -0.367631373813257, -0.228324854474877, 0.100855389972614, -0.3289660062317, -0.732542521944843, 0.075163675853285, 0.594642778470109, -0.374099619013697, 0.109360979469292, 0.231111886956425, 0.0867836173839464]', 2.87); -insert into credit_card_transaction (time, features, amount) values (157997, '[-0.336239426170053, 0.958429815680492, -0.24889173869767, -0.746848195911093, 0.274269650318516, -0.546923737773364, 0.503795181688903, 0.463445249433104, -0.322065352417541, -0.4571219134258, 0.173844886916435, 0.42347874366809, -0.789677612021243, 0.775675564117922, -0.972964608233147, 0.324518306892487, -0.532016283436993, -0.0660608356153877, 0.282532810174294, -0.161811043129225, -0.190438410833539, -0.589730387075449, 0.104367282564373, -0.498258864252165, -0.481315563369098, 0.155649782478461, 0.111600822557173, 0.0186245286382775]', 13.99); -insert into credit_card_transaction (time, features, amount) values (157997, '[2.07227678423414, 0.155810694256452, -1.69040736134271, 0.425853175945209, 0.395716667549523, -0.900752360734983, 0.183882512640836, -0.236483240795318, 0.497722540278616, -0.377158818203769, -0.545417645429673, 0.136368471590181, 0.019141992231033, -0.834540731408179, 0.207195044610871, 0.308797783524846, 0.487589642533864, -0.313427682600817, 0.0408021393862854, -0.159101423586181, -0.362804013519222, -0.942009105043574, 0.344115104030004, 0.567010777180656, -0.263872441599506, 0.169744040359626, -0.0629537428290597, -0.0301685119021836]', 1.98); -insert into credit_card_transaction (time, features, amount) values (157997, '[1.89142394167909, 0.461925233243559, -0.74498642849913, 3.60437892143354, 0.523475632235626, 0.23278700238057, 0.112270521822615, 0.103716691947064, -1.01752051307632, 1.63106591073464, 0.0118734508196438, -0.235196702459739, -1.33029764070338, 0.709285044875633, -1.36882642356874, 1.09084761541496, -0.985950338437737, -0.125841497872216, -0.95488056362038, -0.356430951462129, -0.254410668869074, -0.825294015065832, 0.313420004207921, -0.583386295319196, -0.294627049217404, -0.328505470675697, -0.0471442294175663, -0.0596523887074605]', 9.85); -insert into credit_card_transaction (time, features, amount) values (157997, '[1.95581549901846, 0.0064200337213412, -2.63556579695858, 0.0458810376539879, 1.5554127316891, 0.198887846133665, 0.742241558151422, -0.0905190989182302, -0.202215426164499, 0.0905837486484391, 1.31443995868746, 1.18110135867995, -0.132397172420877, 1.12959218828524, -0.0021701535247633, -1.68622804870277, 0.4026567302194, -1.38025858756923, -0.637270442447588, -0.318025060572124, 0.418556274317098, 1.49322107311686, -0.199073001579511, -1.33003623239184, 0.615005377374104, 0.221316570880241, -0.0289957001045035, -0.107714970044056]', 17.35); -insert into credit_card_transaction (time, features, amount) values (157997, '[1.72986506814428, 0.37174933012196, -1.61297138354966, 3.7959286431451, 0.769966836114099, -0.748735049608872, 1.01194750424307, -0.413043568570005, -1.46281207666999, 1.53791798356379, -1.25782145683423, -0.664832404867863, -0.505758065995271, 0.836359792172352, -0.584720931689256, 0.61175336738986, -0.761991805660756, -0.510663749344267, -1.49740032747962, -0.049354581416787, 0.161755965916549, 0.120367296777598, -0.0797963948768653, -0.134588628952614, 0.233421470219938, 0.068273542838009, -0.110208180292015, -0.0420379583817925]', 144.12); -insert into credit_card_transaction (time, features, amount) values (157998, '[-0.0640958562133124, 0.663898024301168, -0.760477066502158, -0.922439695087993, 1.84110396284019, 1.2280774707675, 0.581541966751942, 0.525113793607584, -0.202841666650212, -0.788730243186031, 1.02623748963988, 0.372535496055676, -0.488542777952157, -0.675080252364888, -0.0763698193630831, -0.147262441497555, 0.752348722389591, -0.804238380819083, -0.781884659841249, -0.0228732512448712, -0.23864346591827, -0.538224598375529, 0.147990662418589, -1.06297512853967, -0.59258266054486, 0.225142908524695, 0.256604536177576, 0.0591223459757539]', 16.99); -insert into credit_card_transaction (time, features, amount) values (157999, '[-1.02574938375413, 1.15776291744236, -0.033327477821379, -0.442243813863839, 0.393003389774765, -1.19693665319056, 1.0989318096207, -0.371292483490231, 0.338062078062157, 0.418121441759003, -0.668703480545418, 0.106382715853071, 0.358559522590487, 0.0683863671740823, 0.693155822516832, -0.452353661315082, -0.465190389979203, 0.0241815230822891, 0.0434485216146917, 0.150053624184731, 0.170571854526715, 0.91016263242133, -0.292805521683459, 0.0921582959904475, 0.511682271103957, -0.0324269308502219, 0.239172073534195, 0.286926278190003]', 38.09); -insert into credit_card_transaction (time, features, amount) values (157999, '[2.05603140576344, 0.342600840903561, -1.81955947683389, 1.24637060988893, 0.572197989525541, -1.41054327263024, 0.798174184572388, -0.496394436217941, -0.109103043389559, 0.37415468472009, -0.777261214118751, 0.0264318227166965, -0.399594005572001, 0.872706235560097, 0.26099638167988, -0.451128923564884, -0.374623663124239, -0.468745496691316, -0.445848364176961, -0.302746528084032, 0.124553959218894, 0.461693303591412, -0.0098771048358922, -0.0461543591706105, 0.450949421727211, -0.479142804179872, -0.0314340442411572, -0.0641287250516018]', 8.36); -insert into credit_card_transaction (time, features, amount) values (157999, '[-1.42656259993647, -2.36732850168801, -2.1491077454988, -2.85642449287857, -1.33558729099318, 0.67084246937659, 3.92924406221627, -0.650406479028878, -3.42991822394087, 0.153531209322498, -0.838723151709099, -1.66398574297931, -0.264681323464446, 0.475410635409852, -1.89291189835722, -0.474357040668973, -0.242155089010834, 1.02470967746216, -0.0377785154810256, 1.41999492602488, 0.632862819046121, 0.713253419575556, 1.2247375972255, -1.44879582442195, 1.29660721484043, 0.252188828697769, -0.271000932427871, 0.125407173302402]', 857.55); -insert into credit_card_transaction (time, features, amount) values (157999, '[2.01102378066906, -0.624258780548357, -2.07613122346912, -0.268794071745131, 0.253604296813077, -0.646627503228843, 0.329745824921249, -0.384418114296321, -1.35704233085159, 1.08694744094524, 0.850578581032546, 1.18835482670936, 1.12220661786516, 0.449006919426211, -1.22143952013622, -2.04755549121025, -0.118250700942601, 0.929476645845765, -0.507935782020169, -0.383266167731841, -0.137817695259622, 0.0699408663907496, -0.0127426989762834, 0.767071428464348, 0.279433698780856, 0.470825965126254, -0.0884967725903225, -0.0634472867099299]', 89.44); -insert into credit_card_transaction (time, features, amount) values (157999, '[2.29899706749088, -1.3459062126824, -0.563147550902457, -1.71377958314276, -1.33590068528017, -0.393882056259288, -1.40187624254848, -0.0626831870150649, -1.15675184430066, 1.57568781032651, -0.848992992853496, -0.843739454096345, 0.657899532899061, -0.463988023154065, 0.738780145102113, 0.0043906068621889, 0.160528140633593, -0.0235764467531043, -0.346203611862752, -0.408380227731442, -0.348380201969361, -0.616430363616836, 0.500609454683835, 0.526165859287702, -0.619592133825937, -0.500084928398665, 0.03254746173764, -0.0296132921820711]', 6.7); -insert into credit_card_transaction (time, features, amount) values (158001, '[2.0804458012968, 0.157797221564784, -1.72497222941489, 0.40466173647078, 0.439693464897851, -0.851665937379694, 0.181354048303846, -0.231323911793502, 0.502060710477959, -0.376851844717831, -0.620442344527644, 0.113858829102904, 0.0451229441090357, -0.842157642072063, 0.212125713658569, 0.33320870345553, 0.455663801453384, -0.286961790098674, 0.0734824403881914, -0.157822675531815, -0.368989996328157, -0.956358190469169, 0.334313399069626, 0.481142864362185, -0.251620976418148, 0.175155116790014, -0.0627878217372978, -0.0312064091081313]', 0.89); -insert into credit_card_transaction (time, features, amount) values (158002, '[-0.549098556120708, 0.766195858129804, 1.01909289642756, -1.07510196402487, -0.129909471934689, 0.126445190701562, -0.104323067052091, 0.680171682259812, -0.0127904295950648, -1.10224461713379, 0.705173783476582, 1.12638195017102, 0.265629205980796, 0.258916255338938, -0.392073865317991, 0.505319582445916, -0.64616793178304, 0.290283934207098, 0.0693128702455883, -0.201792112756794, -0.0654568866809415, -0.319780426971331, 0.0443886396399804, 0.681193508833636, -0.229043111350763, -0.320790261779217, -0.10031657898665, -0.0461826232346844]', 3.7); -insert into credit_card_transaction (time, features, amount) values (158004, '[2.06550290251705, 0.162821106221004, -1.69100116807402, 0.413852601882327, 0.449491628074564, -0.806407337309328, 0.181257182481838, -0.220818275169419, 0.467695496903158, -0.390979249986143, -0.470052846499326, 0.255882148719389, 0.209415068917796, -0.867924211765855, 0.233993465007978, 0.243679354795962, 0.529694388382164, -0.423236913744068, -0.0288115174610784, -0.154137731814145, -0.355709657467918, -0.903873646891761, 0.348031378005165, 0.512722172718482, -0.270970861902284, 0.174850710145318, -0.058401382456676, -0.0305246906946382]', 1.29); -insert into credit_card_transaction (time, features, amount) values (158004, '[0.109324109169265, -0.341359999690875, -0.184801742480943, -2.34348578412266, -0.724844167576597, -0.394404191913993, -0.437892621320415, 0.101288947662588, -1.69032272176358, 1.21765313336653, -1.85018687214858, -2.01620345223279, -1.05993224039229, -0.0826300686653481, -0.284471370283958, -0.632545908880372, 0.562731195431606, 0.400662124109114, 0.314626330728009, -0.504081803445869, -0.0419308672436013, 0.321584296839844, 0.175852729743953, 0.417841022498596, -1.28200230406287, -0.338280669456561, -0.131838307432044, -0.0284202718310015]', 20.0); -insert into credit_card_transaction (time, features, amount) values (158004, '[-1.15506028408787, 2.4189020055203, 0.917719176127805, 4.34800584015966, 0.0286157856885355, 0.553499890025478, 0.479632581514223, 0.725492752682277, -3.05477649771925, 0.866651919786396, -0.686530212856898, 0.221366203142337, 1.42214479836464, 0.819436764218728, 0.634016613620267, -0.114883441465671, 0.598338924424487, -0.421850268280038, 1.28734383701138, 0.0908511058084369, -0.112713270597994, -0.644786218760235, -0.0045105816774112, 1.12899939306351, 0.18643712593013, 0.138407088167937, -0.291010968855825, -0.0449216077722927]', 56.69); -insert into credit_card_transaction (time, features, amount) values (158004, '[-1.15506028408787, 2.4189020055203, 0.917719176127805, 4.34800584015966, 0.0286157856885355, 0.553499890025478, 0.479632581514223, 0.725492752682277, -3.05477649771925, 0.866651919786396, -0.686530212856898, 0.221366203142337, 1.42214479836464, 0.819436764218728, 0.634016613620267, -0.114883441465671, 0.598338924424487, -0.421850268280038, 1.28734383701138, 0.0908511058084369, -0.112713270597994, -0.644786218760235, -0.0045105816774112, 1.12899939306351, 0.18643712593013, 0.138407088167937, -0.291010968855825, -0.0449216077722927]', 56.69); -insert into credit_card_transaction (time, features, amount) values (158004, '[-1.21856080377954, 2.3188899092973, 0.962124579511793, 4.37257807777186, 0.254430020526787, 0.399950438575389, 0.268947913997004, 0.768127780257851, -3.04230859762087, 0.892319101728426, -0.69453243044046, 0.242375499576354, 1.42125658230275, 0.834256083331126, 0.631472523161664, -0.132702840500678, 0.608662777267431, -0.417839058065723, 1.2830589929023, 0.173004066676641, -0.0828315589305315, -0.662974331983671, -0.022599086032618, 1.12577946680195, 0.178329541926154, 0.131827203077857, -0.349199246859752, -0.0203315741999646]', 6.01); -insert into credit_card_transaction (time, features, amount) values (158004, '[-1.21856080377954, 2.3188899092973, 0.962124579511793, 4.37257807777186, 0.254430020526787, 0.399950438575389, 0.268947913997004, 0.768127780257851, -3.04230859762087, 0.892319101728426, -0.69453243044046, 0.242375499576354, 1.42125658230275, 0.834256083331126, 0.631472523161664, -0.132702840500678, 0.608662777267431, -0.417839058065723, 1.2830589929023, 0.173004066676641, -0.0828315589305315, -0.662974331983671, -0.022599086032618, 1.12577946680195, 0.178329541926154, 0.131827203077857, -0.349199246859752, -0.0203315741999646]', 6.01); -insert into credit_card_transaction (time, features, amount) values (158005, '[-1.32810970955363, 0.107338014270061, 1.73762146291356, -0.331052776733906, 0.986896555632258, 0.510835874288767, 0.445982754162208, 0.340067045879952, -0.438485084066442, -0.82268729994518, 0.0904337560501687, 0.371077421739853, 0.180131863029724, 0.0033190296924099, -0.430258921904993, 1.00371254724598, -1.47809191533409, 1.17085240148857, -0.821312878215421, 0.233601153819319, 0.331077019310538, 0.572049383968115, -0.256214299632852, 0.167230162790563, 0.908312883877749, -0.546693084577415, 0.00781965182604, 0.0744328428619158]', 95.0); -insert into credit_card_transaction (time, features, amount) values (158005, '[1.95863121859227, -0.270358858428833, -0.361758061353839, 0.232941035614787, -0.341751857602434, -0.01286687699886, -0.557950971549502, 0.10289433602546, 0.876470961056475, -0.0239914475363933, 1.04756783261856, 1.64125606189957, 0.876207172849847, -0.0229889075230185, -0.101866433770536, 0.364804483093047, -0.853220123414868, 0.218722539711737, 0.208228224499259, -0.142187299996863, -0.124964196913852, -0.230031602129102, 0.394390129342312, 0.741236308817778, -0.413886149270631, -0.680441236162737, 0.0329031283035746, -0.0324001159271016]', 2.49); -insert into credit_card_transaction (time, features, amount) values (158006, '[1.96807082007987, -0.473547486337158, -0.224402524425328, 0.388142689028991, -0.790983742207614, -0.404441367273001, -0.69333792227015, -0.0120263556123078, 1.20784562090276, -0.0215718960470008, -0.626773151403427, 0.580835533992384, 0.404442051912913, -0.326718394006489, 0.341163082442498, 0.219212502839639, -0.376442449141442, -0.0947754607243288, -0.389843707015761, -0.137925129929002, 0.237008128981077, 0.880059040207286, 0.205791671246351, 1.22810530739388, -0.277807655716904, 0.681254716110786, -0.0313862405242558, -0.0372369502682329]', 14.99); -insert into credit_card_transaction (time, features, amount) values (158007, '[-0.174917483310695, -0.3802532173463, 0.425592259603839, -1.60065326921161, -1.79280612435935, 0.269107756756679, 1.4934269467715, -0.383368658178788, -0.762060463385778, -0.232361892163579, -0.81829070606579, -0.0287198029042257, 1.32830763279617, -0.949920527356444, -0.938435376070552, 0.967722921045715, 0.1632538044246, -1.90953822667882, 0.629253080361338, 0.0985351199276307, -0.128633755803298, -0.259236286080482, 0.402771704425359, -0.0815274099926616, -0.652753682019415, -0.65023886510379, 0.107371044334943, -0.0367400964881512]', 357.4); -insert into credit_card_transaction (time, features, amount) values (158008, '[2.12824860039992, -1.37484398762585, -1.70766623468932, -1.85208377750572, 1.13351130900808, 3.84281520229695, -1.82825993170034, 1.02281227216907, 0.186772577126798, 0.72245308449633, -0.15763866001492, -0.405617405802214, 0.140457860683641, -0.47816376057519, 0.471718261364598, 1.08269133281213, 0.0640828220124807, -1.11484502193072, 0.269356364811938, 0.0566471381801107, 0.431020544885627, 1.26910275923978, 0.114499845078129, 0.761774542353535, -0.0696130410945029, 0.0444011539559604, 0.04322762241014, -0.0520447600128112]', 14.95); -insert into credit_card_transaction (time, features, amount) values (158008, '[2.06696679914538, -0.0586455101676325, -1.28892839968384, 0.350483457381838, -0.0561656764195863, -1.22073881355422, 0.160256995636037, -0.333780364647096, 0.706142210634753, 0.0163967498086748, -0.788180370804549, 0.0597027453624339, -0.35392610125504, 0.546414664416819, 0.875582441395916, -0.197023134613227, -0.464927118858226, -0.0344365882615781, -0.297270353474904, -0.277553535295582, 0.255359945354464, 0.894498478025095, 0.0036660425132795, -0.0575925537141293, 0.233468261099952, -0.0928364440237184, -0.0158725770755196, -0.0598064892288759]', 1.0); -insert into credit_card_transaction (time, features, amount) values (158008, '[-1.33284248995339, 2.03119003550903, -0.720939425737272, -0.487277891938185, -0.308116808038665, -0.180411271129577, -1.68137885135292, -4.94871354211716, -0.711354391180041, -1.61145321731141, -1.25576550413049, 0.764544520372453, -0.42883323502723, 1.25129923642293, -0.602596501061529, 0.358616297603198, 0.0431355847483786, -0.62057891106073, -0.420707862018223, 1.10795399788182, -2.72715468874493, 0.217475512910371, 0.571787386257881, -0.0043502116861516, -0.607924730244165, 0.106827705284383, 0.0495643883022036, 0.10757800505176]', 1.98); -insert into credit_card_transaction (time, features, amount) values (158008, '[-0.298673843353843, 0.183739852526517, 0.647865001229045, -0.579165559700988, -0.480181607968308, 0.395464748465713, -0.985381660681913, -2.5118133667157, -0.11385244582456, -1.1114961500072, 0.405144750230186, 0.815051661879033, -0.61666004527177, 0.670727717013591, -0.466202706326449, 0.99276738290918, -0.819217516807982, 0.205792765178059, -0.178956660036883, 0.767749613593986, -1.44020998875816, -0.46315404139436, -0.025509281700941, -0.357899501214852, 0.236179176597933, 0.287736425353656, 0.0214301897309842, 0.26461403946828]', 130.0); -insert into credit_card_transaction (time, features, amount) values (158009, '[-0.187065738562102, 0.938949796372722, 0.158719491986008, -0.635957028283626, 0.267082977201802, -1.08421006871295, 0.90458768576091, -0.0974889838836657, 0.343124081719593, -0.0737261282824574, -1.07776962765302, -0.533308770675161, -1.30940543824619, 0.30919167449721, -0.19663321750018, -0.11058920508987, -0.286106658185972, -0.692350235470158, -0.177221975014794, -0.0036473758111797, -0.300598304711216, -0.677266238419372, 0.10110312439087, -0.0598839760112864, -0.497809069737035, 0.152464734696248, 0.348868155923537, 0.153910093277228]', 4.49); -insert into credit_card_transaction (time, features, amount) values (158009, '[1.77605423354843, -0.643944145159802, -1.16405697582766, 0.546213485659379, -0.175210218972686, -0.389591746147173, 0.0051497998833683, -0.153794950607152, 0.77260234122879, 0.0232261679929539, -1.06528075396715, 0.173686120412681, 0.0086044950463042, 0.150746727001186, 0.345403216716222, 0.188709383093358, -0.506428144770819, -0.251381530104047, -0.0921158114932612, 0.0996194116509905, 0.0305268134628971, -0.118706296972696, 0.108339322874396, 0.599722082980315, -0.21176556296923, 0.188068516027917, -0.0724443369684532, -0.0236568974723718]', 148.75); -insert into credit_card_transaction (time, features, amount) values (158009, '[-0.961235578939082, 1.33817544647597, 0.657262789394844, -0.497486396693, -0.730714410453866, 0.722049906975452, -1.60756288287889, -4.78567532423441, 0.828029747227186, -0.319231028145593, -0.933227880147206, 1.16983614590807, 1.16989282968414, -0.312015090251343, -0.108449106648623, 0.326413109547181, -0.255271208278592, -0.0871572715591543, -0.764758183230007, -1.04888230191168, 4.79202047276388, -0.720301638569118, 0.218132920417395, -0.0470787182790086, 0.763649384130085, 0.735270054982837, 0.36915484211879, 0.273405387017759]', 29.99); -insert into credit_card_transaction (time, features, amount) values (158010, '[-0.359846842014646, -1.72306592785694, 1.04928893390916, -2.31785954793245, -0.932436687283213, -0.135419624087709, -1.19918557691809, 0.18223634351014, -1.01464488811998, 1.00168115114308, -1.50766584860569, -1.58777813764519, -0.312910934496231, -0.853604094235265, 0.0756591824448081, 0.0901607754723302, 0.118832783990921, 0.616825711553791, -0.597274273125863, -0.448238221523313, -0.0215206771846747, 0.371009154709892, 0.637866626028848, 0.534466539068606, -1.04342233194524, -0.38195944404197, 0.0955265517133887, 0.152541512702937]', 67.0); -insert into credit_card_transaction (time, features, amount) values (158010, '[-1.2542814057946, 1.20096307133381, -0.627200807531874, 0.671479997644877, 2.30684078562474, 1.47195996916669, 0.980373130511881, 0.596089708960187, -1.14954783298045, -0.871663207720353, 0.876826509380834, -0.301796587205867, -1.27869630236082, -0.53208179407442, 0.268003910341743, -1.02942905140882, 1.79907100553185, -0.0706723660211838, 0.297031260110904, -0.148100374181437, 0.0220516010513153, 0.304048937035024, -0.308586510007307, -1.08225409006223, 1.01559518865203, -0.12965653868741, -0.278113051461387, -0.267037202557645]', 30.21); -insert into credit_card_transaction (time, features, amount) values (158011, '[2.10114312153406, -0.131633889284133, -2.09444043711982, 0.202531844329187, 0.736451528296812, -0.501846626088548, 0.413759428167791, -0.274836296105806, 0.49347684412016, 0.10139639854721, -1.57536354832683, -0.191761002854347, -0.516013680327826, 0.471888064322938, -0.24276731060148, -0.36696166759536, -0.264130483177789, -0.600831418464043, 0.401751198253923, -0.185175887839243, -0.0756203432825797, -0.101839504363857, 0.0214987019545058, 0.0714925771207879, 0.25129259337617, 0.573086957506978, -0.106701465881401, -0.0751004318541749]', 24.94); -insert into credit_card_transaction (time, features, amount) values (158011, '[2.13568645962781, -0.0495722266166086, -2.42561905467689, -0.250896037581784, 0.80652073476973, -0.877499997940161, 0.525600500430951, -0.251580495866916, 0.228290445740574, 0.237081672505878, 0.357697356019724, -0.177064565613102, -1.84575614751461, 1.31960087365334, -0.0600074678519535, -0.209694419357159, -0.588194831094848, 0.342498404005647, 0.587283682180758, -0.307577557991362, 0.142580642397469, 0.409347190412612, -0.0502162249690347, 0.290028895538371, 0.428879347821436, 0.220688853255967, -0.106299269096564, -0.0907389372021451]', 0.77); -insert into credit_card_transaction (time, features, amount) values (158012, '[-0.356112107485342, -0.176792234424064, 0.667073479330746, -0.832209868478933, 0.708046902364393, -0.556373890222478, 0.84391850402528, -0.140145781725371, 0.396220800911885, -0.598178788054038, 0.164846278986967, 0.0477260492905488, -1.50444726395879, 0.202073972005627, -1.1673127114867, -0.200155807497776, -0.593045242449931, 0.228665426373271, 0.559031887936197, 0.076144266555552, -0.103606206643723, -0.289182382264244, -0.0357451605996312, -0.370219303277823, 0.18072485751449, -0.108404918136018, -0.239703048695415, -0.257559850365974]', 68.45); -insert into credit_card_transaction (time, features, amount) values (158012, '[-0.115623294131462, 0.232952497287794, 1.54391073546632, 0.74175325796478, -0.408977914119821, 0.875809943582535, 0.524788492741967, -0.067408140031601, -0.510123806832224, 0.233755923793785, 1.2133921555289, 0.591021490450145, 0.943774719526892, -0.138164975040216, 1.45782503054464, -0.47189508525955, -0.0484905554283102, 1.01933839962322, 2.65449992273842, 0.727916336802697, 0.334267314456189, 1.06185604724004, 0.0773724916852188, 0.858019182195634, -0.523388914381481, 1.01915778703403, -0.0535869079019798, -0.0628129239951077]', 139.0); -insert into credit_card_transaction (time, features, amount) values (158012, '[-1.36319602377002, 1.46744250567976, -1.80801440252905, 0.758068498733319, 1.91363288695622, 1.26347372708645, 0.534051079649939, 0.971553749657575, -0.831576539740343, -0.551426446125783, 0.665632218797952, -0.0221423444694377, -1.1769746116895, -0.263322643684293, 0.0524271682594856, -0.905754215946917, 1.86084049587924, -0.0554157576697577, 0.128724314473812, -0.276268762354191, 0.1178831286758, 0.62066415939755, -0.080968923661723, -1.07924656287613, -0.0869949100703554, -0.332134232365957, -0.12029706944578, -0.146111970160301]', 32.79); -insert into credit_card_transaction (time, features, amount) values (158012, '[2.06804013207811, -0.854566234202144, -1.48438270459897, -0.952948646598933, -0.293969763362184, -0.761562206676964, -0.172659366138343, -0.29596589214731, -0.858394409898638, 0.898922909951742, 0.906730502052593, 0.646359344803653, 0.940969290991741, -0.006479051868868, -1.03698810719985, 0.822421675294992, 0.0312538227132215, -1.45701291092015, 1.14063774461727, 0.148278489067593, 0.111625309179023, 0.234895744286238, 0.0789322648857008, -0.357476182162683, -0.0073477595872901, -0.282854187904493, -0.0473919080405555, -0.0641320545480188]', 76.48); -insert into credit_card_transaction (time, features, amount) values (158013, '[2.0298433000459, -0.0880601458885333, -0.902333329835496, 0.522586204628432, -0.406609334198378, -1.46985201784382, 0.152797528570979, -0.32675532491943, 0.607351021649553, 0.0905275170575396, -0.470746065389009, 0.244645641298072, -0.636108789216364, 0.425669978145497, 0.0780593327541418, -0.198645989990932, -0.0989181095164906, -0.930120634541996, -0.008975555400264, -0.275783044998366, -0.26801840623418, -0.673364996689796, 0.398815001102551, 0.442669552427606, -0.376303691551718, 0.171754984141973, -0.0745017228674723, -0.0567975559072154]', 2.99); -insert into credit_card_transaction (time, features, amount) values (158014, '[2.19059184936535, -0.667482517987159, -1.42159182025015, -1.10895976920009, -0.20580177735733, -0.607630452654572, -0.421494377090815, -0.217884168919408, -0.942945048297514, 1.00890578671234, 1.28341729358577, 0.53134788831271, 1.02225607847444, 0.0392922229142589, -0.383960015434374, 0.995536083170316, -0.111521365971314, -0.98056107619905, 0.638013238757741, 0.0494848082164501, 0.494216601009636, 1.43343627056651, 0.0128038517785256, 0.789275948935685, 0.205997556340949, 0.0158576375863187, -0.0379919969562041, -0.0677634987861634]', 10.0); -insert into credit_card_transaction (time, features, amount) values (158014, '[2.15772500725235, -0.565010808070048, -2.25210028245371, -0.656838100190328, 0.417949337253706, -0.540404973914572, 0.221306383120983, -0.358830724316406, -1.22462923514464, 1.08842683843672, 0.348654895460532, 0.82697007233589, 0.874521347191276, 0.451709193508456, -1.17860675540703, -1.8235023524484, -0.292778023880146, 1.13519833862308, -0.146309785478595, -0.464203163115534, -0.219075435481153, -0.0801340219061155, -0.0188162703987775, 0.347536337871168, 0.299916502243819, 0.796660422332797, -0.108067714557822, -0.0812456414352052]', 42.13); -insert into credit_card_transaction (time, features, amount) values (158015, '[-3.36075457165147, 3.61812371452389, -1.94380003937942, -1.55487797308058, -0.232721270330603, -2.53741807883311, 1.45757625128927, -0.183662836138109, 2.22376282070789, 3.73364101164388, 0.0306710420874961, -0.0515998645066788, -1.14900357586303, 0.019489090941739, 0.0378903246767697, -1.17582778113969, -0.119461564605101, -0.796937153800969, -0.860334658983379, 1.52647615757724, -0.155660517363271, 0.803622552577433, 0.03170527728366, 0.90911506442161, 0.18856085901733, 0.0112478529725959, 1.00255268080285, 0.289222071208658]', 1.54); -insert into credit_card_transaction (time, features, amount) values (158015, '[1.3286221109967, -3.0036285044689, -2.17104255519545, -1.20034493691271, -1.45192935372842, -0.685638827183179, -0.165426013547936, -0.360504694585152, -1.56723281385972, 1.6220540043684, 0.11072479290007, -0.991455493328809, -0.93758475467081, 0.342389105533479, -0.966093536062319, -0.60627681384665, 0.383972832245193, 0.867719706872176, 0.0571431139179858, 0.520741209728053, 0.518875265687279, 0.844124527807451, -0.573745259072927, -0.286280404572821, 0.156454063926388, 0.242699655877684, -0.127925786452998, 0.0030608193830294]', 527.0); -insert into credit_card_transaction (time, features, amount) values (158016, '[2.05188001302592, 0.0348865835982961, -1.82489028521084, 0.240945123039728, 0.538142561529563, -0.408024626839614, 0.0163465023580155, -0.0201352944127314, 0.388981338726039, -0.182906300289172, 0.714778317665099, 0.265502035502147, -0.856197533034902, -0.488854536653689, -0.376176553343842, 0.640811456881494, 0.165885139670378, 0.393193203430254, 0.459865414572454, -0.191719998725591, -0.342454882066987, -0.959505214956084, 0.301244264898468, 0.161487832110637, -0.278840486170047, 0.175496511657153, -0.0727473926089709, -0.0454994015328238]', 1.98); -insert into credit_card_transaction (time, features, amount) values (158017, '[-0.932059273777712, -0.134426462911196, 0.772692057775689, -0.747332254458257, 1.19363988055783, -0.754138038330834, 0.631763782720432, -0.0203658352550088, -0.080884974934663, -0.888336491273951, -1.22232470732149, 0.0678166073914077, 0.232688959664018, -0.0374107628237998, -0.458266111392729, 0.300523120014312, -0.789381105832364, -0.211169653621913, -0.750798062898426, 0.169673219492678, 0.140619500448844, 0.104309922915188, 0.144435330750445, 0.673637250217338, -0.228817445798648, 0.0526938306279889, 0.050418939379092, 0.183032605262705]', 70.9); -insert into credit_card_transaction (time, features, amount) values (158018, '[-2.89215053450099, -1.39625746956052, 1.53102495742112, 0.822701727139747, 3.16967084037415, -1.54518216175689, -1.1539309234839, 0.214378508190957, -0.221002770060266, -0.708907597819677, 0.703805330201808, 0.662673290680547, 0.373053554687829, -1.2312832915632, -0.261327853556574, 1.05033507632874, -0.148900721263542, 1.00884113579705, -0.0149744683411427, -0.452646117639742, -0.38385290241954, -0.89687542010848, -0.730306754353318, -0.579237341308403, 0.384479012881505, -0.832912674670711, 0.361005313543467, -0.0674958404769695]', 34.95); -insert into credit_card_transaction (time, features, amount) values (158019, '[-0.692113938530945, 1.31322905999001, -0.521201209439012, -0.483767039913747, 0.67528577528705, -0.341005212892133, 0.531521123077797, 0.544426676252537, -0.324382576289273, -1.32184205551676, 0.756413946595868, 0.412216372909969, -0.566762992698048, -1.25437059857952, -1.4893040650211, 0.356076111939148, 1.12360142067351, 0.844035830406707, -0.0358623447215515, -0.0457538598457172, 0.121183903330983, 0.488303121618516, -0.183195340392929, 0.624329253229232, -0.197622719380915, 0.533996954477075, 0.244057268454374, 0.197915897790865]', 14.39); -insert into credit_card_transaction (time, features, amount) values (158020, '[-1.12200628366799, -0.457950088985587, 1.67237441053119, -0.466082206773037, 1.0509684781632, 5.62615888306642, -1.64109782647114, 1.65423636512179, 0.273081740198956, 0.462746963666576, -1.34905623067453, -0.0081170819182522, -0.0293042269574189, -1.34096663940576, -0.899291556406563, -2.29331780809303, 0.536157017254091, 1.6854308044934, 0.0458828036695601, -0.0109095521174638, -0.314833804457018, 0.120776261416867, -0.287328935456076, 0.696121200950272, 0.580222236646483, -0.123866190255205, 0.585458586983351, 0.254846368895795]', 50.0); -insert into credit_card_transaction (time, features, amount) values (158020, '[1.69234571013859, -0.105039263484382, -1.91526204863659, 1.19088481394566, 1.18460904173727, 1.57559755895921, -0.42723589515588, 0.562465879341146, 0.522988426717505, -0.681035776184852, 1.30158377716841, 0.372918968991889, -0.495313231239861, -1.78386619476624, 0.711942108589096, 0.425689857371131, 1.42515544808223, 0.392682245258996, -1.35049741039887, -0.0994592504385012, 0.0480323632818154, 0.174183546075954, 0.107162479626003, -1.1691702782335, -0.232120048291807, -0.597588176590653, 0.0913160732796459, 0.0047357337573496]', 84.0); -insert into credit_card_transaction (time, features, amount) values (158020, '[2.27111082192535, -1.28664547506791, -1.28222705350878, -1.65792731670975, -0.834495361397583, -0.42737892521792, -0.90080684881993, -0.105961962166683, -1.62191843396148, 1.72129681576365, 0.706430219452338, -0.134978372766328, -0.0003340866483964, -0.0520930181934239, -1.24007007633913, -0.740913234887491, 0.51370308298751, -0.114014316456132, 0.356540648380577, -0.442595728371339, -0.342447581123677, -0.533457228659934, 0.345727790021545, 0.657011162039137, -0.224177716487093, -0.375518392670327, -0.0132068316186918, -0.0593780392408658]', 14.4); -insert into credit_card_transaction (time, features, amount) values (158021, '[-0.702790428181329, 0.720406636512539, 0.9342701622712, -1.14531501058955, 0.818452719276262, -0.946817662562218, 1.1817011012598, -0.273955036034273, -0.144021027767585, -0.201863325800114, 0.766480234566862, 0.345900909890859, -0.888688645175973, 0.209018387790344, -1.2726555744136, 0.171937737654069, -0.859793134888601, -0.273147939101213, -0.251707212339735, -0.0685826156312848, -0.25784613905826, -0.538555366533331, -0.153338765103057, 0.0576671923723828, -0.302110249263983, 0.0421762436224188, 0.0132382102031736, -0.0540165180394867]', 8.7); -insert into credit_card_transaction (time, features, amount) values (158023, '[2.07386596664826, -0.0574474764833047, -1.32266276285972, 0.378656051692918, -0.117837413212535, -1.39583096601079, 0.200316364078324, -0.358865810237295, 0.725053004880719, 0.0406563940631472, -0.831944067758982, -0.151727503312774, -0.786835606155431, 0.657393598233784, 0.833119699354609, -0.179442218962579, -0.451064184733163, 0.0363218537704614, -0.229172122366579, -0.301798890214492, 0.235533016070261, 0.80813268884773, 0.0117178195227804, 0.0603417932928446, 0.238485379956948, -0.108280379250893, -0.025032459774617, -0.0604760194003316]', 1.0); -insert into credit_card_transaction (time, features, amount) values (158024, '[1.3812998852291, -1.6855638790775, -1.08201980232882, -0.768956734741289, -0.343957063833239, 1.0631943685801, -0.569929512753637, 0.335112250965508, 1.55728818689712, -0.644782790504745, -0.131422013604171, 0.469188663830721, -0.0807469103033629, 0.123956521667, 2.11002619275931, -0.600274914180664, 0.346997049869918, -1.21251173073995, -1.12261428814145, 0.323980394680132, 0.421475242229477, 0.816282520366422, 0.0515997744700914, -0.268750315521372, -0.653431458245139, 0.743398326844738, -0.0446368027267562, -0.0085561300393639]', 289.8); -insert into credit_card_transaction (time, features, amount) values (158025, '[0.376337000790453, 2.34401765468442, -0.576319562992614, 4.9045885987752, 1.0852926797056, -0.317089445118758, 0.824636000873547, -0.112581024954758, -1.86334386252492, 0.989373105390264, 0.0655255369114273, -0.288828616498574, 1.40109531595254, -2.85582001679919, 0.469506442302996, 0.561961800837084, 2.24822993276018, 0.632002797602366, 0.71821352973162, 0.507300542421562, -0.422439867129738, -0.851232057797204, 0.157989934594824, -0.217006902765562, -0.623896764547443, 0.0459039196578555, 0.425447231332348, 0.147727991755193]', 2.5); -insert into credit_card_transaction (time, features, amount) values (158026, '[-8.96971251912099, 7.53597195525541, -6.72151102801756, -1.51089577092286, -3.46695390039357, -0.948142590776108, -3.5320288922753, 4.72719293847749, 2.28413423822467, 3.67262139954074, -0.524159638289884, 2.1812120584612, 0.483838812579013, 0.822944498549129, -0.795942554609621, 1.52218941426229, 1.66586784234829, 0.871112553522731, -0.705198513309069, 1.18506615693331, 0.0955160015746943, -0.329154839461986, 0.744203148916278, 0.0583801618215842, 0.580245760318318, 0.353083252758906, -0.336489738492317, 0.651645091340483]', 5.09); -insert into credit_card_transaction (time, features, amount) values (158026, '[-0.0411362706306996, -0.220560148922629, 1.01235482098296, 1.11926344898811, -0.191347078861543, -0.293937627356436, -0.315027408081702, 0.174625180849426, -0.0948211408189453, 0.351563338187937, 0.838693633451771, 0.150544230236316, -0.814295047056348, 0.496159370442463, 1.03577209695395, -0.492802671998233, 0.269642775324203, 0.62934993386594, 2.87077127932348, 0.395722073464704, 0.0301042715185565, -0.0356016327614129, 0.569941764458777, 0.064809932666515, -1.9540522843997, 0.474514196656517, 0.249768333200403, 0.282966840241029]', 59.9); -insert into credit_card_transaction (time, features, amount) values (158026, '[1.8845408705184, -1.57198622407464, -2.25834829501493, -2.73018100845195, -0.588552889794093, -1.25244283080556, 0.0726867763310602, -0.375652965145536, 0.568206332600148, -0.273289832238356, 0.928453011429209, 0.939874123010966, -0.399409675738461, 0.827767322163664, 0.395219513341256, -2.63354758679693, 0.0046985048432499, 1.78449470472491, 0.56281535280024, -0.2652998474271, -0.0908898959612222, -0.0091651937167342, -0.0738109272361255, 0.758319483504186, 0.262225115533907, -0.772610466459783, -0.009741585541382, -0.0305728896846595]', 185.96); -insert into credit_card_transaction (time, features, amount) values (158026, '[-1.40186451573321, 0.574414179400537, -0.699218351415311, -1.6998275291308, 2.89966487009745, 3.47599109876195, 0.167104800364399, 1.29806857954787, -0.776928707942542, -1.03902118088366, -0.379846397582771, 0.0569042573111709, -0.390457880345495, 0.666057129070605, -0.0462687491159509, -0.255127371692401, -0.0959822346000761, -0.792042207035525, 0.113453649669977, -0.0557637264872856, -0.17485256670988, -0.858522868763138, -0.258559338410444, 0.720468300050424, 0.646053055551408, 0.413605380465705, -0.290968039114206, -0.038218878870042]', 29.87); -insert into credit_card_transaction (time, features, amount) values (158027, '[1.98334362190362, -1.07499759743561, -1.23808722499258, -0.638798384443381, -0.369728599694053, 0.182272906699272, -0.594504544950383, -0.0131013261854548, -0.518791494926067, 0.966542363373287, 0.123198938808012, 0.679302664092877, 0.771246526746198, 0.0291464366636196, -0.528324940289719, -1.0063492969552, -0.645043921748145, 1.58412516262599, -0.287481492210106, -0.337297625911408, -0.352038911253586, -0.649017700078523, 0.181594043650614, 0.0971591189742047, -0.33270292384924, 0.49130019440509, -0.0597336253818767, -0.0453469733843929]', 99.0); -insert into credit_card_transaction (time, features, amount) values (158027, '[-0.479561088303501, 2.09727296588127, -1.83172350683907, 0.803337039943055, 0.864218865013255, -1.59468961077119, 1.03345438393617, 0.290785266154311, -1.35233075259922, -0.977477489635804, -0.687076195962851, 0.354528577870922, 0.696307980295894, -0.0219360327428018, -0.0845441177817256, -0.13141615423882, 0.923423744674992, 0.20292233394646, -0.386314441592495, -0.362055153651599, 0.334092880653461, 0.807311684264609, -0.166293985290652, -0.0853953199903552, -0.0303548168950653, -0.477985353791553, -0.252130120765253, -0.0055098425400003]', 3.99); -insert into credit_card_transaction (time, features, amount) values (158027, '[-2.26937494863406, 2.46896387958507, -0.552642600075627, -0.988644659117133, 0.160638344611072, 0.236830491934834, -0.922422071570921, -4.4312266201294, 0.149168549443, -0.227034492872218, -1.82019661818979, 0.158328577270348, -0.35385758462076, 0.630045288321782, -0.409353791676874, 0.201282263236349, -0.0468619105025272, -0.327261322718866, 0.208884307203662, -1.09095008228502, 4.34236306228897, -2.30014012987148, 0.592053677644645, -0.752815715798393, -0.145816859928819, 0.249402378844361, 0.261954109699018, 0.179065190459022]', 1.29); -insert into credit_card_transaction (time, features, amount) values (158028, '[0.218982140449111, 1.09790666776565, -1.74492772602432, -0.946471343041764, 1.698527879749, -0.906198693069468, 1.47825586101997, -0.182782704675715, -0.668852024240003, -0.519143300728539, 0.534119705382849, -0.407273312819681, -1.12592269750011, -0.275903173647229, -0.71293008682192, 0.431733235906333, 0.100543417670423, 0.789486965485517, 0.0046360903011481, -0.0180003806083725, 0.137315102116296, 0.455681217692153, -0.185570914500965, 0.13173064984024, -0.311413742189966, 0.633974270852576, 0.257281702739795, 0.161364179377333]', 15.5); -insert into credit_card_transaction (time, features, amount) values (158028, '[-1.37985804980739, 0.793973966478004, -2.1841182593307, -1.58662976300357, 2.17592277366205, 3.43477240992112, 0.0423904108320659, 1.61455694935254, -0.402392264638262, -0.711041771121262, -0.612084855682658, 0.334480768591291, -0.267668714270779, 0.927676030968783, -0.316998046893873, -0.100010013617603, -0.0788829651085887, -0.761822095513528, -0.093670397730602, -0.227448774184604, -0.0631493809295078, -0.402987665249253, 0.249758537636261, 0.716907766776778, -0.758521617301839, 0.154248383742078, -0.0614147152215703, 0.0987632617967819]', 83.14); -insert into credit_card_transaction (time, features, amount) values (158029, '[-0.362211311239705, 0.429058175354956, 1.45910877608664, -0.415063083819598, 0.376753437707893, 0.247101576037765, 0.463892835130038, -0.168525855002821, 0.60254735519351, -0.549286374314341, -1.00851993805448, 0.371509925091531, 0.969895138476047, -0.696979819763335, 0.383786008987526, -0.289351076966226, -0.572426595982439, 0.322956910629434, 0.136455979419392, 0.0475111121403775, 0.300434754479481, 1.23722991434846, -0.30200509706785, 0.673191650282243, -0.268942091685096, -0.189464925216867, -0.0615280978292815, -0.041777109568563]', 29.95); -insert into credit_card_transaction (time, features, amount) values (158031, '[-1.17359609832539, 1.31219367933074, -3.45825634278, -0.619697079736893, 2.66309870331589, 2.91628165771074, -0.0232599555609482, 1.82143301701985, -1.21791988415161, -0.649555761964068, -0.67266631753441, 0.328805727364899, -0.219406734016554, 1.78852807794834, 0.0005214058168281, -0.0687095149492227, -0.202580910778195, -0.295119678913572, -0.759983936367472, -0.657311385180601, 0.365553495274159, 0.61929703867544, 0.188888054422954, 0.697252809401397, -0.199772198646894, -0.645708812586734, -0.407238142613834, -0.268139018826796]', 27.0); -insert into credit_card_transaction (time, features, amount) values (158031, '[2.10703262019669, -1.11519976824871, -0.405904513230341, -0.835567684152946, -1.35262247270329, -0.631244740815227, -1.16879948577003, 0.0554114562586086, 0.0750603357167312, 0.949686885904241, 0.726186662830209, -0.479265705127159, -1.24110687068457, -0.0137108318703954, -0.388079653768245, 1.38052206022577, -0.0020924332498371, -0.522249754710248, 0.705432581462696, -0.10657250734388, 0.366803408279533, 1.04190123558376, 0.14886721567695, 0.078629065065693, -0.239717780927028, -0.108852687044709, -0.002471993601708, -0.0594965189145242]', 14.99); -insert into credit_card_transaction (time, features, amount) values (158031, '[2.03536201944366, -0.154987712698983, -2.9587481513792, -0.576317086765721, 2.60688279192775, 3.1435447970342, -0.413552119246551, 0.783741468086949, 0.35960673565204, -0.352244168884697, 0.329686844837848, 0.183611504312773, -0.272471045586356, -0.596868411176443, 0.584212566926748, 0.17900689176916, 0.473972692508747, -0.498335531622195, -0.140900354260615, -0.11560251899467, -0.350812914111748, -0.998261522870848, 0.361272593229977, 0.604955364070343, -0.265481196698076, 0.219402950201712, -0.0396837084348813, -0.0423499198869141]', 4.49); -insert into credit_card_transaction (time, features, amount) values (158032, '[-1.05024221264022, 0.0025401599929001, -0.85418081044805, -2.48765266834124, 0.219093791364313, -0.603868852709712, 0.293886967238672, 0.305268281916422, -1.23659347166536, 0.416070428206051, -0.27696033239687, -0.436862379417214, 0.213481272883072, 0.25674137351867, -1.08280971519994, 1.73422355424759, -0.674230652189816, -0.297489644820476, 0.285521398692345, 0.216416453083641, 0.535336523504374, 1.44054410815674, -0.317221551372596, -0.978726662973967, -0.155548364571756, -0.0847672490390446, 0.428207540143884, 0.192653197490518]', 92.8); -insert into credit_card_transaction (time, features, amount) values (158032, '[1.90167182036578, -0.0647195001622905, -1.63861508134985, 1.43640591990439, 0.261252439525088, -1.07592324896262, 0.61446466869174, -0.355135298819051, 0.383589825877924, 0.248684797271174, -1.19628967061793, -0.213227125200212, -1.22287295610631, 0.716743752258148, -0.35906352334014, -0.61338219693596, -0.111828183856228, -0.508697174021479, -0.210014328323246, -0.228711088928778, 0.0387730037056437, 0.13760484705351, -0.0228478330306491, -0.109929886045315, 0.348948123430657, -0.534909903086685, -0.0298987755607366, -0.0512705504925316]', 73.91); -insert into credit_card_transaction (time, features, amount) values (158033, '[-1.6449835220238, 0.676857125738824, -0.641803229754665, -0.979810092173884, 2.13515893526295, 1.54144440260202, 0.668270006419728, -2.04957136291005, 0.897611610687022, 1.43824335174584, 1.44553893561281, 0.675702938312644, 0.0612233185862741, -0.240336194394959, 0.813795754964867, -1.29579082087597, -0.286346784597244, -0.766463811282719, -0.604375934118076, -0.544029249675438, 1.74304874744952, 1.29832922272758, 0.451478315058192, -0.713430341074749, -0.885625926989528, -0.255318895472629, -0.394642415030952, -0.0821596998051062]', 2.21); -insert into credit_card_transaction (time, features, amount) values (158033, '[2.0570677358863, -0.973300264074425, -1.54151461408459, -1.14665295726593, -0.19470576155852, -0.312563887359672, -0.412593350862231, -0.189196216674687, -0.842893009744399, 0.958963045754405, 0.830056670552292, 0.393755910846297, 1.16428631465264, -0.0372803419834995, -0.302300341671561, 1.31838452480115, -0.380857623001207, -0.736159049996304, 0.864286623153643, 0.248723554463887, 0.429156000647478, 1.03119374123013, -0.0511204869894362, 0.351594557933091, 0.113794501239562, -0.0750378095262471, -0.0492702168473531, -0.0520609687206832]', 95.0); -insert into credit_card_transaction (time, features, amount) values (158035, '[1.59584958501531, -2.35921708123694, 0.483229406165788, -0.335229768345118, -2.16421323035442, 1.13455323929928, -1.98493022637826, 0.525184293765458, 1.43379378232765, 0.445542841269327, -0.0837875030561063, 0.38353532505258, -0.53076877397851, -1.38772587152528, -2.37556323741882, 0.959248718006741, 0.505523951697418, -0.487885396684577, 1.11334643248188, 0.38075929272823, 0.460185925483974, 1.22933945583353, -0.0320707110079302, 0.837740490895204, -0.356425902314491, -0.0548470026180815, 0.0417136861389353, 0.0005329629137676]', 225.5); -insert into credit_card_transaction (time, features, amount) values (158035, '[0.0566021745191798, 0.951098353437786, -0.324917580352524, -0.615017590159592, 0.963199567285392, -0.609298195137936, 0.869264722914242, 0.0165292763594911, -0.351598965802727, -0.671140867571411, 1.16686148455664, 0.750322686533213, 0.152092828571542, -0.86037437195677, -0.974831883207936, 0.477710990373779, 0.149119160237306, 0.208631321480512, 0.0096100439429732, 0.0605345008608042, -0.272931553934858, -0.680832370963663, 0.112028300919858, 0.667083758743021, -0.456710585780856, 0.0857316915837108, 0.217644616221604, 0.0772180147410612]', 5.99); -insert into credit_card_transaction (time, features, amount) values (158036, '[1.37166443259712, -1.11021453135428, -2.12965919689448, 0.577863463863569, -0.189423993257986, -0.669839314585188, 0.317641621828778, -0.0826023233275789, 1.00660845749559, -0.831872204858817, 0.723187944050703, -0.0213423674863225, -1.85589857447857, -0.992139459844658, -0.51679684880317, 0.379995787423229, 0.988287183417761, 0.864674461658353, 0.352855632853052, 0.373842235715342, -0.0442693053525782, -0.697175702504967, -0.123269472388493, -0.554202338304981, -0.241485533441161, -0.11090445837269, -0.0776978691668765, 0.019915980712503]', 329.75); -insert into credit_card_transaction (time, features, amount) values (158036, '[-0.848132112847811, -1.37741691535354, -0.483287887917608, -2.8677557216457, 0.160810180395217, -1.35355120274205, 0.955147119570841, -0.33043950181277, -2.45035025166664, 0.64430088257854, -2.1846429107193, -3.11501515284984, -2.56219291840295, 0.639089315121884, -0.469331325840908, -0.461257390784567, 0.232887105661091, 0.398929582677185, -0.486526548409494, 0.0068392871085084, 0.0776555965243466, -0.0950931954148426, 0.134249179747713, -0.756083218207173, 0.596374994164938, -0.0176637952921578, -0.0671055523432867, 0.107939417872924]', 212.0); -insert into credit_card_transaction (time, features, amount) values (158036, '[-3.05661614363048, -0.925224110668674, -0.0263192523562169, -0.786261554545787, -0.107190115723014, -0.755997836327521, 0.35656638166816, 0.935692834050907, 0.0134966500442507, -1.56590009666917, -0.543473301292723, -0.61088280554071, -3.18765283312174, 1.39810193041292, -1.14833698987461, 0.463934357611409, -0.193650888427685, 0.548328515952565, 0.244120941268683, -0.402671632722606, -0.0613502519687377, -0.687308147826808, 0.0312355883625691, -0.38691925716432, 0.833368448478289, -0.0444888432940726, -0.184565333095616, -0.600208999178454]', 120.75); -insert into credit_card_transaction (time, features, amount) values (158037, '[-0.0739888344128354, 1.4086829888292, -0.714582542706148, 0.997097935627811, 0.476138902435877, -1.32199346330527, 1.10559822160598, 0.0665682378070395, -1.34542812726404, 0.0300651504594178, 1.03830567842148, 0.624854959132702, -0.613251955221646, 1.44707453390369, -0.504046184324323, -0.699419998362678, -0.0366453172997912, 0.283501885756301, 0.605847345023067, -0.256643935477219, 0.437758138153104, 1.20560255392758, 0.0314273144179835, 0.549898660497841, -0.918290936224458, -0.583786191478743, 0.152652206651162, 0.206205322688217]', 13.56); -insert into credit_card_transaction (time, features, amount) values (158039, '[0.0027886393703686, -0.246172130247548, 0.432182731679725, -2.19237956717741, 0.321394057013514, 0.594958072348222, -0.16572393463533, -0.147374491780634, -0.493200471846075, 0.775866716544824, 0.188588081878574, -0.043540043924062, 1.07454308236404, -0.979852863359727, -0.844954857473175, 1.46500106484545, -0.705396584600766, -0.46431381343931, 0.797086909295227, 0.0664926982253571, 0.366367093987032, 1.15076631765794, -0.263078949164154, -0.14935882692341, -0.311047239134237, -0.222004127980555, -0.495862493857952, -0.212741970218743]', 24.99); -insert into credit_card_transaction (time, features, amount) values (158039, '[2.16419493082148, -2.00104284658433, 0.37760078887389, -1.47306988582828, -2.03670395092928, 1.03648682131037, -2.46071020717002, 0.454148486037529, -0.0892711512372141, 1.46798399922231, -0.225823228621129, 0.0726147480521411, 0.559564067320394, -1.37269953202828, -1.55722493210918, -0.0699723044720499, 0.216558915704659, 1.05860125324494, 0.26704623134624, -0.37299309833219, 0.0114172849385955, 0.743688007541658, 0.204592219008939, 0.368546668543463, -0.390333943608661, -0.0559280122208667, 0.093931236134012, -0.0327800085965102]', 18.95); -insert into credit_card_transaction (time, features, amount) values (158039, '[-1.42571176165928, -0.761333263622105, -1.66947983257245, -2.51419912602983, 3.50558649833876, 2.40104651024928, -0.427789419682642, 1.16632274532313, -1.93349121646105, -0.244198425191946, -0.440168854260717, -0.199515450211599, -0.0258042250628068, 1.07450571891906, 0.403130376925301, -1.92707807057653, -0.0249710598933956, 0.888529135329965, -0.895422608450692, -0.230184592841364, -0.138303207387573, -0.594791209485464, -0.226214123717853, 0.698407015559469, 0.267324663082692, 0.0742725849543881, -0.0150263606499974, -0.1504438264428]', 0.95); -insert into credit_card_transaction (time, features, amount) values (158039, '[2.13248934754282, 0.185056806998615, -2.13576503203818, 0.291459747202838, 0.65576440856261, -0.933549359540901, 0.245727499169464, -0.325141942179795, 0.674203962620894, -0.4675105621698, -1.29217289433744, -0.32037648033182, 0.101098181372744, -0.775868465336214, 0.982090739679764, 0.5090970742339, 0.0231045264026084, 0.847991634117938, -0.0399279883164512, -0.179944322138216, 0.125704534431823, 0.544289216361839, -0.147053448049202, -1.06955894178303, 0.389778295805663, -0.0386269905933658, -0.0040235625872427, -0.0420075917906744]', 2.39); -insert into credit_card_transaction (time, features, amount) values (158040, '[1.93071818096019, -2.1262985915603, -0.562190042262186, -1.4455218532364, -1.82450252361202, -0.124037055005639, -1.45575427286702, 0.0155392181642128, -0.957051580803472, 1.62432324368829, 0.213048359491319, -0.303107164840523, 0.241484681918027, -0.515757461364103, -0.756392570310974, -0.0611778675400904, 0.0828598299394405, 0.971968833215396, 0.0220578874096559, -0.108266497907202, 0.172035792111545, 0.698651196919579, -0.0254000635636389, -0.322349843871649, -0.265073476103063, -0.0042389602053724, 0.0102038961761064, -0.0283918397818033]', 173.19); -insert into credit_card_transaction (time, features, amount) values (158040, '[0.162509218802761, 1.08802975471127, -0.479260243527288, -0.599334149389565, 1.07314605318904, -0.692843559943088, 1.03308275381776, -0.142439804949978, -0.151174590384665, -0.858677568184693, -0.74971150340878, 0.221683454733099, 0.816425535030794, -1.18375945087461, -0.308493788149635, 0.358094766225378, 0.244251032482099, -0.240543305875597, -0.154092859470752, 0.077918170415628, -0.346172244771247, -0.810638330925273, 0.0631315141210395, 0.390804827771353, -0.365837069660957, 0.122772471859586, 0.226677785884346, 0.0838988207694406]', 4.95); -insert into credit_card_transaction (time, features, amount) values (158040, '[-1.46807680106721, 0.467623126420621, 2.45083236371981, 3.20817626336865, 1.56031755775091, -0.929101125469001, 0.790742331611271, -0.208926196557915, -1.6909262621155, 0.637981618249925, -0.688561439677695, -0.0625944634063719, 0.0782913373552517, -0.322584496777146, -1.86626015516544, 0.022072553466161, -0.308665818393793, -0.716260989603198, -1.68950103181656, 0.199631019272556, 0.178867090541067, 0.441549696551428, -0.277427413056125, 0.939775631601582, 0.854239509749194, 0.131670153407918, -0.200910210928901, -0.142277778306537]', 18.96); -insert into credit_card_transaction (time, features, amount) values (158040, '[-0.554663867441918, 1.69598933859823, -1.11751215491975, 1.02949087125493, 0.177269366320355, -1.39145947157606, 0.711667832128233, 0.45522170735753, -1.43940361356781, -0.0763629328989788, 0.89993116461054, 0.789421333501349, -0.546852991522995, 1.72789128520947, -0.531925837041507, -0.587260606350829, 0.125424636881326, 0.309455955225973, 0.606178578326564, -0.405067450045686, 0.490366604813421, 1.18907777001833, 0.0497586618628577, 0.552244794856709, -0.91496791959085, -0.59421363851772, -0.091770616237237, 0.123215519009794]', 11.92); -insert into credit_card_transaction (time, features, amount) values (158041, '[-1.76293392713379, -0.0420766603235875, -0.585828673472461, 0.419884423094998, 1.45235514549013, -1.07393606458466, 0.378920224620948, 0.157588740953506, -0.49489869800209, -0.770181841878987, -0.739469022666234, 0.195870829186762, 0.842697240381394, -0.786023912161699, 0.419795631327136, 0.0091587169612489, 0.850120653607785, -0.0105339190085261, 1.21130647772201, -0.349613764650356, -0.314036678559929, -0.492210717579355, 1.20930297670168, 0.494998852989626, -0.410117916050452, 0.298732601406856, -0.13987742712738, 0.227970504647912]', 1.98); -insert into credit_card_transaction (time, features, amount) values (158041, '[-0.0441639798911216, 1.09760257862115, -0.926787159178486, -0.0654949702765529, 0.260679461168122, -1.25691893862939, 0.728401977120678, 0.147748308551425, -0.190933239023631, -1.20196357405327, -0.773128563327046, -0.370485092284141, -0.448474787024962, -0.394868511957962, 0.748157441057619, 0.158706252858903, 0.658645386224814, 0.739165590316672, -0.241773195410174, -0.188618207477022, 0.361979211952857, 0.972935637098266, -0.0485278626837927, -0.166174166003259, -0.348512492892967, -0.145310073569738, -0.0146182766926823, 0.0390811186475384]', 42.81); -insert into credit_card_transaction (time, features, amount) values (158041, '[-0.824361656394776, 0.738153775557966, 0.877998518925298, -1.40715195623649, 0.346294930358104, 0.458448638273054, 0.553576376107043, -0.0527763649874379, 0.981085546524477, 0.17871846817522, -0.0439714728804402, 0.313895261533906, -0.0903441662407898, -0.448423124156698, -0.174655441094708, 0.576735499437365, -1.31456583384812, 0.557798182305857, 0.443348021724407, 0.103890871339873, -0.288169801469596, -0.507147311558589, -0.161148185186428, -1.19487435638729, -0.0739794417946125, -0.258828922296431, -0.158334102168078, -0.109956373101282]', 38.52); -insert into credit_card_transaction (time, features, amount) values (158041, '[1.96625483088915, -1.53752348140964, 0.0243053303304094, -0.822982318869676, -1.60397314416749, 0.144384982394338, -1.63053698969458, 0.187319170048801, 0.708983410720329, 0.651032277238713, -1.16052174914491, -0.830562476265344, -0.0403551176648998, -0.78516558576119, 0.749786415317184, 1.77989603443373, -0.167855432634068, -0.498686097418137, 0.244213521840766, 0.170775184372445, 0.454294206283303, 1.15351758828884, 0.13360739886429, 0.601060331973767, -0.423266284386191, -0.122578046037241, 0.0310195519724147, -0.0117926489430764]', 99.0); -insert into credit_card_transaction (time, features, amount) values (158042, '[1.99629600233142, 0.0351417045860207, -1.75608476523766, 0.561395464021629, 0.05403683856977, -1.46016650143182, 0.214359028075343, -0.30973308887363, 0.766861742785519, -0.457655169974517, -0.501588071716564, -0.548707260035861, -1.19397518439081, -0.479896337484598, 1.07916284788365, 0.203264208736131, 0.521842251297097, 0.562263593416986, -0.504878930275455, -0.235087375541727, 0.203838501122883, 0.653543328575067, -0.0227829135917265, -0.108194162621486, 0.188169175317524, -0.0971691365269092, -0.0119832473075463, -0.0296145365046353]', 29.98); -insert into credit_card_transaction (time, features, amount) values (158043, '[-0.457777589303788, 0.798486572321378, -0.57750546940168, -0.747448840222225, 2.10762988654929, 1.05723194085689, 1.02837833793358, 0.405471526952467, -0.384498732900626, -1.34184348350663, -0.177522764625974, -0.799508659531795, -1.84487697413551, -0.45616078819072, 0.593325848387299, -1.38026916518166, 2.0117863066503, -1.83451224024327, -1.4970597069453, -0.275185231506541, 0.0827588213761465, 0.38856542006845, -0.144280108382553, -0.766350530839447, -0.2640333501296, 0.637221123841715, 0.116934620305455, 0.145000633495933]', 12.99); -insert into credit_card_transaction (time, features, amount) values (158043, '[2.04927596201142, -0.0490032104957632, -1.32290356639624, 0.382513045283908, -0.0691618382140238, -1.37476441471411, 0.264296910452165, -0.401378697764927, 0.619202987636985, 0.014370553501562, -0.714263967296096, 0.215226723532476, -0.0955526031496355, 0.523221493991925, 0.759162336303115, -0.210046954001096, -0.490049672569432, -0.0455446401694726, -0.237972624037573, -0.231202796562971, 0.251325507941943, 0.857701549835788, -0.0080011997298862, 0.079871663432282, 0.257027344310482, -0.111974569951064, -0.0229829349259743, -0.0567345504399878]', 13.99); -insert into credit_card_transaction (time, features, amount) values (158044, '[1.96174359236974, 0.007208771153347, -1.84440280072034, 0.250383138783817, 0.677941074473482, -0.263530471153249, 0.169870672522184, -0.0980095268189798, 0.134735092773077, -0.259575306826791, 1.03750659363432, 1.1562959489835, 0.788697494550978, -0.800281786954105, -0.502622842489987, 0.513588924794929, 0.126607196026686, 0.114828788842056, 0.366525997111099, -0.0050637961386726, -0.292246302737941, -0.825941956542132, 0.249277137229631, 0.149054557132857, -0.253030169833617, 0.171094043764246, -0.0669937279248558, -0.0351393081699311]', 44.99); -insert into credit_card_transaction (time, features, amount) values (158044, '[0.0369544338564517, 0.928230745931255, 0.278472478307022, -0.6181713562497, 0.552089585121511, -0.962948636926338, 1.09179132781791, -0.242033601750856, -0.210762353668994, -0.456567184108027, -0.750728493546413, 0.720437166366282, 1.12448339638087, -0.105948757158573, -0.471907240253493, -0.181979237867702, -0.441466642457278, -0.948212500306135, -0.137955858214439, 0.0372664862704724, -0.244174050641105, -0.470204602245057, 0.0647634158430095, -0.0609980753713009, -0.455773018004239, 0.143925761934615, 0.255991249852423, 0.0987592388082234]', 8.01); -insert into credit_card_transaction (time, features, amount) values (158045, '[-0.309247483098739, 1.00180543151555, -0.268309483740652, -0.764525748135804, 0.30736749719437, -0.584977839035211, 0.52192956943199, 0.430220407997166, -0.349112661676105, -0.451880996120532, 0.0940258508189762, 0.501754560402765, -0.541727087117274, 0.718390767281084, -1.04075934202735, 0.393813694690724, -0.629476587820414, 0.017703039556694, 0.383052416101266, -0.149658251674726, -0.201894687053612, -0.607547921314458, 0.0755701453189772, -0.518071279415494, -0.449754933102611, 0.154741641550326, 0.111154019729223, 0.0198264595129384]', 9.81); -insert into credit_card_transaction (time, features, amount) values (158045, '[-0.861206293696744, 1.03840094345116, -0.0331518723369128, -0.227256311042534, 0.769609492432418, -1.28917532680993, 1.08322060697039, -0.262949962431265, 0.0191922594439277, -0.771674877911098, -0.568950376387317, -0.927775252572413, -1.11075281664584, -0.794593032513192, 1.01384092783818, -0.0120384563152488, 0.685024783604102, 0.787607003775575, -0.0814872069408404, -0.11698872077387, 0.199215877877277, 0.815216801855523, -0.203098080565496, -0.10876863759699, 0.261067269158557, -0.0240388438237309, 0.17339120067972, 0.198801141968144]', 20.33); -insert into credit_card_transaction (time, features, amount) values (158045, '[-0.241626849940373, 1.28959858180472, -0.675589653785654, -0.593099148127863, 0.650708632277234, -0.633474241596401, 0.549143106783324, 0.422089887184249, -0.573524333475638, -0.904355130127726, 1.07846894840802, 1.09184884458219, 0.556076384963949, -0.615621009992703, -1.05386681770079, 0.583516991260149, 0.297428484314067, 0.201185829310297, 0.0033033562518628, -0.0490551327529463, -0.233169533810241, -0.66051166144719, 0.143389430904265, 0.676353174484033, -0.424787340651846, 0.0871579523421106, 0.0978955170621409, 0.0137272179804553]', 1.98); -insert into credit_card_transaction (time, features, amount) values (158045, '[-0.360654838129332, 0.860239140077136, 0.833754660217246, -0.813738756419872, 0.174019334423401, -1.78717448907624, 1.28810029926903, -0.394136592612964, -0.166884145380937, -1.02443143989489, -0.0930819371778737, 0.276586912712384, -0.220502040222885, 0.482987242076331, 0.365797234073995, -0.669498693569452, -0.236544429575547, -0.114863857577038, -0.550372372572943, -0.152980827438772, 0.410894791332264, 1.24272994902686, -0.277647658458909, 0.963613843902349, 0.113509161216559, -0.454053889841847, 0.140073907812585, 0.160139791806169]', 17.49); -insert into credit_card_transaction (time, features, amount) values (158045, '[-3.53061264689577, -2.88036025067832, 2.48195109539194, 0.303782237096385, 0.106190848692327, 1.59604326223454, -0.65241274174616, -0.071531605664762, 1.0583663740712, 1.13919412381556, -0.725774724313279, 0.229251375990574, 0.0095391553411392, -2.09053091334511, -2.18587516878431, -1.43005759226523, -0.589997329663525, 2.25432865405336, -0.169066252644082, -1.21209790907249, -0.667016139235043, 0.202018602813361, -0.576249320925147, 0.250359610108243, 0.568988161594735, -0.511194775072067, -1.25501508515865, -0.177785734716368]', 120.0); -insert into credit_card_transaction (time, features, amount) values (158045, '[-7.04967734500612, 6.22346067143712, -3.16210885614043, -2.93078263669895, 0.819725256439663, 0.907167432014108, 1.40949515131412, -0.316346097659255, 6.97153568748172, 11.2507301329479, 2.2539836102297, 0.286961107779601, -0.59256113251204, -2.82900272905902, 1.36281708448014, -2.26253952911196, -0.893503406472064, -1.25592328826542, -1.60373299502508, 4.58795856941289, -0.881544079669902, 1.20504394844206, 0.0899640482110283, -0.840246947557245, 0.43855777180815, -0.311546096646831, 1.71309115838051, -0.41100974427325]', 0.79); -insert into credit_card_transaction (time, features, amount) values (158046, '[2.03280521148798, -0.168190765778752, -1.19740790236069, 0.222570910849199, 0.0450715220504348, -0.632229879564578, 0.0144109738785781, -0.10256032771085, 0.4053759895739, 0.253956573307866, 0.598680787432403, 0.678560030317362, -0.644389038688123, 0.592825236760949, -0.514696437610703, 0.160241590234497, -0.563147167380652, -0.272859880216248, 0.492084245437282, -0.251979090847398, -0.26096010475533, -0.679069991790227, 0.301855495299331, -0.414057850402678, -0.322704645124882, 0.206222106217416, -0.0762715850543882, -0.0754284358975098]', 1.98); -insert into credit_card_transaction (time, features, amount) values (158046, '[-0.167328708744615, 0.502076965985162, -0.709248280147804, 2.25579829433559, 3.6076305178543, 4.32442509830559, 0.0167230489635649, 1.11206742536693, -1.45782426171965, 0.923083977421996, -0.93825461579807, -0.458739710733163, -0.398904425311608, 0.152294141167741, -1.30553933866091, 0.200734665852775, -0.538628486484938, -0.419112797255344, -1.20236012728672, -0.0119454230980116, 0.227399764661435, 0.539107130658707, 0.0571044265359236, 0.69271393766991, -0.450046241716516, 0.0627919859708296, 0.120056861862893, 0.111686189344893]', 23.18); -insert into credit_card_transaction (time, features, amount) values (158046, '[-0.93680125297717, 0.859082963929476, 1.72689963450359, -0.0290095443872069, -0.637650877659658, 0.390964874060823, -0.349630542134048, 0.652628937018306, -1.87298405265036, 0.438414407580365, 0.300511483751131, 0.622764293069369, 1.08783249743318, 0.190976536834424, 0.225631470433147, -1.09033863337755, -0.343087110161399, 2.16838063655658, 0.167883088615166, -0.238110339353733, -0.432455351083333, -0.797510216120741, -0.148756224400264, -0.421963063761307, 0.273705990076248, -0.601171207492508, 0.257915205607349, 0.0774009332947655]', 17.0); -insert into credit_card_transaction (time, features, amount) values (158046, '[2.22127820372406, -0.606952121788273, -1.08163741102949, -0.812094985770578, -0.605064504217847, -1.27659776047806, -0.285841705864116, -0.405988683176092, -0.491704396296431, 0.747800729002468, -0.566780159868413, 0.0276296278021145, 0.898440698637403, -0.267750013754306, -0.327325580132385, 0.718004819829924, 0.299590474079629, -1.99125619691934, 0.839432489506881, -0.0143138408481991, -0.0674357498789766, -0.11256806132735, 0.279088617023285, 0.0316343741291712, -0.147783149954189, -0.408919015437785, -0.0227827353980988, -0.0567106255960488]', 4.95); -insert into credit_card_transaction (time, features, amount) values (158047, '[0.140334742414108, 0.988536716225315, -0.39913377609429, -0.523617346642668, 0.826930136581668, -0.878958297900041, 0.937666113612492, -0.0782640919640309, 0.0453708461548768, -0.816716583438785, -0.758515857628307, -0.442860148532183, -0.640343034449782, -0.887126737244217, -0.172433734618616, 0.34844984073013, 0.419316581874039, -0.152017683604469, -0.242147742294824, -0.0205571594334353, -0.345192008527678, -0.878755970715596, 0.112053935430627, 0.611925790189547, -0.448163343997131, 0.111436880051032, 0.217763378815883, 0.0835685400772794]', 4.49); -insert into credit_card_transaction (time, features, amount) values (158047, '[1.98741635856846, 0.128297718328412, -2.17222660211076, 1.11094384247555, 0.884337849263309, -0.814837086085613, 0.770939534850372, -0.368249160134696, -0.0372762477405685, 0.356820413544879, -1.13526019154846, -0.357502387260932, -0.783769965767086, 0.944605702525518, 0.384289692996234, -0.309600368849068, -0.477193755203672, -0.269389977986895, -0.336905628926395, -0.187854210092217, 0.125253230408802, 0.285599029948867, -0.0498249382483703, 0.394706530777852, 0.474202643432056, -0.499132400391359, -0.0495449894196223, -0.0521092292615957]', 59.7); -insert into credit_card_transaction (time, features, amount) values (158048, '[-0.300214503768063, -0.162933334967322, 1.32280376377343, -2.1491562582558, 0.381065863994089, 0.420695885651061, 0.219582064290766, 0.0225290248874589, -0.986105706442055, 0.181843257650334, -0.0621327705881322, 0.125501422241847, 0.364053736803903, -0.409741505762836, -0.970637702110409, -0.596337336482429, -1.14063895094659, 1.64412959112626, -0.899804032264457, -0.381196919135105, -0.575682127897389, -1.15056464537517, 0.0713363197876743, 0.0299455931663197, -0.705442277995971, 0.0704700906509997, -0.0692445110013047, -0.07111458521595]', 21.95); -insert into credit_card_transaction (time, features, amount) values (158049, '[2.09644507153469, -0.97628501915331, -1.46967099413564, -0.933683538460257, -0.487283459784679, -0.822467214792926, -0.36957442003371, -0.195519694443509, -0.29032898064024, 0.801543153267885, -0.908640949075622, -1.26695290798688, -1.23151808465943, 0.277169586233122, 0.332156084126636, 0.960644268401542, 0.314319576797943, -1.66619766296907, 0.725841466824367, 0.0250899189457903, -0.0442838792750437, -0.401111799441588, 0.284259300269653, 0.548560319077711, -0.261505852847418, -0.451968848527957, -0.0572070505788601, -0.0429688784613449]', 77.44); -insert into credit_card_transaction (time, features, amount) values (158050, '[-2.59067914020312, -2.35241895396614, -1.7619579783047, 1.51625524879955, 4.53203680261981, -2.30853748647356, -0.965623926731461, -1.31056649496078, 0.243869709406191, 1.55446584399786, 0.138538627788593, -0.810841745165796, -2.80156387027333, 1.18790756444083, -0.277481165236819, -0.685625513197026, -0.354364602696192, 0.430311388125896, 0.87935192358108, -1.70295753996574, 0.713315849279896, 0.712502154921543, -1.28165113119589, 0.401344074019227, 0.0172723168803012, -0.237773722664883, -0.277590496289562, 0.487405951462239]', 1.0); -insert into credit_card_transaction (time, features, amount) values (158050, '[-0.513597802594165, -0.900232839465239, 0.948939260084391, -2.99525546951477, -0.410127710515561, -0.233223606751585, -0.0610858069325511, 0.0590393167763066, -2.32183656275408, 0.664965989769748, 0.410524041434846, -0.571771712453661, 0.0659077712868453, -0.343547555643415, -1.54247591534139, -0.157607814718721, -0.0308884208053827, 0.538091076306178, -0.502213441166136, -0.150921299869733, -0.0128573233440718, 0.0798718559156074, 0.102609192659194, 0.719569923844345, -0.110603106604199, -0.359399596808665, 0.0799190816076589, 0.143022081784996]', 91.6); -insert into credit_card_transaction (time, features, amount) values (158051, '[-2.13023270905677, -1.5787610410514, -3.18169207767389, 1.58934127730561, 2.34468346679763, -1.22881617450677, 0.56420619447076, -1.06631556579953, 0.179431262640725, 1.38374889535392, -0.0690767390556154, -0.819164044414501, -2.65579886961081, 1.36685207688252, -0.415556780821799, -0.564754087769728, -0.308750130676465, 0.640065275555576, 1.06815107645791, -1.97138383146265, 0.792487847206179, 1.52070117244493, 1.87644932367662, 0.259372910667783, -0.514925411724223, -0.35050775745542, -0.442688880779016, 0.420591471807596]', 1.0); -insert into credit_card_transaction (time, features, amount) values (158051, '[2.25128933702913, -1.56747961665041, -1.1070598754971, -1.78379937635581, -1.0040913843179, 0.0232423583873219, -1.28339247667621, -0.0007860213519153, -1.23932920190308, 1.72031788081058, -0.240128720740062, -0.563022207333322, 0.2154570346622, -0.287643782320593, -0.667349709543604, -0.047801968736155, -0.0766481917969821, 0.733799510311714, 0.410680159250432, -0.367735088827374, -0.155355252890769, -0.0146831024915894, 0.101382290890269, -1.12367561552489, -0.181764454384488, -0.130404525197396, 0.012031764639004, -0.0634510771239426]', 43.0); -insert into credit_card_transaction (time, features, amount) values (158052, '[-0.34115724595417, 0.964644552473398, -0.218134661888991, -0.730878570234816, 0.24526386085088, -0.585828250315211, 0.509356143248557, 0.455535300592884, -0.335946920521378, -0.458981005473889, 0.247058049490724, 0.478528671434084, -0.742229395067395, 0.76800348699747, -0.984676394798984, 0.30116596098137, -0.509819226998575, -0.0963832502607585, 0.255574101869458, -0.160263519787752, -0.185118558871185, -0.571858608991212, 0.112359243655117, -0.426056682340816, -0.488695524010144, 0.151080231497952, 0.112084019305846, 0.0194674519463468]', 13.99); -insert into credit_card_transaction (time, features, amount) values (158052, '[-0.119789318628698, 1.06133329649585, -0.603303593353997, 0.0259494895005489, 1.7279710086789, -1.73570033401657, 1.36606629010028, -0.794981045981071, 0.113322269027701, -1.18145363212693, 0.0783111965234852, -0.900299646256578, -0.319989168432693, -2.98287980655373, 0.958912337451257, 0.399436759779982, 1.61168549559879, 1.47471792424704, -0.300211695540034, 0.0238040231780335, 0.12766158215869, 0.857785088548046, -0.425815139879602, -0.227174403446773, -0.555734458726766, -0.224835852779666, -0.162686508077223, -0.183632786561089]', 1.0); -insert into credit_card_transaction (time, features, amount) values (158052, '[2.36926716042377, -1.24609902495935, -2.17382021749752, -1.84850321222334, -0.149322087315866, -0.329846187341586, -0.521771353353859, -0.288142582932259, -1.77465044320002, 1.77356208363264, -0.563013273032314, -0.468343011404381, 0.496816147126186, -0.0320190736121438, -1.49347090499992, -0.626719522782918, 0.0694869130661255, 0.395437286676759, 0.926968070919673, -0.37836931823471, -0.20718148422151, -0.0732488462453094, -0.0921750665800468, -1.37413090758979, 0.338942565013294, 0.0217975539250091, -0.0367176045092703, -0.0903231506057273]', 29.9); -insert into credit_card_transaction (time, features, amount) values (158052, '[2.0963637444315, -0.978955904771515, -0.379211111571828, -0.77742130947897, -1.20045750269603, -0.828603717892373, -0.867580597075723, -0.176196392995108, 0.0071312609131175, 0.681277843756132, -0.680377929643361, -0.125414108550753, 0.752852365944866, -0.544928384025883, 0.166535667978341, 1.25307051954704, 0.07382959889101, -1.5550449940279, 0.628577477890057, 0.068995989408971, -0.0213429643283343, -0.0941116585998622, 0.343448406248042, -0.0358042594702178, -0.485729513290804, -0.48864291418283, 0.0095653100134527, -0.0335264656714153]', 45.0); -insert into credit_card_transaction (time, features, amount) values (158053, '[-3.14198314601995, -0.795747772990656, -3.22872410771548, 1.38515758391949, 1.94493796528915, -1.09048597715142, 0.564201149815337, -0.6840797584683, -0.0635237340593889, 1.30770870918202, -0.246503874820104, -0.760471640699039, -2.62596286208287, 1.66760940504194, -0.446721804837327, -0.549807923718244, -0.117407677681424, 0.70025020216097, 1.21216567392072, -2.08886258992153, 0.795509070343903, 1.65601578542278, 1.69612661033994, 0.280425838319691, -0.65924286915628, -0.348070025252755, -0.19979202404733, 0.62481946422239]', 20.0); -insert into credit_card_transaction (time, features, amount) values (158053, '[1.78848211880527, -0.351577290238326, -0.285186406391459, 1.39775584209901, -0.616029821188238, -0.505693978321213, -0.300441301143996, -0.133206128840839, 0.779853952625029, 0.161292991484048, -0.810229646947379, 0.656901182838524, 0.909853966274774, -0.132602841182037, 0.703080536966557, 0.439654799071828, -0.83667925945936, 0.272857685597335, -0.78995335027845, -0.0196046254298708, 0.286271113531241, 0.820474202985322, 0.0485314358039791, 0.03118923011929, -0.0932808679886006, -0.574754094903624, 0.0452801628693278, -0.0127810764367538]', 95.0); -insert into credit_card_transaction (time, features, amount) values (158053, '[1.96968336046084, -0.0964962250022813, -0.710070699281692, 1.30421340111195, 0.304598537857831, 0.569519045247275, -0.213703634641616, 0.0492712198067681, 1.00191685868978, -0.0685682023356797, -1.66895410745299, 1.21642940014383, 1.31723175726522, -0.592735171005588, -1.22458160561029, -0.315873103242682, -0.351449862334455, -0.875942097212711, 0.40585131572622, -0.141201729848692, -0.549637802082017, -1.26263090270532, 0.369443191798886, -0.0229593685904975, -0.177258375063635, -1.0981111113625, 0.0594869852898803, -0.0263652727104336]', 16.28); -insert into credit_card_transaction (time, features, amount) values (158054, '[0.018341766123318, 0.727123659597603, 0.156352441826882, -0.776670951115936, 0.567948774391502, -0.5571198064077, 0.80772482580987, 0.0474891874312141, -0.121445590483331, -0.216823082825509, 0.347652735291864, 0.17402196719854, -1.08252320043251, 0.50584355611331, -0.916061024947777, 0.189681001620597, -0.661553281171852, -0.105519382949307, 0.265261373748907, -0.0961708359053289, -0.238069028621332, -0.5825375987544, 0.0307865328597195, -0.431211539235901, -0.527421246713587, 0.14995507065977, 0.23994518841151, 0.0809090456634147]', 0.89); -insert into credit_card_transaction (time, features, amount) values (158054, '[-1.01267295348477, 0.4682509695406, -1.02986952527514, -0.398862739545357, 1.98892162336445, -1.16420592840461, 0.623420039709719, -0.0217103407875031, 0.543361210122182, -1.48821877937244, -1.78226040854642, -1.87683133103201, -2.29543278829302, -2.43758977392769, -0.598346139188743, 0.756892243380234, 1.62278982462605, 1.23721813155852, -0.340814767872601, -0.175754753631895, -0.0700599332267562, 0.0716661135428761, -0.545344261056474, -1.24491362176541, 0.0679041714645703, 0.699314925456353, 0.305419867918879, 0.243688356985179]', 29.56); -insert into credit_card_transaction (time, features, amount) values (158054, '[1.52080142915274, -0.77820140092093, -2.33515777704217, 0.415627654807271, 0.472697155083894, -0.328008502571347, 0.541534652446861, -0.306690027602327, 0.806618660709988, -1.02148643126813, -0.915990997275203, 0.824147158203123, 1.54318501257345, -1.73477787851352, -0.159348204685902, 0.191607828026595, 0.708843071553992, 0.16848678962857, 0.31470047402869, 0.558102939924943, -0.107399848638681, -0.668475244865543, -0.145380535231515, -0.0290789200772619, -0.0024418139805457, -0.114532648235638, -0.0580588562981461, 0.0322838287423411]', 301.84); -insert into credit_card_transaction (time, features, amount) values (158054, '[1.87614518394264, 0.585367206769706, -0.693006909770134, 3.58682140007763, 0.687824651650574, 0.36097388059056, 0.19477600225076, 0.051334862224966, -1.31009188811732, 1.58139678231463, 0.614799679320102, 0.729202748739479, 0.279466933339481, 0.384981246767101, -1.58539088098162, 0.973020679561193, -1.00381206025566, -0.345296589289656, -1.04656984314445, -0.221730095974606, -0.216898472520202, -0.691472344504252, 0.373913158281579, 0.69114381887658, -0.263427253334316, -0.40058947549215, -0.044381451930199, -0.0436186223175986]', 12.51); -insert into credit_card_transaction (time, features, amount) values (158055, '[1.80888580120365, -0.699901907453964, -1.41192659426633, -0.101255637515896, 0.479881645809919, 1.04899977221234, -0.329081096024142, 0.385854690743167, 1.04604209477172, -0.162235115444438, 0.610352962401577, 0.6651570526803, -1.32432601827821, 0.591344127646303, -0.0351976285595531, -0.941151749922794, 0.316977202521436, -1.13917460285594, -0.195139696583259, -0.272403055743338, -0.0555865830838366, -0.0084155373014661, 0.175069087885377, -1.64714073823403, -0.286039921996293, 0.0215267139045696, 0.0024246770903611, -0.0761251316043972]', 60.0); -insert into credit_card_transaction (time, features, amount) values (158055, '[2.00736633378888, 0.197605490107496, -2.31292767230526, 1.01068461374767, 1.18453116200442, -0.560293343350268, 0.855922216171058, -0.417799102964725, -0.206546422783952, 0.317477735664009, -1.26250777273801, 0.200762021983395, 0.575368638578868, 0.665491142647104, 0.271658486354423, -0.256295239005763, -0.691988437367095, -0.300106202806184, -0.200621409248385, -0.0837983790833267, 0.117171975793909, 0.317473732195776, -0.117129341848675, 0.0412893239555221, 0.568106602898064, -0.479833437225246, -0.0424349490636987, -0.0525243288229536]', 64.02); -insert into credit_card_transaction (time, features, amount) values (158055, '[1.94395372643321, -1.66526597629775, -0.160880656915558, -0.650764232756074, -1.27218776786536, 0.825805683241033, -1.54479923020897, 0.233190415799586, 1.06182590455868, 0.398137307327396, -1.9860487793936, -0.0694452487071388, 0.825185005314729, -1.45179724494334, -1.23351732279866, 1.02952045707233, 0.261188656245176, -1.12018048572968, 1.13093310692688, 0.249748720111618, 0.142528963631199, 0.508749001765518, 0.0689424769735744, 0.0915231880054894, -0.22785765814095, -0.181669889198793, 0.042885410709068, -0.0170944627421974]', 116.43); -insert into credit_card_transaction (time, features, amount) values (158056, '[-0.913222756375777, -0.510744913327451, 1.27929140325769, -2.82017773729711, 1.31111267119318, 4.72016057949832, -0.411020771708426, 1.00301961695429, -0.326959949696871, -0.284111492030938, -0.517665514849398, -0.440042813876752, 0.140448639739117, -0.758424656728543, 0.779337500016846, -0.895773707612941, -0.919148299692307, 1.86279131492079, -1.90481348258028, -0.391045563574394, -0.168519199521533, 0.0904561733189935, -0.238458982635033, 0.666540047732917, 0.430271781181312, -0.24519088338482, -0.124393824530429, -0.177661275531115]', 112.7); -insert into credit_card_transaction (time, features, amount) values (158056, '[1.0708531479055, -1.75410024912809, -2.0721382931966, 0.548071494560761, -0.296132616690594, -0.711412209990822, 0.877419896822178, -0.470178538313481, 0.270720998143061, -0.0967304851571395, -0.677405440108196, 0.364450705523664, 0.675799371290164, 0.430161777139185, 0.690577100014718, 0.132336723466881, -0.533521141748383, -0.17964920225141, -0.364182532350579, 0.943922454178608, 0.527668292118363, 0.417766437467591, -0.401101369370746, 0.823041813051571, -0.0940491035346733, 0.696898546170088, -0.19268318358273, 0.0298726965962113]', 538.0); -insert into credit_card_transaction (time, features, amount) values (158056, '[2.11366540972298, -0.0625313670485518, -1.37761680582221, 0.239114892693589, 0.234679690120205, -0.779785813488236, 0.179683970482505, -0.295334897237603, 0.570966597658399, 0.0697200461409319, -1.38894221713175, 0.267747679856097, 0.341220675691468, 0.20158958437351, 0.0791675373234989, 0.107418734809747, -0.569733970464571, -0.641929306966707, 0.428297921497103, -0.188928828401778, -0.336504854106543, -0.826149148836059, 0.244729441383997, -0.711774224843256, -0.193430124019134, 0.241988913356279, -0.0709360557128, -0.0670972116220714]', 2.68); -insert into credit_card_transaction (time, features, amount) values (158056, '[2.17748950437641, -0.736223118899005, -1.26581931845296, -0.898160562192686, -0.576158295092153, -1.06449012422919, -0.375654755733691, -0.206660144809882, -0.619716142993168, 0.982149912261311, 0.983832872210899, -0.128171684071749, -0.851120292490032, 0.341596987056181, -0.889000964077639, 0.772553435713818, 0.276721634874781, -1.39710640084506, 1.01968024670217, -0.121797876029927, 0.0753031805703097, 0.209314721577517, 0.214219930869322, 0.0055294797093293, -0.0936291470680254, -0.295017703202381, -0.0443388735571768, -0.0762088661540979]', 4.13); -insert into credit_card_transaction (time, features, amount) values (158057, '[1.55662218761062, -0.943101169547192, -1.6440226162826, 0.273656608242931, -0.311297015730152, -1.08585405552726, 0.539228810860325, -0.2902085829919, 0.525913776016586, -0.0270908697932851, 0.871407119825074, 0.670776196540878, -1.11794847948101, 0.88940814684043, -0.473580664871551, -0.249273005358224, -0.352611506546353, -0.0707406827157482, 0.458629282352921, 0.201190725903527, 0.0527787623877599, -0.309905402533756, -0.0161881089425985, 0.0747400754226593, -0.136448051652766, -0.126490659219331, -0.10688022896079, -0.0314186477557069]', 249.0); -insert into credit_card_transaction (time, features, amount) values (158057, '[1.83604359298373, 0.361213698697015, -0.655592756317554, 3.73259504183759, 0.56033733833686, 0.6867672362945, -0.0094747917690079, 0.145688293058722, -0.925862324135712, 1.52360143185409, 0.276052399683832, 0.613274231957642, -0.0942139231736152, 0.166282664241039, -2.15016435455197, 0.601032023902391, -0.720450860719725, -0.102303684852575, -1.13101251168902, -0.237293879797034, 0.140196254777488, 0.487858669812262, 0.100059137871992, 0.703019309900319, 0.1002290400241, 0.044993597551924, -0.0344375238442478, -0.0510118427526211]', 22.68); -insert into credit_card_transaction (time, features, amount) values (158057, '[2.07213838086927, -0.0747559805958977, -1.1323991419929, 0.384651860390274, -0.0969873196893065, -1.13608531826296, 0.162990761328786, -0.309865398631069, 0.593612850892599, 0.0815749172496382, -0.920360302656867, 0.242443938900753, -0.187408658480414, 0.321802143770461, 0.0812469647377727, -0.0491422172062759, -0.325847267961774, -0.787442879183695, 0.203541367052077, -0.237021141068522, -0.302043489766016, -0.74906876715041, 0.325144726522631, -0.117954866926699, -0.288147096758683, 0.205993564877014, -0.0727743338036832, -0.0619964447660501]', 1.98); -insert into credit_card_transaction (time, features, amount) values (158057, '[1.98859021571532, -0.462435002608779, -0.587557230924636, 0.11017123090759, -0.117172508641378, 0.616844724306851, -0.767758002745185, 0.190371909919723, 0.878871498545837, 0.130784657849819, 0.349101127865736, 1.3660354858958, 1.22693772158787, -0.318401736341083, -0.328976516550753, 0.62099013357787, -0.993467394838053, 0.518741133882817, 0.197178081450755, -0.0661589877002234, 0.183824942046755, 0.736386058590645, 0.100992558019131, 0.117090970567576, -0.187269627297211, 0.556315857716198, -0.0190973181804629, -0.0543573824058145]', 11.5); -insert into credit_card_transaction (time, features, amount) values (158058, '[-0.765962670291498, 1.53491809806818, -0.868302627406612, -0.930869604809474, 0.780307847797014, -0.331711301740271, 0.811608847633188, 0.0645062745036926, 0.64882673174714, 1.13787882635058, 0.266847934858503, -0.0408876551033626, -0.976929475114732, 0.495991378236091, -0.0023198067971015, -0.128953415183282, -0.889554091869874, 0.895297132480328, 0.392475696785222, 0.490764814004673, 0.257964406088212, 1.14669726595361, -0.108220757836914, 0.275280807377137, -0.570435216468638, -0.224848989302734, 0.914426309723186, 0.552461059934263]', 2.69); -insert into credit_card_transaction (time, features, amount) values (158058, '[-0.245899782509229, -0.0827620938579728, 1.21420928337861, 0.287399623540103, -1.57178725891245, 1.0741216709421, -1.35279799970126, 0.771873177463041, -0.641025094870666, 0.63282187978159, 0.485118569179367, 0.571774518284022, 0.709486244611973, 0.0496629865314147, 1.49834619529287, -1.88355984025355, 0.382591003833595, 2.97505797957449, 1.69411614050303, -0.26789931266379, 0.16462551505184, 1.00510898765884, 0.209462737583158, 0.697287078574199, -1.44870822571487, -0.341444893716906, 0.182026131180365, 0.201904513138414]', 62.85); -insert into credit_card_transaction (time, features, amount) values (158058, '[1.91698236752409, -0.623713912063827, -0.577232823699824, 0.366288295344461, -0.469307786772858, -0.0456202979662577, -0.561924202810063, -0.0449573694570374, 1.20875443245996, -0.0437298815327138, -1.50245897451322, 0.502459563158338, 1.00901514846953, -0.43862546121085, 0.376987553939646, 0.441316037009794, -0.74125092120754, 0.132597874519823, -0.106590822227025, -0.0050327428122797, 0.217536387989648, 0.773685050414691, -0.0211668749904259, -0.684280116678274, -0.1427207964521, 0.668831911840868, -0.0236013138704864, -0.0439777340677026]', 69.99); -insert into credit_card_transaction (time, features, amount) values (158059, '[1.94798365241909, -0.266252073363287, -1.69035458571125, 0.534072776862618, 0.0378711580201823, -1.39938068607612, 0.566939381547449, -0.453209128501882, 0.461009214858657, 0.0935906236616408, -0.977401675201871, 0.0384101599545751, -0.705238397468891, 0.547014423457886, -0.374032271789174, -0.534972116160354, -0.0314292583972938, -0.763837166298141, 0.175812437295928, -0.129560109799346, 0.0024706745400765, 0.0309315102264677, 0.02174093520098, 0.0954832350297339, 0.130944280627825, 0.552425588398322, -0.114232311354674, -0.0653240625031898]', 77.39); -insert into credit_card_transaction (time, features, amount) values (158059, '[2.1106679202672, -0.0642292754328239, -1.35288875262305, 0.253614204403093, 0.198800901987926, -0.816760867435516, 0.174848032722424, -0.294696812142355, 0.578496004849875, 0.0722119549318383, -1.34751478425621, 0.247006058377405, 0.253639000630061, 0.220368367261592, 0.0830451977836086, 0.0931471667437671, -0.543202848135033, -0.652544515840614, 0.406060814585815, -0.197249280159364, -0.333803158951552, -0.820839719829356, 0.253804726054176, -0.6528495780223, -0.203907647075743, 0.238540033774892, -0.0712258024889534, -0.0667656915036206]', 1.98); -insert into credit_card_transaction (time, features, amount) values (158059, '[2.03858190118996, -0.08955411837767, -1.20381247011261, 0.195219985323175, 0.178605072225296, -0.565459170803417, 0.0883132225056465, -0.161190559388497, 0.241913599909149, 0.221415201376897, 0.72520740927674, 1.24642271767646, 0.479406746038521, 0.367405233467167, -0.631490197616445, 0.128653259477706, -0.652274249962714, -0.386235030809468, 0.511135195536199, -0.178484407194994, -0.25281349130724, -0.601019562358839, 0.279805146669692, -0.454192386515664, -0.275695009030426, 0.206866735466045, -0.069098074057509, -0.0737559039313933]', 1.98); -insert into credit_card_transaction (time, features, amount) values (158060, '[1.80177445180494, 0.392900146650338, -0.764728756168735, 3.65117947615325, 0.62361486211524, 0.485783941645229, 0.16928057973791, 0.118861011346272, -1.13431680009952, 1.55885926903576, 0.44707433228444, 0.366778481764997, -0.530725938020933, 0.496382585451187, -1.68792662937989, 0.836182813663618, -0.819173081929585, -0.362880374319654, -1.0591322778914, -0.215820446157879, -0.187039833837802, -0.6716725808213, 0.328963596879575, 0.621648001150195, -0.25515828386024, -0.351783951244471, -0.0518704877629955, -0.0420217892639217]', 45.38); -insert into credit_card_transaction (time, features, amount) values (158060, '[-0.397301829938534, 0.937969128694766, 0.19260164696609, -0.447221668743905, 0.763687410290789, -1.22371604276296, 1.41308353320128, -0.350034773814132, -0.323134838637991, -0.544366180893735, -1.30680428146014, -0.667290392605218, -1.38903101562744, 0.533267581613254, -0.73779222116137, -0.583628554593284, -0.102225363787679, -0.50798479494302, 0.0805805951811145, -0.254050466861325, 0.0582550960812433, 0.19986997785849, -0.31617354426051, 0.0701338211751449, 0.0519364843360323, 0.334074414529849, -0.071607107490044, 0.127574872131995]', 13.4); -insert into credit_card_transaction (time, features, amount) values (158060, '[2.06469236749068, 0.193408694015494, -2.76101478000716, 0.278346924701658, 1.14934597735104, -0.720036253641448, 0.597821706634258, -0.251793703557811, -0.0682234807975602, -0.195627696608758, 0.801785796751263, 0.300284623071794, -0.620847662978237, -0.457952610319925, -0.735993348022924, 0.0823938801163987, 0.549978263012657, 0.43057016077715, 0.332295629774418, -0.148589801028603, 0.0561150341531602, 0.258335302379025, -0.0883005333235351, 0.182712034363408, 0.391996497815793, 0.693194987507978, -0.109865682524321, -0.0627451984996771]', 20.0); -insert into credit_card_transaction (time, features, amount) values (158062, '[-1.42370397819228, 0.572465457584779, 1.09822708350118, -0.774047164402353, 1.09377763731995, 1.29415399308902, 0.204210977388848, 0.556054069929106, 0.231303860868837, -0.320949405870751, 0.768519073282095, -0.228708504845823, -2.04109709353267, 0.584103697229902, 0.822126111875452, -0.952882123879487, 0.341498131629051, -0.632408542276245, -0.206573077950201, -0.203519389899039, 0.0507363947725749, 0.253125237298422, -0.417934861266197, -1.54279990752579, 0.425507457955472, -0.0815234616494057, -0.0752547263517826, 0.163206416254446]', 9.83); -insert into credit_card_transaction (time, features, amount) values (158062, '[1.98845313775173, 0.0155463785550837, -2.05446862423836, 0.307062427764176, 0.482226554682777, -0.871033238214819, 0.270083021873564, -0.150762185734681, 0.222280835617012, -0.230374981805227, 1.15404728632482, 0.303632083267801, -1.06481994610466, -0.472607323584188, -0.541608360213101, 0.334733683039823, 0.551883735050448, 0.314664717040862, 0.27859282243093, -0.150125268137629, -0.151170981428364, -0.445142444705659, 0.190413040587063, 0.674193311206083, -0.108955445695942, 0.463384737267867, -0.101600061491616, -0.0443616975130006]', 30.95); -insert into credit_card_transaction (time, features, amount) values (158062, '[-0.090258092684463, 1.14139039856269, -0.638816930492043, -0.795632925050198, 1.06888714359649, -0.33206393095434, 0.84108370763587, 0.0825098789077009, -0.0572781518477523, -0.350121192504979, 0.674263778390358, 0.336462026838403, -0.255058276464882, -0.865091270593329, -0.873234947528042, 0.621130256041031, -0.0082325993800895, 0.40733973503873, 0.165414535188785, 0.150704167252117, -0.346932075109601, -0.827931366051785, 0.0534278827694109, 0.166250725681542, -0.360467649257552, 0.122152712203135, 0.323381732011365, 0.129386280724004]', 2.69); -insert into credit_card_transaction (time, features, amount) values (158062, '[1.78393840767865, -0.190894371893229, -1.06989673977674, 1.76946048833352, -0.118343566898157, -0.206228223305486, -0.194602220264359, 0.0343387299776153, 0.902740599165868, -0.307545997657614, 0.655545797908997, 1.07348912312364, -0.33565060708333, -1.3443237652253, -1.9374670387508, -0.225069983946257, 0.804970598945215, 0.754039698224413, -0.141720615895689, -0.144712320557656, 0.279606828890742, 1.14032378579156, -0.173734321596993, -0.0253093151548956, 0.397831435388674, -0.271393142154207, 0.0498101941227625, -0.0230016886453852]', 62.58); -insert into credit_card_transaction (time, features, amount) values (158063, '[1.82781261500287, -0.834576905584231, -0.621645544756949, 0.16909041609066, -0.660666282262516, -0.122512148342058, -0.593528596264158, 0.0333186916722233, 1.57636098632024, -0.249583361989633, -1.23012765564523, 0.133708837155878, -0.254354817711652, -0.134898284339224, 0.623351119138974, 0.214386707898909, -0.5256815903896, 0.294995114956702, -0.0651426791653565, 0.0005168862027209, 0.214600181948143, 0.593962087605712, 0.0655213087825487, 0.611863865125332, -0.174768612579088, 0.0927212099813462, -0.0104811116188821, -0.0207053864539358]', 106.5); -insert into credit_card_transaction (time, features, amount) values (158063, '[-0.208471673121375, 0.765746531432683, -2.43969216049611, -0.510489315057049, 1.59345592155506, 0.259208779185712, 1.42664875534026, 0.380298244346266, -0.79833639199878, -0.3393056050257, 0.851408499599706, 1.03116905210376, -0.12992712774525, 1.42114026616392, -0.461100156271367, -1.76148787938286, 0.52445934133305, -1.06760294003354, -0.492754264682229, -0.0470819988630124, 0.722246689473042, 2.20751418768393, 0.211029943326324, -1.34368487580256, -1.22555093758533, -0.0442763383692967, 0.457259147355167, 0.298485093693931]', 106.07); -insert into credit_card_transaction (time, features, amount) values (158063, '[1.9685750052288, -0.503187605694809, -0.186967160575634, 0.29692013050899, -0.608110998506472, 0.177803938604807, -0.90062500722356, 0.166651359270377, 1.58544636024093, -0.189579567560013, -1.1485729326818, 0.313805005133515, 0.189228879354687, -0.269033068560807, 1.03635841116761, 0.49197041691924, -0.75605615645576, 0.328640749985723, -0.268989696142519, -0.169288048191564, 0.0610989552812056, 0.31945968456597, 0.266263607045252, 0.399499985843925, -0.347813876971312, -0.421621004214798, 0.0540468896903258, -0.0212510488442206]', 15.16); -insert into credit_card_transaction (time, features, amount) values (158063, '[2.0421643018548, -0.349952391977515, -1.79074160699123, 0.395536913114032, 0.229197672466133, -0.707037798969294, 0.277954114644534, -0.347905142354436, -1.43480805202343, 1.28713879464262, 0.505586637786463, 0.727090373221375, 0.662904726803939, 0.694210139191587, -0.55268002082255, -1.55977061151737, -0.590340582084389, 1.39443525732114, -0.794836091535283, -0.531325754453925, -0.25375492460605, -0.289369065379604, 0.0395283232949813, -0.512523696355468, 0.222686158605791, -0.589403963487044, -0.0055160621338437, -0.0576773706489091]', 58.8); -insert into credit_card_transaction (time, features, amount) values (158064, '[-0.0307276060395299, 0.876928609719564, -0.859382625797533, -0.0627757362236442, 0.514044629885717, -1.32224687914059, 1.08011991984497, -0.43249730701895, 0.306170850395402, -0.482532125877761, -0.523779170219644, -0.348308141918262, -0.116448035449065, -1.00437643432236, 0.764250406646827, 0.0712868989842776, 0.336916405415481, 0.677530937479771, -0.189737276243736, -0.257430504093161, 0.206011154390673, 1.00345028088615, 0.0032128536867709, -0.0953780211001562, -0.293453871503418, -0.218245211970163, -0.589215794727545, -0.54663140666535]', 42.81); -insert into credit_card_transaction (time, features, amount) values (158066, '[-0.25478041067097, 1.10524619985592, -0.5041980143308, -0.31638040561217, 0.0819042645406688, -1.30576703194993, 0.720781474538327, 0.164112699387785, -0.0569017129101983, -0.493393326564251, -1.22545213563873, -0.365084245716588, -0.830087780528719, 0.920310175716388, 0.514557899274165, -0.279633324440794, -0.251826654196782, 0.310848000960627, 0.0318047703994647, -0.15437778167266, 0.411610383379771, 1.25883065929227, -0.0274290109519171, 0.0591158901778585, -0.790844169762277, -0.217807560500606, 0.373386201368361, 0.259639857981223]', 19.99); -insert into credit_card_transaction (time, features, amount) values (158066, '[2.0694111124574, -0.0944565161602246, -1.89463696576991, 0.0333005463213146, 0.552174164354481, -0.554415897363521, 0.254390621332373, -0.137200720847121, 0.553618938654337, 0.0842019321579898, 0.41046765719381, 0.333264020715734, -1.21659894502071, 0.97278022368361, -0.119789745118491, -0.225798825351016, -0.664271103213415, 0.491002510592234, 0.495878432087348, -0.284287436872967, 0.114826476814383, 0.396209068273423, 0.0045715343401154, 0.331236501786823, 0.374232304679169, -0.54531726230948, -0.0248717439015936, -0.0681164080490862]', 5.0); -insert into credit_card_transaction (time, features, amount) values (158066, '[1.92735618586021, -0.0320639091326363, -1.36972351849436, 1.07445917969652, 0.346600915782068, -0.341138405522301, 0.126181722807939, -0.0628143989569896, 0.0709944348559103, 0.495481881522249, 0.82366872738408, 0.465617792954891, -0.758408801833574, 0.842605102860724, -0.0027271488203465, 0.158410886047471, -0.787686662501673, 0.523570494051303, -0.400355259322564, -0.217466696982898, 0.321507040308478, 0.889613100159995, 0.0072119869514688, 0.693271132477487, 0.253799410151988, -0.477652488325716, -0.0135646390466795, -0.0510600274123866]', 35.5); -insert into credit_card_transaction (time, features, amount) values (158067, '[2.16114266476253, -0.854060029930769, -1.22422292720539, -0.755991920097876, -0.225583767532568, 0.208141568471526, -0.690957575795242, -0.0456654080011426, -0.45340033873382, 0.995486125308165, -0.462429821423128, 0.67711357509785, 1.27488392911981, -0.135983046893044, -0.52952782834414, -0.809933413618608, -0.933493430017945, 1.80881437328479, -0.0489505322286981, -0.465241130752253, -0.384093423101951, -0.503541853432988, 0.0935468918116679, -1.36470949389581, -0.202806044100518, 0.619664509245038, -0.0352184736221549, -0.0708506934753829]', 26.2); -insert into credit_card_transaction (time, features, amount) values (158069, '[-0.638750327733038, 1.16379757576115, -1.06638605171706, -0.738521186552809, 4.16902485877022, 3.31734792244742, 1.24586922992769, 0.584440792328399, -0.990152789182, -1.11964181485828, 0.113218483163353, -0.573182957050857, -0.737492764826597, -1.08083879630009, -0.237173110355923, -0.389626388984832, 0.77971922075232, 0.102585895454119, -0.506880070036051, 0.0503806091341384, -0.0886119424821012, -0.114731513291954, -0.671233043014259, 0.581011832384235, 1.28659545749539, -0.376848877928385, -0.120629980274248, -0.156792428479784]', 1.0); -insert into credit_card_transaction (time, features, amount) values (158069, '[1.52011867589579, -0.814491196215313, -1.69389648892886, 0.760903870377673, -0.0591250834615059, -1.09519862443895, 0.837516059259168, -0.533962953651456, 0.192359873345928, -0.0367122909388949, -0.72170418976513, 0.93513768610503, 1.18830936872834, 0.229681241210634, -0.157729244777629, -0.258794490953418, -0.359128436135173, -0.824553440898034, 0.0319933362507131, 0.430454126709364, 0.0254389537284521, -0.376030651530863, -0.0775235410776442, -0.0476972733639176, -0.0898828548764882, 0.156176611097369, -0.11902760346036, -0.0135240795679878]', 293.9); -insert into credit_card_transaction (time, features, amount) values (158070, '[2.08418395137894, 0.303908521995735, -2.98154514900366, 0.142018048669677, 1.37375102175253, -1.07533452220695, 0.955685956751364, -0.57587323352673, -0.277849590624981, -0.351621067503912, -0.701548425374395, 0.421199001457474, 1.52572019036536, -0.815979727463438, 0.290003317186343, 0.160865859035089, 0.307766856026333, -0.0557114593722326, 0.0818417065144045, 0.071418576700575, 0.0525267997822637, 0.197623751689773, -0.149178734450972, 0.0493895756270135, 0.453386015104436, 0.798005231408597, -0.121284959648873, -0.0464489281458786]', 58.0); -insert into credit_card_transaction (time, features, amount) values (158070, '[-0.343731551410044, 0.720867903950207, 0.459598122969709, -0.571910013492466, 0.771714901891993, -1.09997983358582, 1.02608611814309, -0.304518713012099, -0.275976038499654, -0.540643284882029, -0.830411287002669, 0.448358829680354, 0.626856135685181, 0.0464331210729753, -0.441222051332081, -0.259514363693083, -0.374452166012208, -0.866936769643486, -0.008213954349943, -0.134927240608947, -0.128718353942374, -0.310205112947141, 0.159531270113385, 0.004758201745015, -0.887340975274899, 0.0716782780087929, 0.0095292541970001, 0.222699848849322]', 0.89); -insert into credit_card_transaction (time, features, amount) values (158072, '[2.00016959883351, 0.766128039256629, -1.87039526394277, 3.53350417145155, 1.57286743145024, 0.174578087654259, 0.848128074497978, -0.282346483776415, -1.4621501632082, 1.48323505388731, -1.69599978968366, -0.0810134852943552, 0.827041786527786, 0.356109222849145, -1.22241275006295, 0.362259678641628, -0.794762423877421, -0.664584385582423, -1.15606939783326, -0.182054802131374, 0.0890507823409251, 0.32018157466165, -0.0846731790870023, 0.0516898867832329, 0.541006046331634, 0.180406004228705, -0.0789793657516306, -0.063674129496317]', 22.69); -insert into credit_card_transaction (time, features, amount) values (158072, '[1.88150027085014, 0.273816112432466, -2.60402128251999, 1.44802207078666, 1.09693138228262, -0.971803461812934, 0.960368734316088, -0.442158676032975, -0.101192741630322, -0.251601201601777, -0.613569203676707, 0.126107895882707, 0.0943376381598297, -0.626439463326391, -0.224659104293593, -0.316860960561607, 0.700827091061394, -0.0093983856381431, -0.450862367048816, -0.0207693115617597, 0.129221670511681, 0.366761198841948, -0.163769301175009, 0.531805799474019, 0.610572001205469, -0.420042708008352, -0.033006231301453, -0.0180038541198166]', 100.0); -insert into credit_card_transaction (time, features, amount) values (158072, '[-1.97814595416767, 2.64635049402622, -2.31529335583235, -1.6934941590907, 0.998281714705924, -1.10323942055503, 1.23622345402664, 0.153035173749095, 0.985647782188868, 1.66191523226598, -1.62466237781549, -0.422458941754717, -0.480340536985045, 0.470140914997481, 0.0460411152679054, -0.476200480815713, -0.602633337229558, -0.143433243743065, -0.0532807904455965, 0.781890858909877, -0.0365929267987142, 0.576927879032573, -0.181862881930305, 0.0426483217350015, 0.151830428737418, 0.0794291250441214, 0.5419842410313, 0.118671334779544]', 0.77); -insert into credit_card_transaction (time, features, amount) values (158072, '[1.91913455184454, -0.213459991046471, -1.29897589824821, 1.30483076904466, 0.175382146084449, -0.242623831918883, 0.0732764315539103, -0.0620597292290035, 0.5718617525157, 0.360673329287559, -0.0872083753252122, 0.491637975341428, -0.998848267287836, 0.474534681160918, -1.32646294288266, -0.212724882459056, -0.545179281644989, 0.465986841273086, 0.242646491713901, -0.24327106785197, 0.204190637063395, 0.75462977338881, -0.144758718493471, -0.483972030793564, 0.432671542928282, -0.365060270669454, -0.0018003018270572, -0.0646560560494987]', 43.89); -insert into credit_card_transaction (time, features, amount) values (158072, '[1.97043653588596, 0.0232671897061891, -1.57889189507548, 1.33066416293783, 0.223783578160951, -1.00691567359934, 0.435916090049396, -0.195043194787799, 0.233549103466842, 0.489086092842113, 0.424581774145237, -0.0201149032113373, -2.32217014896317, 1.12297448777842, -1.05686235643686, -0.418412247729906, -0.287418121287991, 0.135885378776211, 0.113196004865995, -0.396217498103411, 0.0843971342700311, 0.315080050368324, 0.0067090079020514, 0.0296902205643354, 0.361065183087688, -0.512155346309828, -0.0359444573779361, -0.0734515648845868]', 16.98); -insert into credit_card_transaction (time, features, amount) values (158073, '[1.8703414374326, 0.421265426411168, -0.523970931317917, 3.95531508819241, 0.254851417215812, -0.0437141511002858, 0.151889361530053, -0.0971800236987923, -0.654692521237274, 1.36169942980138, -1.42470061372104, -0.0316516480124279, -0.0065462432417887, -0.0208846651672863, -1.49430997243393, 0.383635170938346, -0.455850690431738, -0.62790386431443, -1.42289538635865, -0.276838485035133, 0.0928865521419743, 0.429187500573849, 0.0731369594422189, -0.0129837459169884, 0.115602913715351, 0.0981990511536669, -0.0255557429282221, -0.0480888658281339]', 22.75); -insert into credit_card_transaction (time, features, amount) values (158073, '[-0.243050688451976, 1.40789375870162, 1.50611478005943, 4.28067568232745, 0.985938562843297, 1.05146027138761, 0.669648609317906, 0.0889721494610659, -2.30187124816434, 1.25793456662633, -1.08240898120638, -0.0242207706812204, 1.62127712468875, -0.0545595966274106, 0.517243082801085, -0.0211377009360716, -0.0224980643624611, -0.40099231883392, 1.58519159637501, 0.444234359177754, -0.391641649438725, -1.22105025553885, 0.264886021441823, 0.411839545020749, -0.692307047366379, -0.193484821393766, 0.160741111803187, 0.183927157667793]', 46.9); -insert into credit_card_transaction (time, features, amount) values (158073, '[-0.0883906696269832, 1.0457325897812, -0.703413615304326, -0.802783837805217, 0.994594745702955, -0.308077915207444, 0.763648874495042, 0.156553735102884, 0.13425396978603, -0.315291542416744, 0.388011205225123, -0.346180582074604, -1.46851520304134, -0.62593342224556, -0.731689613945576, 0.704744590810923, 0.0303386309075489, 0.586521127271906, 0.206203366823669, 0.0743541965947302, -0.367136894899187, -0.943967800912328, 0.0618545021742439, 0.0464609637696135, -0.3895541474266, 0.131772696794208, 0.31657972699435, 0.124739613247839]', 4.49); -insert into credit_card_transaction (time, features, amount) values (158075, '[2.1165195274224, -0.060824070946816, -1.59491954141603, -0.0311329714902188, 0.675114162028371, -0.080999692209259, 0.124207479264702, -0.16030811165515, 0.215602891262901, 0.213127238952929, -0.0857668796331095, 1.23779664779035, 1.27563973429416, 0.179654670094019, -0.676353988908631, 0.440602125509111, -1.09650610509599, -0.057593109967187, 0.944097434637234, -0.101308798725368, -0.31536226117377, -0.752003151824819, 0.145991938746094, -1.35703967873107, -0.11017571628235, 0.259764079741058, -0.0694354956121309, -0.0817189536084626]', 1.79); -insert into credit_card_transaction (time, features, amount) values (158076, '[-0.297797045258832, 0.908675905559729, -0.314027921639516, -0.880273125101702, 1.68567934063896, -0.300726760338133, 1.2749065617148, -0.23921972170733, -0.369280654454933, -0.652169598075945, 0.376737695129232, -0.492210325985142, -1.26615698604864, -0.765064903838997, -0.818380932972477, 0.42673380767152, 0.0577295086447829, 0.691376745131895, 0.43605503811391, -0.0606303064950935, -0.175582969518696, -0.43264404855109, -0.255331958667567, -0.0115791058952027, -0.287894346560759, 0.262798076181858, -0.228093532681901, -0.0501784306677713]', 5.87); -insert into credit_card_transaction (time, features, amount) values (158076, '[-2.6602074511247, 1.8936211706316, -1.29260377955572, -3.38408034817405, -1.02316069888704, -0.657291959032157, -1.08973688801533, 1.90157454288868, 0.711239768530032, -2.71582721739333, -2.10997949575661, 1.62089995588236, 1.47057941860962, 0.996047820814807, -0.127820270233685, 0.774403128642233, -0.371125034994948, 0.0682067767622025, -0.214434082831887, -0.771323929651732, 0.112696894014598, -0.501869296098083, 0.168446636222551, 0.0290380643673965, -0.252142454911719, -0.847440858536893, -1.15541013660752, -0.158711687418066]', 9.85); -insert into credit_card_transaction (time, features, amount) values (158077, '[-0.265969438077506, 0.906718581276279, -1.82266370491374, -1.60895604663072, 3.11120817025141, 3.17050054404624, 0.313669688109596, 0.895223997339977, 0.10309419996328, -0.378379842304796, 0.168465923596973, -0.145475534840891, -0.424501219311756, -0.85875304093318, 0.181240747075413, 0.182828159042802, 0.335994641364543, -0.399791927265376, -0.422706284088929, 0.150024489293798, -0.351020705071461, -0.928440494534973, 0.144588705603171, 0.588682307504071, -0.379282074993107, 0.156865587563356, 0.217273441936228, 0.135748289526853]', 1.29); -insert into credit_card_transaction (time, features, amount) values (158077, '[1.55511747553783, -2.03532233318157, -2.22530657582974, -1.09876359849239, 1.09358606277707, 3.91484244215921, -1.15030983155469, 0.894398897319769, 0.0642651585179147, 0.582680805128733, -0.407682345636573, 0.128119077495033, 0.293379831260656, 0.0423498599023209, 0.897102511659099, -1.51683906365488, -0.346855717470443, 1.57853658310192, -1.2977198694016, 0.016532780104685, 0.142422277162276, 0.382624341664947, -0.111227147305119, 0.721073965123793, -0.0949422908509532, -0.0662146927717048, 0.0218665949151095, 0.0039704643905569]', 287.94); -insert into credit_card_transaction (time, features, amount) values (158077, '[-0.221261638764708, -0.103304153828853, 2.20542754773743, -1.12218827926237, -1.09267219125482, -0.0903064941492987, -0.471941550428012, 0.0721799600464207, -0.754543535878988, 0.0859490568391077, -1.02097872806516, 0.168427594790715, 1.72406017388393, -0.816449678763223, 0.813874879619495, -0.857463465109312, -0.522431136623004, 1.81671006312581, -0.929585623798286, -0.287392453056418, -0.0210638136205978, 0.505404435123536, 0.0070878667240081, 0.0857237645986269, -0.82712709270363, 0.648192267383244, 0.185237867923584, 0.185278236661975]', 29.89); -insert into credit_card_transaction (time, features, amount) values (158078, '[2.08402094416765, 0.789079638479605, -3.01718047834247, 0.795187108140692, 1.15987374997072, -1.84032321026247, 0.906778832378184, -0.5714474436963, -0.163618773274032, -1.07797829518101, 0.553297642647569, 0.371488367456094, 0.784767795239195, -2.61022113128385, -0.144966727305513, 0.169243128733897, 2.25104066877001, 0.297266560685705, -0.449659267664362, -0.0699977612270718, -0.0331642536405961, 0.162090670975431, -0.0095222703956224, 1.0062505607374, 0.388392087951558, 0.652258575487315, -0.0740953565804871, -0.0067569278284233]', 0.76); -insert into credit_card_transaction (time, features, amount) values (158078, '[1.99838560018673, 0.129986208297545, -1.64931100825586, 0.792388306861566, 0.161079372199674, -1.13954206370383, 0.156197342357292, -0.314807152984846, 0.693342533350202, -0.710619337071993, -0.380603727284313, 0.578258459535896, 0.675798348086938, -1.86051560741299, -0.470030344424595, 0.0160251202290032, 1.24960090085785, -0.0166639673022884, -0.204246738466864, -0.109638968119896, -0.0087047927811704, 0.315568331528921, 0.0225802743682575, -0.0575439433555003, 0.0995687108104761, 0.637543331506091, -0.0343152138519227, -0.02658802609948]', 17.59); -insert into credit_card_transaction (time, features, amount) values (158078, '[2.25976613595617, -1.47062749804758, -1.76727811214294, -1.8755881625177, -0.629435402687654, -0.293176926530501, -0.902011090475073, -0.118126255936916, -1.65728848385508, 1.86168826791702, 0.0767373089456427, -1.04510715235444, -0.517837924013802, 0.242347988403254, -0.313713833092114, -0.15857239143508, -0.039297671491883, 0.919154773701658, 0.196057687326123, -0.353099462234909, 0.0902240288026091, 0.526966788356112, -0.0140674327621695, 0.0810120330396643, 0.114534781799811, 0.0547860003552184, -0.038255241777681, -0.064719948751202]', 60.0); -insert into credit_card_transaction (time, features, amount) values (158079, '[-0.545212398316568, 0.491961263810459, 1.2245020289817, -0.347667522942493, 0.211771284121254, 0.33272698266724, 0.397083139847578, 0.194546122755747, 0.538195781139998, -1.60139881848552, -1.33765801215261, -0.0918011458980561, 0.0918307416066358, -2.00899752954312, -1.07420365607947, 0.177373735538439, 0.741228180955831, 0.543247690028306, -0.13400975214764, 0.0987896564955963, 0.13123878238793, 0.578831795655899, -0.460271252770885, 0.577854293320336, 0.976243116080739, 0.873923657778245, -0.0836754640305318, -0.0372597441362773]', 54.95); -insert into credit_card_transaction (time, features, amount) values (158079, '[-0.0008328572451291, 0.888961854898189, 0.372249860341718, -0.689232099351591, 0.494920556445377, -0.830088688313869, 0.975007535745541, -0.117785847499354, -0.446620811082917, -0.268802585677266, 1.00842668372035, 1.33393298770981, 0.806313977910539, 0.135673436601211, -1.20922589467188, 0.0339658565903343, -0.676804343775477, -0.393800746772186, 0.164423332039843, 0.0251051969422241, -0.192908302687729, -0.367926142102051, 0.0565732292012525, 0.0951637003831646, -0.501745069841462, 0.112045143118432, 0.249591320647151, 0.0899986122328242]', 2.97); -insert into credit_card_transaction (time, features, amount) values (158080, '[2.2583215130857, -1.34833411064532, -0.953865411782146, -1.61666133000974, -1.07946743349742, -0.627391155843994, -0.924967770849296, -0.273676714205855, -1.31159929281736, 1.48582189684475, -1.34701686789439, -0.397738911540485, 1.42243897106487, -0.607554671730647, -0.212843837572286, -0.293257978634325, 0.202675156242394, -0.460574134810278, 0.32422423267761, -0.289554492702726, -0.64625848559179, -1.45958472786715, 0.429094624499299, -0.729472130497656, -0.538527342702467, -0.639309157327278, 0.0150640406131446, -0.0374173325297163]', 52.95); -insert into credit_card_transaction (time, features, amount) values (158081, '[1.88270978276207, -0.203215603343795, -1.43003350113993, 0.491799248504603, 0.0694321963626393, -0.638357338202461, -0.0132510104773134, -0.082357905032932, 0.761526372827605, -0.488805909914426, -0.538535782427391, -0.152671488216229, -0.603813733709077, -0.901787142223031, 0.547011316250756, 0.600411416644901, 0.560009514153027, -0.331867502266493, -0.0357466366417133, -0.0372225662242964, -0.545341601500347, -1.72293844054031, 0.489095317382395, 0.436285184517016, -0.687529931590287, -0.116639320969008, -0.0584642948198295, -0.0038387702189186]', 81.0); -insert into credit_card_transaction (time, features, amount) values (158082, '[2.2039336854423, -0.747797057211488, -1.43918339058904, -0.994530400254695, -0.371544446983618, -0.826442473626299, -0.379018554350413, -0.183606275075657, -0.599667186469029, 0.980543537327192, 0.623728126488045, -0.235969863563173, -0.725204653978271, 0.306524795283782, -0.864496499423267, 0.890624428106622, 0.123639216980209, -1.26868660940973, 1.17446876377488, -0.10219103580892, 0.0496109167829102, 0.136933276167255, 0.161332322853014, -0.40638979922345, -0.0372370931151909, -0.269744009106936, -0.0447918127381696, -0.0800404212289757]', 5.51); -insert into credit_card_transaction (time, features, amount) values (158082, '[2.07432126412485, 0.14389739720641, -2.05346938698305, 0.362237265782979, 0.521694220635563, -1.08337985450324, 0.339651669920655, -0.293159185617915, 0.447426178736587, -0.406858354032851, -0.595006445323535, -0.202282673748731, -0.512597423293254, -0.780991692294195, 0.175817754080364, 0.212145726062603, 0.697601501036405, -0.187807040765836, 0.0441634374939348, -0.163964045824354, -0.246453351188729, -0.630256214714182, 0.222933119945107, 0.576435318904607, -0.0890735156663121, 0.451587233586819, -0.0890503053245467, -0.0361410535144938]', 12.7); -insert into credit_card_transaction (time, features, amount) values (158083, '[-0.548143851180123, 0.822260253758586, -0.380725156211691, -0.682493347641176, 0.503978106908539, -1.34706401890499, 0.761621572994474, -0.342549564947644, 1.26698005213032, 1.05502280950522, -1.20314655853046, -0.855941272632263, -1.78943689137258, -0.0142708841722056, -0.163404957666389, -0.0430205210036624, -0.560831109808515, -0.605741094524832, -0.226660389533922, 0.083310601085726, -0.455610981057382, -0.752369861696202, 0.0765051728663474, -0.167718863728392, -0.704190643707102, 0.0645098258752825, 0.30764451080339, -0.0031405174135306]', 8.99); -insert into credit_card_transaction (time, features, amount) values (158084, '[-0.407301501389798, 0.599187496319106, 0.67014941968811, -0.236033023222735, 0.797438884695857, -1.06932663520237, 1.07532557870956, -0.30724107859846, -0.541546651686777, -0.644759885572147, -0.803582917792047, 0.666352269529717, 1.11119947206464, -0.0240481612471989, -0.48261291388063, -0.551613881843007, -0.141960115790906, -0.796515933601656, 0.59561054762285, 0.130111707736977, -0.101881060031207, -0.255756487387776, 0.0141964899946217, 0.097553341006981, -0.370973367667514, 0.299048898807788, 0.0839627756264165, 0.16489980398556]', 30.79); -insert into credit_card_transaction (time, features, amount) values (158084, '[-0.237072882987776, 0.597910832266842, -0.172596091390882, -0.606132166698665, 1.67357890769623, -0.929743957599525, 1.40736556776356, -0.747654791675128, 0.150455311198472, -0.374031785970019, -0.494571992489758, 0.116972511950436, 0.789700774113428, -1.57591091457866, -0.392035642928224, 0.0756915077459882, 0.0382627569813209, -0.322707594717668, -0.150661570295444, -0.0489648439377985, -0.28326946069883, -0.349862651198065, 0.324385183627055, 0.589434932039139, -1.30042191590005, -0.118187287630564, -0.364489361775515, -0.12876546121133]', 0.99); -insert into credit_card_transaction (time, features, amount) values (158084, '[2.09824945538098, 0.228234723328982, -2.16714040318854, 0.245655702719036, 0.868877702880564, -0.645849790913187, 0.291724262842977, -0.317915728773504, 0.461236833290222, -0.516188816332361, -0.848877257139733, 0.362331304334737, 1.2551828906387, -1.00551992440391, 0.877245510935354, 0.398432894544184, 0.0370154867566652, 0.647367372876822, -0.14936707062255, -0.0565945810103014, 0.160369420076634, 0.630621443369791, -0.100925183783467, -0.0022217541687746, 0.405129936588162, -0.0961601084484463, -0.003347910900897, -0.0272299481118484]', 15.33); -insert into credit_card_transaction (time, features, amount) values (158084, '[-0.387600347784762, 0.175436361873595, 0.345720488165518, -0.634227690451022, 1.287967898755, -0.913605260526702, 0.651514658233317, -0.1074617050902, -0.153378237427606, -0.674477593947801, -1.51776112899619, -0.179975316044408, -0.0575058802032664, 0.155591225932977, -0.216837950599842, 0.080193421082645, -0.565630783915332, -0.570894103737566, 0.136256232065958, 0.0125142187678312, -0.252416753156908, -0.874697327263612, -0.0207816826802341, -0.726277594346789, 0.0591533396491715, 0.250699878065437, -0.0949525735234002, -0.0310354979088665]', 10.99); -insert into credit_card_transaction (time, features, amount) values (158085, '[-1.24768990124209, 0.258574818653987, 0.664601588398163, -0.706924067292257, 0.62724172827434, -1.06361941360236, 0.559785144542227, 0.0601835690905438, 0.258546847187433, -0.966875767056081, -1.26764806683635, 0.110571436150021, -0.433278256365815, 0.161993867279446, -0.567670691421919, -0.525199549629115, -0.0591756436558982, -0.513929503159043, 0.211420875090599, -0.0966974159226946, -0.0652445868956963, -0.193173736444832, -0.254527014630197, -0.0670897576134426, 0.0358721855019896, -0.125803706387639, -0.352185941632468, -0.166473857351358]', 10.0); -insert into credit_card_transaction (time, features, amount) values (158085, '[1.09005817592847, -1.61517462149508, -0.711285400444173, 1.711553924973, -1.12510981628332, -0.42838785782095, 0.0700808431066272, -0.138054034929766, 0.976149382964895, 0.0402187791408546, -1.05325854902609, -0.164431316827223, -0.618281516854788, 0.2664261075669, 0.920739069953, 0.554250295836756, -0.72607856618264, 0.533185951016063, -0.90373939641835, 0.610964972796443, 0.487811150016614, 0.505080531497447, -0.246588513068335, 0.0315011843227289, -0.282564424824381, -0.609395185264343, -0.0330880469647394, 0.0467473536239455]', 455.0); -insert into credit_card_transaction (time, features, amount) values (158085, '[1.94517387006848, -0.241569175062956, -0.246097421368926, 0.457002592176409, -0.577646756759342, -0.63147775701274, -0.34280872823463, -0.153340451065074, 1.0525046454637, -0.221808596889395, -0.507017816242199, 1.33657557323354, 1.57133815042497, -0.320969427532141, 0.538119804326634, 0.0657169606370537, -0.56950401100442, -0.463025217706063, -0.162884649896958, -0.106763572602661, -0.147477931271728, -0.227991247391173, 0.347586933704342, -0.0166408111847024, -0.399470291541983, -0.625793538646539, 0.0450018407042757, -0.0252246140384243]', 23.24); -insert into credit_card_transaction (time, features, amount) values (158085, '[-0.176098329170012, 1.15046129671737, -0.15812831391767, 0.756227431753437, 1.22377334394024, -0.265806068705763, 1.28243795759551, -0.101030561181443, -0.858309542063943, 0.17577875023774, 0.149867593381854, 0.339391446164429, -0.435790394360737, 0.695769257534579, -0.96250561109521, -0.869890683401475, -0.221390506695121, 0.31123458859643, 1.22686901128535, 0.094042016136484, 0.138920777072542, 0.671516801536024, -0.341435481249146, -0.539935988797998, 0.058850427388073, -0.362016657506103, 0.431183689553437, 0.229091353584809]', 13.27); -insert into credit_card_transaction (time, features, amount) values (158086, '[2.03415287317897, -0.0563999721090738, -0.892816077470864, 0.517532917514887, -0.373794757350399, -1.46241179829141, 0.173382401142653, -0.345780903105248, 0.55543838498511, 0.0813878377976955, -0.412029156978667, 0.427768737669155, -0.291999661212327, 0.356638052274153, 0.0399994049051681, -0.215081991071998, -0.118665670225141, -0.972814887580991, -0.0106306471366415, -0.257988374221006, -0.265330135880475, -0.644044227778443, 0.396531120191226, 0.451993456753972, -0.363876836152545, 0.170824565200438, -0.0718529614055622, -0.0564233633657493]', 0.89); -insert into credit_card_transaction (time, features, amount) values (158087, '[-1.67347859224627, 2.09736441055119, -1.15218250364996, -0.677685201245432, 0.984340414172702, -1.07562266222881, 1.05655515569714, 0.576071087840273, -1.10565562242107, -1.33014217241647, -0.889691880621656, -0.0532001770339381, 0.0978200420671897, -0.351065480929806, -0.440178978538398, -0.0761450901418398, 1.21090066505197, -0.0447371829138738, -0.12006948406886, 0.0681471398743792, 0.0359491468679062, 0.0651283022173351, -0.569491164576101, 0.582832254352365, 1.36086012745298, 0.84488460334357, 0.0365064488336446, 0.0246598386572959]', 16.43); -insert into credit_card_transaction (time, features, amount) values (158088, '[2.04898285988623, -0.809157412263293, -1.19863065081856, -0.707368616270271, -0.683809072666342, -0.514626119253209, -0.950765730680637, 0.0007066637476348, -0.201098871251505, 0.22521234099967, 1.14492711769896, -0.0748373523805822, 0.300909258462651, -1.94747469079178, -0.312168923631464, 1.89304740953025, 1.05531734065522, 0.0471170297000639, 0.530942430854705, 0.118985910066886, 0.296080882700273, 0.858451639569599, 0.0284410005525877, -0.487760730585029, -0.157783588388586, -0.0857620726217122, 0.0230679318613714, -0.0195537234091875]', 49.98); -insert into credit_card_transaction (time, features, amount) values (158089, '[-1.16198629433283, -0.487939610289333, 0.904127925716778, -2.22301250157102, 1.38003811967009, -1.16433447448122, 0.280990577022542, -0.104294490043446, -1.53165603409977, -0.323412650519439, -0.968318252230365, -0.784159614612916, 0.152972323596845, -0.188819828172465, -0.80056586662978, 0.765583228731952, 0.171859054565474, -1.79014479266086, 0.277835752558299, 0.300254554501421, 0.0910332076619541, -0.140182209560325, -0.252457996905965, 0.610698495978681, 0.93019298021847, -0.26327404898223, -0.0645582105115289, 0.0548755703683155]', 12.55); -insert into credit_card_transaction (time, features, amount) values (158089, '[-0.433889077243946, 0.800554457693849, -0.305057486031491, -0.970588032953791, 1.01851606966106, -0.262851475986909, 0.833047888990124, -0.0180597856725609, 0.0644846972925898, 0.193718585024979, -0.178957026390183, 0.416089939296449, 0.0095756058837613, 0.153093968542073, -0.972174670074616, 0.404863444829806, -1.06875207180648, 0.0912901858579476, 0.607229444378598, 0.0387884814494773, -0.323018518986299, -0.672736826166993, 0.0807835559952665, -1.11258777438451, -0.30034589338388, 0.1885896803278, 0.252166149381054, 0.116147280603481]', 7.23); -insert into credit_card_transaction (time, features, amount) values (158089, '[2.0972824569959, -0.122837377581949, -1.49433508003744, 0.0453884386749687, 0.446506575346497, -0.269671173220791, 0.0611900357318454, -0.121577760337433, 0.347684260640149, 0.242547157747946, 0.000471490289366, 0.799868619863082, 0.223425783169, 0.396046242933982, -0.587579889438837, 0.403646467333126, -0.934799205605278, -0.0286559466527968, 0.842816120488545, -0.17663594525776, -0.308526743594896, -0.780633207367095, 0.194339703658428, -1.0966393660842, -0.182098193310612, 0.245392637009632, -0.0754371501457788, -0.081112124469335]', 0.89); -insert into credit_card_transaction (time, features, amount) values (158090, '[2.04022698036619, 0.658167032476465, -2.3487897119355, 0.760713881935295, 0.654877582400217, -1.70245314609606, 0.434325669809334, -0.446553374295066, 0.344668574926125, -1.23910966579679, 0.429646187388238, 0.357713724979096, 1.04426080147407, -2.74139513460311, 1.00033307392637, 0.662443419583762, 1.76502281758142, 1.05022075325544, -0.777519740340114, -0.0915884423184959, 0.115642016200398, 0.596336920673733, -0.0536546823590322, -0.19838279863096, 0.27911496096633, -0.101090590032899, 0.0302855162472742, 0.0095794889283817]', 1.0); -insert into credit_card_transaction (time, features, amount) values (158091, '[1.99373726003452, -0.128551236105866, -1.21210779884686, 0.277867324408519, -0.072599845457297, -0.977883338490194, 0.0823197767094163, -0.206173711074434, 0.416070334233448, 0.176719786770898, 1.06998956339337, 0.865144122556398, -0.341132433944465, 0.730141816206901, 0.151610672797818, -0.050163913392258, -0.666130643785583, 0.397455026153235, -0.0701331750669008, -0.243053398794669, 0.324767308954143, 1.0401913437532, -2.11894081769692e-05, 0.0480036787816706, 0.183149230777361, -0.12138387454437, -0.0205936778891407, -0.0663924774679762]', 11.1); -insert into credit_card_transaction (time, features, amount) values (158091, '[-11.6373442487818, 9.0848328835584, -10.0612756405108, -1.09557785929482, -5.55419239170499, -0.0561926905982396, -8.49487653967082, -0.1933009134856, -1.9676981611826, -1.98497239267709, -2.5323207435467, 4.0255418758943, 0.411374104930579, 6.88131039796648, -1.5039953417143, 1.93370903532687, 3.11611940879729, 0.990513274007641, 0.0652677529649987, -4.23828977636867, 9.05864041259056, -1.99644529309411, 1.79782625063198, 0.111193497118115, 0.0961089492494726, -0.0714180539927687, -4.28261248876486, -1.05808292112014]', 38.52); -insert into credit_card_transaction (time, features, amount) values (158091, '[-1.06892760141129, 0.679531804648469, 0.496769394920854, -1.10897952955767, 1.78120525080318, 1.42859514307248, 0.565155374231507, 0.488640447428433, -0.442491627784629, -0.36558883735647, 1.45487714890164, 1.16339016572397, 0.223867215645962, 0.304549993892942, 0.0805396832700647, -1.1533923770563, 0.433267526309248, -2.09889428723114, -1.03189287730293, -0.143834738902689, -0.101692991122473, -0.0732590155041425, -0.0778990427242523, -1.73826612603025, -0.466285170297431, 0.324106203458366, 0.106841904127213, 0.183326479889934]', 3.57); -insert into credit_card_transaction (time, features, amount) values (158091, '[1.98983911549471, -0.167762601128678, -0.220172748471614, 0.438222040230277, -0.554844735846896, -0.639797879983998, -0.373488526050164, -0.147339565414892, 1.05522786124679, -0.211040134713208, -0.507349059861029, 1.33562329001869, 1.56721616377068, -0.32620370340295, 0.535211320906856, 0.0626675588977888, -0.570189451865006, -0.467762211343751, -0.155500347584958, -0.153846534119709, -0.161487052325711, -0.215788787332005, 0.367964890177989, -0.0178271556624584, -0.390981194520225, -0.623327737766295, 0.0493702941945669, -0.0292502160887878]', 0.12); -insert into credit_card_transaction (time, features, amount) values (158092, '[-0.945571368518438, 0.345248661102196, -0.104713006087022, -0.375220681723907, 1.29294656348924, 1.5020201731981, -0.268593298222835, 0.897182453812541, -0.578976354767741, -0.452630233812574, 0.969874257297121, 1.04823606402067, 0.41313439818138, 0.621214788828823, 0.565115248463854, -0.921622321105943, 0.577927384066225, -0.987319320929827, 0.288758252417057, -0.16256167796487, 0.250844899541348, 0.721966946636435, -0.131584611825962, -0.643500804193784, -0.963155428449924, 0.697784785409688, 0.0226496159612859, -0.0186477525200934]', 10.0); -insert into credit_card_transaction (time, features, amount) values (158092, '[-0.209248039182748, 1.21046148850354, -0.622695514067446, -0.902893326213596, 1.18818944175993, -0.281837134425201, 0.996983919657194, -0.0990396653633745, 0.337140466220848, 0.181288498260055, 0.652507690444982, 0.0486284040640577, -0.604548129186652, -1.08134386226685, -0.785732542280408, 0.556438402618319, -0.131996816515832, 0.433140761214962, 0.173297280670453, 0.335195668110087, -0.436383202740261, -0.867710038422543, 0.0157292701385595, 0.0668860011035545, -0.336403674983663, 0.104436032475606, 0.26002898699554, -0.032387403453054]', 0.99); -insert into credit_card_transaction (time, features, amount) values (158092, '[2.12688561612748, -1.12033650643079, 0.0412171574653195, -0.520921338665569, -1.43041239998944, 0.0318491089562395, -1.53857563764103, 0.119997478410251, 0.504754086055302, 0.83086289711949, -1.78090165980089, -0.440107733713972, 0.433077761028875, -0.515802819316194, 1.16190874333842, -0.338854218444129, -0.822684668921011, 2.01228175000271, -1.04100016339986, -0.56189718643089, -0.189582605382326, 0.053209387922822, 0.250125297174141, -0.7224056769836, -0.612606122269372, 0.659214522437881, 0.021935615860717, -0.0374890291062133]', 10.6); -insert into credit_card_transaction (time, features, amount) values (158092, '[1.96935560368262, -0.389883230467109, -0.860295217933778, -0.0691540389844665, 0.135502656346451, 0.569185284517156, -0.570246987805748, 0.128296357910764, 0.968137439068462, -0.0965435611373025, 0.354805148800534, 1.51083945074064, 1.54646829219618, -0.106936781341768, 0.382057082656561, 0.523140069573143, -1.28349787732976, 0.946080774368326, 0.215247563958677, -0.0353247654014468, 0.250311428018148, 0.866260100202517, 0.0072383603202719, -0.170872031855957, 0.063280242421168, -0.562632724884825, 0.0564978371889291, -0.0380977033897141]', 30.0); -insert into credit_card_transaction (time, features, amount) values (158093, '[0.144284134251589, 1.09701381060509, -1.27984817797986, -0.248399162918321, 0.506294047342374, -1.26029698830937, 0.969009356706899, 0.0716723841132748, -0.486967991748855, -1.19718257169359, -0.302282031039785, 0.677959653353355, 0.931052162282815, -0.820926142919542, -0.612156053806736, 0.177681206447504, 0.7250286079839, -0.354932607331892, -0.512536008426331, -0.12969062150067, -0.0199763616884816, -0.147434002706866, 0.349884271557535, 1.08153178203605, -0.746222866277082, 0.135989146805322, -0.133632375042151, -0.0189512121768577]', 52.9); -insert into credit_card_transaction (time, features, amount) values (158093, '[-0.902479634210226, 1.06456754642278, 1.73902148032602, -0.480557081508535, 0.0314875589730367, -0.363817899495278, 0.781053376846971, -0.439609582800063, 0.607835262754474, -0.0817150309896642, -0.602260850649336, 0.566248284545627, 1.14575037981274, -0.777811370224999, 0.525559254174712, -0.27114738682877, -0.64226912850371, -0.191716059596236, 0.382167300429845, 0.0241779080986937, -0.158733980848731, -0.0930980463870523, -0.112271607997907, 0.0392800682048323, -0.383921818964599, -0.669129153950408, -0.981054582144627, -0.593218626625402]', 10.0); -insert into credit_card_transaction (time, features, amount) values (158093, '[-2.3082093081445, 0.516493102417341, -0.465689627415325, -0.361627055738481, 1.20385129752107, -1.69198013493389, 0.831126471614565, -0.220078299250809, 0.133947881463859, -0.45390238400603, -0.321428030253902, 0.278990305672809, 0.870206623696915, -1.09812131966602, 0.584610964931516, 0.13356764643819, 0.33816186420952, 0.403840288740456, -0.623775450638294, -0.10110594924905, 0.144765254720549, 0.846619836996749, -0.57427240524202, -0.0222217951323605, 0.384077794559862, -0.160721315925312, -0.221768432854791, 0.23606970982294]', 21.71); -insert into credit_card_transaction (time, features, amount) values (158094, '[-1.67552857998417, 0.789513581650327, -0.144200820367981, -0.177578885583882, 0.367189376223954, -1.63713296563304, 0.618681684342823, 0.0472270149307917, 0.0309280894020112, -0.0555025112303673, -0.550045375047246, 0.188680932587619, -0.0345510673779806, 0.578769003699882, 0.66328298375021, -0.484036855709808, -0.0959406586240212, -0.0627669500446129, -0.0382383674992371, -0.432645476035113, 0.226635517892696, 1.27325858221429, 0.364075160135979, 0.440989083181606, 0.0390955556747681, -0.0957686566466375, 0.35789741608757, 0.107298306242012]', 0.89); -insert into credit_card_transaction (time, features, amount) values (158094, '[-0.0728698912035648, 0.794483211035932, 0.554977612465192, -0.557569649482135, 0.248454464677606, -1.14635090102269, 0.908535971754675, -0.105277483184297, -0.372240093731409, -0.246169446628157, 1.31273959452789, 1.13093504214468, 0.0452788551300183, 0.301762261814226, -1.16693675415454, -0.0722654900478796, -0.465999033855831, -0.461733859289495, -0.0082963914979424, -0.0169258088447094, -0.164664198163728, -0.340209712214373, 0.136421982557808, 0.547460822469341, -0.584690323268993, 0.0851112834151908, 0.243376587885302, 0.0944527549640905]', 4.49); -insert into credit_card_transaction (time, features, amount) values (158094, '[0.0076762342675182, 0.602594305469068, -0.346944258362736, -0.630931423287438, 0.537102720279461, -0.639662617786215, 0.953878169041618, 0.008705010827957, 0.240763866096902, -1.36100304416301, 0.521679806275906, -0.069937066555374, -1.418475364914, -1.15305078755537, -1.12579890375648, 0.353552293399419, 0.660586113180797, 0.908240870549429, 0.332585135742902, -0.0856111947097896, -0.122386560819535, -0.337306762812071, 0.0158253349827007, -0.495349777803418, -0.320215450071142, -0.160658216895598, 0.0369745959354867, 0.0614416220363263]', 61.16); -insert into credit_card_transaction (time, features, amount) values (158094, '[2.15929692637919, -0.920283439608135, -0.637066089279967, -0.912802464072116, -0.787560956950413, -0.261056085866641, -0.964008885733249, -0.100728899683998, -0.0489112509454606, 0.688319090935912, -0.705723104940489, 0.0861596228425579, 1.43715871889795, -0.736503236179224, 0.142668314499269, 1.0995716356906, 0.0551134679616648, -1.30800729622118, 0.420979136030512, 0.0865952466864251, 0.332727685032672, 1.06028550637764, 0.141628550941401, 0.67247754066917, -0.0921963402278394, -0.115733064794957, 0.0148910784904178, -0.0387728287144674]', 19.95); -insert into credit_card_transaction (time, features, amount) values (158096, '[-0.760820454007006, 0.771373118508915, -1.18205937887548, -0.840363740520401, 0.899014319077187, -1.84189477764295, 1.40246651726575, -0.0703127636718442, -0.614653352231739, -0.758855184747824, -0.963621443258745, 0.216288463779397, 0.0667266735314359, 1.02384298191477, -0.178536956902159, -0.601902716048616, -0.186093646034804, -0.430376500503685, -0.235896501288051, 0.082547212738367, 0.372180077851166, 0.918660692502304, -0.0422342629547716, 0.043406045696035, -0.269458277180909, 0.0864687733086281, 0.260017702307211, 0.14680080513015]', 68.8); -insert into credit_card_transaction (time, features, amount) values (158096, '[1.97897161253861, -0.12271942589058, -0.818335039918767, 0.437949366216083, -0.405756537761386, -1.22369453833558, 0.0599579047979109, -0.195545557354451, 0.319208864341505, 0.255995578532438, 1.37619779107814, 1.04631494416936, -0.621433962788435, 0.605794473697494, -0.64656236173159, -0.0496292982180108, -0.305156611300904, -0.496567567758861, 0.226480363475753, -0.26339181201177, -0.20615817388538, -0.524010360318269, 0.403332219604305, 0.535034931250825, -0.420794859830978, 0.145173663531665, -0.0771295292833862, -0.0654431228871805]', 1.98); -insert into credit_card_transaction (time, features, amount) values (158097, '[1.93684448474331, -0.459957053368673, -0.436654368362665, 0.266731859007182, -0.531146053282273, -0.135797893216158, -0.619705804906207, 0.154217241718442, 1.17721755098334, 0.0187772005945139, 0.433166713154755, 0.641003868045781, -0.799038135535103, 0.319363937084133, 0.12466749101519, 0.488390322821929, -0.830853302875314, 0.450556069140534, 0.294263149302829, -0.242283824119552, -0.151658903364968, -0.379608174808109, 0.317836324793646, -0.534196990416578, -0.454452184667279, -0.610169811420252, 0.0260697326757262, -0.0452457544574447]', 18.99); -insert into credit_card_transaction (time, features, amount) values (158097, '[2.13724038835429, -0.0767820880380639, -1.49953745402167, 0.171789674906908, 0.361412519393058, -0.619948570685321, 0.159668625276571, -0.2668268681067, 0.616546030792667, 0.0759534963100051, -1.67495891149597, 0.0826522950004897, 0.221711034128348, 0.217681086666965, 0.118560583888986, 0.198960273344012, -0.664590594500009, -0.527720051793603, 0.53834615359303, -0.194121966998247, -0.358436791059324, -0.89202155091498, 0.212811028669473, -1.00438021385273, -0.160149620411906, 0.260572172472175, -0.0720828416284717, -0.0706878727445317]', 0.89); -insert into credit_card_transaction (time, features, amount) values (158099, '[2.04387672336769, -0.0846674535145838, -1.17046565587378, 0.221744277516308, 0.0975798411436982, -0.699349269871648, 0.0941374882679135, -0.184303467952483, 0.258268734527393, 0.234205600915405, 0.723030270600547, 1.181885652391, 0.336264536122014, 0.392713651797382, -0.670224327610842, 0.17018457001624, -0.672234711203558, -0.307112913648747, 0.554358658703094, -0.185525474911905, -0.255666552293944, -0.620343779670996, 0.285449724897866, -0.327792936351933, -0.275322977020132, 0.197380355771073, -0.0728309121097359, -0.0728667314004909]', 0.89); -insert into credit_card_transaction (time, features, amount) values (158099, '[2.11661697421739, 0.13988800206923, -1.95384656993448, 0.277856936910916, 0.703663218772156, -0.540145171684285, 0.171286196442692, -0.19686759770259, 0.538975465110964, -0.376604706201481, -1.10632820495494, -0.0647437483990968, 0.141881405729279, -0.874788152684911, 0.251856817102947, 0.491800875002354, 0.25802583842177, -0.109576109857345, 0.2779795637991, -0.137902310275977, -0.404049926017248, -1.05691684611398, 0.266147493008966, -0.0631275766619684, -0.179437534902895, 0.208739723439506, -0.0636972154647032, -0.0365257073002679]', 1.98); -insert into credit_card_transaction (time, features, amount) values (158100, '[0.342793110429886, -0.287261030687008, -0.0933252341703406, -1.98418595427963, -0.439231421928649, -1.30291887895992, 0.953927075161979, -0.725135954950892, -0.24768179211501, -0.200636040787097, -0.604255406676331, -0.286895491866822, -0.101875221684159, 0.483180366917527, 2.2764595567812, -4.07312753230281, 1.1296607636659, 1.7207327520418, 3.05152389374649, 0.042896461353378, -0.139282440121017, 0.425724045137724, -0.0981341315100914, 0.0641253377323846, -0.189590036827337, -0.33438345492012, 0.0804654432333014, -0.0350896019737029]', 84.98); -insert into credit_card_transaction (time, features, amount) values (158100, '[-0.0193845230578541, 0.0813437116183215, -0.123084684200039, -1.58005600867001, 0.93049143996304, -0.103879633803591, 1.14701778970959, -0.320478472201595, -1.5751004504366, 0.500310713256511, 0.0489999403243191, -0.0850124452179171, -0.321662537639655, 0.216845786602834, -1.57096092005955, -1.89677815738097, -0.35518412949643, 1.26978681811476, -0.295770640168619, -0.375383949353751, -0.285242347633549, -0.204706377164344, -0.0997544452359128, 0.294668911114002, -0.346887294312847, 0.419339624073865, -0.0716772597504023, -0.0581369955977684]', 47.61); -insert into credit_card_transaction (time, features, amount) values (158100, '[0.077338945991989, 0.78043299830265, -0.640003489208689, -0.143651965877503, -0.0497355010155829, -1.02703426150194, 0.8402653211067, 0.050636154370072, -0.308546339817244, -0.747207653142655, -0.772159076419779, 0.74030875278531, 1.20104953565085, 0.463585501741128, 0.457891359104055, -0.26833922711374, -0.340616230476837, -0.0014976789631764, -0.172396361044441, -0.0498765453656851, 0.455633963603872, 1.23155707232782, 0.0981427884553025, 0.0398010447751219, -0.216981162458766, -0.15344982684261, -0.0987349005751729, -0.0655036905744334]', 85.25); -insert into credit_card_transaction (time, features, amount) values (158100, '[1.93948896381013, -0.469871527616659, -0.355205262153049, 0.312484966808565, -0.530844012474013, 0.102405750625639, -0.761942355112931, 0.179919771659607, 1.20508337731698, -0.0021177589180198, 0.713071855093997, 1.10803333132093, -0.0234264573552982, -0.000430513415361, -0.177394465297379, 0.289598893202039, -0.755625472908917, 0.724243366446333, 0.0547387499636053, -0.185511685032334, 0.241436059282215, 0.875160788592062, 0.147748254005445, 0.786338120445995, -0.115365554239363, -0.268819395548443, 0.0325550531980302, -0.0391637294338968]', 9.99); -insert into credit_card_transaction (time, features, amount) values (158101, '[-0.265021807974238, 0.697274956114369, -0.688388679669962, -0.869974136845275, 1.64982583027218, -1.17166941315847, 1.11046674296122, -0.162572723194628, -0.153901002016783, -1.22908199068775, -1.1797801547767, -0.824489707332643, -1.09346658575399, -0.84617004621226, -0.619360685699456, 0.476813991349286, 0.348184745220955, 0.0947197243395556, -0.648285495929034, -0.152868525317181, -0.0981157713555551, -0.38299439991256, 0.0410077863271335, 0.354661677272148, -0.745871456918168, 0.104786055970378, 0.124732442157054, 0.246742116830861]', 7.32); -insert into credit_card_transaction (time, features, amount) values (158101, '[-1.53465908150274, 1.83862678673387, -0.225463045383317, 0.627528112515424, 0.0814690901189145, 0.158890236656975, 0.778377446016933, 0.292274706503078, 0.587254266549266, 1.48982586201722, -0.0474177881095055, 0.347026558632778, -0.582561172291179, 0.018768806241311, -1.00934320804571, -0.67532281831666, -0.299188674044467, 0.622987891314272, 1.11996841402817, 0.492633683372837, -0.0403318229394232, 0.861166426769615, -0.302101170870214, -0.489750077901004, 0.105817068631284, -0.391771931245495, 0.190892164946714, -0.32077338487077]', 50.0); -insert into credit_card_transaction (time, features, amount) values (158101, '[2.09053781353743, -0.547143517118784, -3.29258777410779, -0.537067214986212, 2.5665972963547, 3.09317919064836, -0.188776529132601, 0.555901723556236, -1.36214212417098, 1.18274884948291, -0.223201049388393, -0.12555819244218, 0.0041256952931892, 0.868090946799658, 0.454891850807344, -1.9839575136078, -0.266557366563513, 0.809412645089907, -1.28246339681873, -0.533037281324756, -0.218750585962745, -0.255323010400983, 0.0725633230485925, 0.659471849256448, 0.384969116239264, -0.466116121958146, 0.0054405674281493, -0.0582073378255668]', 45.2); -insert into credit_card_transaction (time, features, amount) values (158101, '[2.06360645255844, -0.0080988959583393, -2.1840391122884, 0.253442875798909, 0.981182324095781, 0.206991589632901, 0.0280561470070728, -0.0380252177049686, 0.450482617226158, -0.337788933248111, 0.216127637494887, 0.935351993727404, 0.771354281599726, -1.21895805439434, -1.16659693185526, 0.296451667504787, 0.27291902563184, 0.661789895473593, 0.556792128241113, -0.0651142166440278, 0.0566303460881829, 0.455676732574935, -0.132063635577595, -0.349217482142836, 0.343083153233551, 0.738252366421223, -0.0561431944882507, -0.0558538496660642]', 11.5); -insert into credit_card_transaction (time, features, amount) values (158102, '[-1.27296375104223, 1.88699037994696, -0.756176621991244, 0.957220735304354, 0.385955420695301, -0.805606952243749, 1.00840441500542, 0.145876223297351, -0.634180010522493, 0.187680483544885, -1.23468672343011, 0.338744163777208, 0.319722725289077, 0.664042348234363, -0.365579616732331, -1.08212770506513, 0.338923039821917, -0.386382316018162, 0.799782946402919, -0.228475712430853, 0.177829637118788, 0.707880143356651, -0.142214885799575, -0.0535052591581526, 0.0497312265199262, -0.44020018233763, -0.463285623672708, -0.137061202222681]', 28.4); -insert into credit_card_transaction (time, features, amount) values (158103, '[2.08843181991689, -0.597663861725287, -1.60705924591156, -0.525817581719043, -0.141958731875097, -0.82804042526325, -0.0067765119945119, -0.295739523510996, -0.859592029815763, 0.951878959883511, 0.46821198409591, 0.650193689374901, 0.364914501521249, 0.632864186690209, -0.169142137730976, -1.41299775757809, -0.616786348629523, 1.45928476554466, -0.296017349636417, -0.530784952308861, -0.449200137458304, -0.870255972295054, 0.195789250071528, -0.557604037544169, -0.0947448225683981, -0.485496188727246, -0.0158361016860141, -0.0568455100591142]', 49.6); -insert into credit_card_transaction (time, features, amount) values (158104, '[-1.39764319371123, 0.682598729893661, 0.919836071529467, -1.71342789904981, -0.587311399409774, 0.322204267331025, -0.651363349910599, 0.959821384620919, -1.36961163945888, -0.570251734356641, -2.10664646002848, -0.211185450556423, 0.818009377711385, 0.122351819547098, 0.104790088977273, -0.62483644112955, -0.249740803889989, 1.39273780442764, -0.565480027598169, -0.601613790850221, -0.526418710070052, -1.42073393434623, -0.113685596832628, -0.005276844422918, 0.210579362064958, 0.397052768195102, -0.361447905737923, -0.0898720733709888]', 18.0); diff --git a/pkg/udf/pythonservice/demo/dist/detect-1.0.0-py3-none-any.whl b/pkg/udf/pythonservice/demo/dist/detect-1.0.0-py3-none-any.whl deleted file mode 100644 index 9e78c923f4ebb..0000000000000 Binary files a/pkg/udf/pythonservice/demo/dist/detect-1.0.0-py3-none-any.whl and /dev/null differ diff --git a/pkg/udf/pythonservice/demo/setup.py b/pkg/udf/pythonservice/demo/setup.py deleted file mode 100644 index 8db958bbbf793..0000000000000 --- a/pkg/udf/pythonservice/demo/setup.py +++ /dev/null @@ -1,12 +0,0 @@ -# coding = utf-8 -# -*- coding:utf-8 -*- -from setuptools import setup, find_packages - -setup( - name="detect", - version="1.0.0", - packages=find_packages(), - package_data={ - 'credit': ['model_with_scaler'] - }, -) diff --git a/pkg/udf/pythonservice/pyserver/requirements/base.txt b/pkg/udf/pythonservice/pyserver/requirements/base.txt deleted file mode 100644 index c3d724172e0cd..0000000000000 --- a/pkg/udf/pythonservice/pyserver/requirements/base.txt +++ /dev/null @@ -1,12 +0,0 @@ -#-i https://pypi.org/simple --i https://mirrors.aliyun.com/pypi/simple - -grpcio==1.59.0 -protobuf==4.24.4 - -numpy==1.26.0 -scipy==1.11.3 -pandas==2.1.1 -scikit-learn==1.3.1 -tensorflow-cpu==2.14.0 -onnx==1.14.1 diff --git a/pkg/udf/pythonservice/pyserver/requirements/pytorch.txt b/pkg/udf/pythonservice/pyserver/requirements/pytorch.txt deleted file mode 100644 index d23b156a670c2..0000000000000 --- a/pkg/udf/pythonservice/pyserver/requirements/pytorch.txt +++ /dev/null @@ -1,5 +0,0 @@ --i https://download.pytorch.org/whl/cpu - -torch==2.1.0 -torchvision==0.16.0 -torchaudio==2.1.0 \ No newline at end of file diff --git a/pkg/udf/pythonservice/pyserver/server.py b/pkg/udf/pythonservice/pyserver/server.py deleted file mode 100644 index 262df4861f08f..0000000000000 --- a/pkg/udf/pythonservice/pyserver/server.py +++ /dev/null @@ -1,417 +0,0 @@ -# coding = utf-8 -# -*- coding:utf-8 -*- -# Copyright 2023 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. -import argparse -import datetime -import decimal -import enum -import importlib -import json -import logging -import os -import shutil -import subprocess -import threading -from concurrent import futures -from typing import Any, Callable, Optional, Iterator, Dict - -import grpc - -import udf_pb2 as pb2 -import udf_pb2_grpc as pb2_grpc - -DEFAULT_DECIMAL_SCALE = 16 - -DATE_FORMAT = '%Y-%m-%d' -DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S' -DATETIME_FORMAT_WITH_PRECISION = '%Y-%m-%d %H:%M:%S.%f' - -ROOT_PATH = os.path.dirname(os.path.abspath(__file__)) -INSTALLED_LABEL = 'installed' - -OPTION_VECTOR = 'vector' -OPTION_DECIMAL_PRECISION = 'decimal_precision' - -logging.basicConfig( - level=logging.INFO, - format='[%(asctime)s] - [%(name)s] - [%(levelname)s] - [%(threadName)s] : %(message)s' -) -log = logging.getLogger('Server') - - -class Server(pb2_grpc.ServiceServicer): - - def run(self, requestIterator: Iterator[pb2.Request], context) -> pb2.Response: - firstRequest: Optional[pb2.Request] = None - path: Optional[str] = None - filename: Optional[str] = None - item: Optional[InstallingItem] = None - - firstBlock = True - lastBlock = False - - try: - for request in requestIterator: - # check - checkUdf(request.udf) - - # the first request - if request.type == pb2.DataRequest: - log.info('receive data') - - if request.udf.isImport: - path, filename, item, status = functionStatus(request.udf) - - if status == FunctionStatus.NotExist: - firstRequest = request - yield pb2.Response(type=pb2.PkgRequest) - - elif status == FunctionStatus.Installing: - with item.condition: - # block and waiting - if not item.installed: - log.info('waiting') - item.condition.wait() - log.info('finish waiting') - yield self.calculate(request, path, filename) - - else: - yield self.calculate(request, path, filename) - - else: - yield self.calculate(request, "", "") - - # the second request (optional) - # var firstRequest, path, filename and item are not null - elif request.type == pb2.PkgResponse: - log.info('receive pkg') - - # install pkg, do not need write lock - absPath = os.path.join(ROOT_PATH, path) - lastBlock = request.udf.importPkg.last - try: - if firstBlock: - if os.path.exists(absPath): - shutil.rmtree(absPath) - os.makedirs(absPath, exist_ok=True) - firstBlock = False - - file = os.path.join(absPath, filename) - - with open(file, 'ab+') as f: - f.write(request.udf.importPkg.data) - - if lastBlock: - if request.udf.body.endswith('.whl'): - subprocess.check_call(['pip', 'install', '--no-index', file, '-t', absPath]) - os.remove(file) - - # mark the pkg is installed without error - open(os.path.join(absPath, INSTALLED_LABEL), 'w').close() - - except Exception as e: - shutil.rmtree(absPath, ignore_errors=True) - raise e - - finally: - if lastBlock: - with item.condition: - item.installed = True - item.condition.notifyAll() - - with INSTALLING_MAP_LOCK: - INSTALLING_MAP[path] = None - - if not lastBlock: - yield pb2.Response(type=pb2.PkgRequest) - else: - yield self.calculate(firstRequest, path, filename) - - else: - raise Exception('error udf request type') - # notify all - finally: - if item is None: - with INSTALLING_MAP_LOCK: - item = INSTALLING_MAP.get(path) - - if item is not None: - with item.condition: - item.installed = True - item.condition.notifyAll() - - with INSTALLING_MAP_LOCK: - INSTALLING_MAP[path] = None - - def calculate(self, request: pb2.Request, filepath: str, filename: str) -> pb2.Response: - log.info('calculating') - - # load function - func = loadFunction(request.udf, filepath, filename) - - # set precision - if hasattr(func, OPTION_DECIMAL_PRECISION): - prec = getattr(func, OPTION_DECIMAL_PRECISION) - if type(prec) is int and prec >= 0: - decimal.getcontext().prec = prec - else: - decimal.getcontext().prec = DEFAULT_DECIMAL_SCALE - else: - decimal.getcontext().prec = DEFAULT_DECIMAL_SCALE - - # scalar or vector - vector = False - if hasattr(func, OPTION_VECTOR): - vector = getattr(func, OPTION_VECTOR) is True - - # init result - result = pb2.DataVector( - const=False, - data=[], - length=request.length, - type=request.udf.retType, - scale=defaultScale(request.udf.retType) - ) - - # calculate - if vector: - params = [] - for i in range(len(request.vectors)): - params.append([getValueFromDataVector(request.vectors[i], j) for j in range(request.length)]) - values = func(*params) - assert len(values) == request.length, f'request length {request.length} is not same with result length {len(values)}' - for value in values: - data = value2Data(value, result.type) - result.data.append(data) - else: - for i in range(request.length): - params = [getValueFromDataVector(request.vectors[j], i) for j in range(len(request.vectors))] - value = func(*params) - data = value2Data(value, result.type) - result.data.append(data) - log.info('finish calculating') - return pb2.Response(vector=result, type=pb2.DataResponse) - - -def checkUdf(udf: pb2.Udf): - assert udf.handler != "", "udf handler should not be null" - assert udf.body != "", "udf body should not be null" - assert udf.language == "python", "udf language should be python" - assert udf.modifiedTime != "", "udf modifiedTime should not be null" - assert udf.db != "", "udf db should not be null" - - -class FunctionStatus(enum.Enum): - NotExist = 0 - Installing = 1 - Installed = 2 - - -class InstallingItem: - condition = threading.Condition() - installed = False - - -# key: db/func/modified_time, value: InstallingItem -INSTALLING_MAP: Dict[str, Optional[InstallingItem]] = {} -INSTALLING_MAP_LOCK = threading.RLock() - - -def functionStatus(udf: pb2.Udf) -> (str, str, Optional[InstallingItem], FunctionStatus): - with INSTALLING_MAP_LOCK: - filepath, filename = os.path.split(udf.body) - path = os.path.join('udf', udf.db, filepath[filepath.rfind('/') + 1:], udf.modifiedTime) - item = INSTALLING_MAP.get(path) - if item is None: - if os.path.isfile(os.path.join(ROOT_PATH, path, INSTALLED_LABEL)): - return path, filename, item, FunctionStatus.Installed - else: - item = InstallingItem() - item.installed = False - INSTALLING_MAP[path] = item - return path, filename, item, FunctionStatus.NotExist - else: - if item.installed: - return path, filename, item, FunctionStatus.Installed - else: - return path, filename, item, FunctionStatus.Installing - - -def loadFunction(udf: pb2.Udf, filepath: str, filename: str) -> Callable: - # load function - if not udf.isImport: - exec(udf.body, locals()) - # get function object - return locals()[udf.handler] - else: - if udf.body.endswith('.py'): - file = importlib.import_module(f'.{filename[:-3]}', package=filepath.replace("/", ".")) - return getattr(file, udf.handler) - elif udf.body.endswith('.whl'): - i = udf.handler.rfind('.') - if i < 1: - raise Exception( - "when you import a *.whl, the handler should be in the format of '.'") - file = importlib.import_module(f'.{udf.handler[:i]}', package=filepath.replace("/", ".")) - return getattr(file, udf.handler[i + 1:]) - - -def getDataFromDataVector(v: pb2.DataVector, i: int) -> pb2.Data: - if v is None: - return pb2.Data() - if v.const: - return v.data[0] - return v.data[i] - - -def getValueFromDataVector(v: pb2.DataVector, i: int) -> Any: - data = getDataFromDataVector(v, i) - - if data.WhichOneof("val") is None: - return None - - if v.type == pb2.BOOL: - return data.boolVal - if v.type in [pb2.INT8, pb2.INT16, pb2.INT32]: - return data.intVal - if v.type == pb2.INT64: - return data.int64Val - if v.type in [pb2.UINT8, pb2.INT16, pb2.INT32]: - return data.uintVal - if v.type == pb2.UINT64: - return data.uint64Val - if v.type == pb2.FLOAT32: - return data.floatVal - if v.type == pb2.FLOAT64: - return data.doubleVal - if v.type in [pb2.CHAR, pb2.VARCHAR, pb2.TEXT, pb2.UUID]: - return data.stringVal - if v.type == pb2.JSON: - return json.loads(data.stringVal) - if v.type == pb2.TIME: - sign = 1 if data.stringVal[0] == '-' else 0 - h, m, s = data.stringVal[sign:].split(':') - if sign == 0: - return datetime.timedelta(hours=int(h), minutes=int(m), seconds=float(s)) - return datetime.timedelta(hours=-int(h), minutes=-int(m), seconds=-float(s)) - if v.type == pb2.DATE: - return datetime.datetime.strptime(data.stringVal, DATE_FORMAT).date() - if v.type in [pb2.DATETIME, pb2.TIMESTAMP]: - formatStr = DATETIME_FORMAT if v.scale == 0 else DATETIME_FORMAT_WITH_PRECISION - return datetime.datetime.strptime(data.stringVal, formatStr) - if v.type in [pb2.DECIMAL64, pb2.DECIMAL128]: - return decimal.Decimal(data.stringVal) - if v.type in [pb2.BINARY, pb2.VARBINARY, pb2.BLOB]: - return data.bytesVal - else: - raise Exception("vector type error") - - -def defaultScale(typ: pb2.DataType, scale: Optional[int] = None) -> int: - if scale is not None: - return scale - if typ in [pb2.FLOAT32, pb2.FLOAT64]: - return -1 - if typ in [pb2.DECIMAL64, pb2.DECIMAL128]: - return decimal.getcontext().prec - if typ in [pb2.TIME, pb2.DATETIME, pb2.TIMESTAMP]: - return 6 - return 0 - - -def value2Data(value: Any, typ: pb2.DataType) -> pb2.Data: - if value is None: - return pb2.Data() - - if typ == pb2.BOOL: - assert type(value) is bool, f'return type error, required {bool}, received {type(value)}' - return pb2.Data(boolVal=value) - if typ in [pb2.INT8, pb2.INT16, pb2.INT32]: - assert type(value) is int, f'return type error, required {int}, received {type(value)}' - return pb2.Data(intVal=value) - if typ == pb2.INT64: - assert type(value) is int, f'return type error, required {int}, received {type(value)}' - return pb2.Data(int64Val=value) - if typ in [pb2.UINT8, pb2.INT16, pb2.INT32]: - assert type(value) is int, f'return type error, required {int}, received {type(value)}' - return pb2.Data(uintVal=value) - if typ == pb2.UINT64: - assert type(value) is int, f'return type error, required {int}, received {type(value)}' - return pb2.Data(uint64Val=value) - if typ == pb2.FLOAT32: - assert type(value) is float, f'return type error, required {float}, received {type(value)}' - return pb2.Data(floatVal=value) - if typ == pb2.FLOAT64: - assert type(value) is float, f'return type error, required {float}, received {type(value)}' - return pb2.Data(doubleVal=value) - if typ in [pb2.CHAR, pb2.VARCHAR, pb2.TEXT, pb2.UUID]: - assert type(value) is str, f'return type error, required {str}, received {type(value)}' - return pb2.Data(stringVal=value) - if typ == pb2.JSON: - return pb2.Data(stringVal=json.dumps(value, ensure_ascii=False)) - if typ == pb2.TIME: - assert type( - value) is datetime.timedelta, f'return type error, required {datetime.timedelta}, received {type(value)}' - r = '' - t: datetime.timedelta = value - if t.days < 0: - t = t * -1 - r += '-' - h = t.days * 24 + t.seconds // 3600 - m = t.seconds % 3600 // 60 - s = t.seconds % 3600 % 60 - r += f'{h:02d}:{m:02d}:{s:02d}.{t.microseconds:06d}' - return pb2.Data(stringVal=str(r)) - if typ == pb2.DATE: - assert type(value) is datetime.date, f'return type error, required {datetime.date}, received {type(value)}' - return pb2.Data(stringVal=str(value)) - if typ in [pb2.DATETIME, pb2.TIMESTAMP]: - assert type( - value) is datetime.datetime, f'return type error, required {datetime.datetime}, received {type(value)}' - return pb2.Data(stringVal=str(value)) - if typ in [pb2.DECIMAL64, pb2.DECIMAL128]: - assert type(value) is decimal.Decimal, f'return type error, required {decimal.Decimal}, received {type(value)}' - return pb2.Data(stringVal=str(value)) - if typ in [pb2.BINARY, pb2.VARBINARY, pb2.BLOB]: - assert type(value) is bytes, f'return type error, required {bytes}, received {type(value)}' - return pb2.Data(bytesVal=value) - else: - raise Exception(f'unsupported return type: {type(value)}') - - -def run(): - server = grpc.server(futures.ThreadPoolExecutor(), options=[ - ('grpc.max_send_message_length', 0x7fffffff), - ('grpc.max_receive_message_length', 0x7fffffff) - ]) - pb2_grpc.add_ServiceServicer_to_server(Server(), server) - server.add_insecure_port(ARGS.address) - server.start() - server.wait_for_termination() - - -ARGS = None - -if __name__ == '__main__': - parser = argparse.ArgumentParser( - prog='python udf server', - epilog='Copyright(r), 2023' - ) - parser.add_argument('--address', default='[::]:50051', help='address') - ARGS = parser.parse_args() - - log.info('python server start') - - run() diff --git a/pkg/udf/pythonservice/pyserver/udf_pb2.py b/pkg/udf/pythonservice/pyserver/udf_pb2.py deleted file mode 100644 index 52e791a8a7ff0..0000000000000 --- a/pkg/udf/pythonservice/pyserver/udf_pb2.py +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: udf.proto -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\tudf.proto\x12\x03udf\"\xce\x01\n\x07Request\x12\x15\n\x03udf\x18\x01 \x01(\x0b\x32\x08.udf.Udf\x12 \n\x07vectors\x18\x02 \x03(\x0b\x32\x0f.udf.DataVector\x12\x0e\n\x06length\x18\x03 \x01(\x03\x12\x1e\n\x04type\x18\x04 \x01(\x0e\x32\x10.udf.RequestType\x12*\n\x07\x63ontext\x18\x05 \x03(\x0b\x32\x19.udf.Request.ContextEntry\x1a.\n\x0c\x43ontextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"L\n\x08Response\x12\x1f\n\x06vector\x18\x01 \x01(\x0b\x32\x0f.udf.DataVector\x12\x1f\n\x04type\x18\x02 \x01(\x0e\x32\x11.udf.ResponseType\"\xab\x01\n\x03Udf\x12\x0f\n\x07handler\x18\x01 \x01(\t\x12\x10\n\x08isImport\x18\x02 \x01(\x08\x12\x0c\n\x04\x62ody\x18\x03 \x01(\t\x12\x1f\n\timportPkg\x18\x04 \x01(\x0b\x32\x0c.udf.Package\x12\x1e\n\x07retType\x18\x05 \x01(\x0e\x32\r.udf.DataType\x12\x10\n\x08language\x18\x06 \x01(\t\x12\x14\n\x0cmodifiedTime\x18\x07 \x01(\t\x12\n\n\x02\x64\x62\x18\x08 \x01(\t\"%\n\x07Package\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\x12\x0c\n\x04last\x18\x02 \x01(\x08\"p\n\nDataVector\x12\x17\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\t.udf.Data\x12\r\n\x05\x63onst\x18\x02 \x01(\x08\x12\x0e\n\x06length\x18\x03 \x01(\x03\x12\x1b\n\x04type\x18\x04 \x01(\x0e\x32\r.udf.DataType\x12\r\n\x05scale\x18\x05 \x01(\x05\"\xc0\x01\n\x04\x44\x61ta\x12\x11\n\x07\x62oolVal\x18\x01 \x01(\x08H\x00\x12\x10\n\x06intVal\x18\x02 \x01(\x11H\x00\x12\x12\n\x08int64Val\x18\x03 \x01(\x12H\x00\x12\x11\n\x07uintVal\x18\x04 \x01(\rH\x00\x12\x13\n\tuint64Val\x18\x05 \x01(\x04H\x00\x12\x12\n\x08\x66loatVal\x18\x06 \x01(\x02H\x00\x12\x13\n\tdoubleVal\x18\x07 \x01(\x01H\x00\x12\x13\n\tstringVal\x18\x08 \x01(\tH\x00\x12\x12\n\x08\x62ytesVal\x18\t \x01(\x0cH\x00\x42\x05\n\x03val*C\n\x0bRequestType\x12\x12\n\x0eUnknownRequest\x10\x00\x12\x0f\n\x0b\x44\x61taRequest\x10\x01\x12\x0f\n\x0bPkgResponse\x10\x02*E\n\x0cResponseType\x12\x13\n\x0fUnknownResponse\x10\x00\x12\x10\n\x0c\x44\x61taResponse\x10\x01\x12\x0e\n\nPkgRequest\x10\x02*\xbf\x02\n\x08\x44\x61taType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x08\n\x04\x42OOL\x10\n\x12\x08\n\x04INT8\x10\x14\x12\t\n\x05INT16\x10\x15\x12\t\n\x05INT32\x10\x16\x12\t\n\x05INT64\x10\x17\x12\t\n\x05UINT8\x10\x1e\x12\n\n\x06UINT16\x10\x1f\x12\n\n\x06UINT32\x10 \x12\n\n\x06UINT64\x10!\x12\x0b\n\x07\x46LOAT32\x10(\x12\x0b\n\x07\x46LOAT64\x10)\x12\x08\n\x04\x43HAR\x10\x32\x12\x0b\n\x07VARCHAR\x10\x33\x12\x08\n\x04TEXT\x10\x34\x12\x08\n\x04JSON\x10\x35\x12\x08\n\x04UUID\x10\x36\x12\x08\n\x04TIME\x10<\x12\x08\n\x04\x44\x41TE\x10=\x12\x0c\n\x08\x44\x41TETIME\x10>\x12\r\n\tTIMESTAMP\x10?\x12\r\n\tDECIMAL64\x10\x46\x12\x0e\n\nDECIMAL128\x10G\x12\n\n\x06\x42INARY\x10P\x12\r\n\tVARBINARY\x10Q\x12\x08\n\x04\x42LOB\x10R23\n\x07Service\x12(\n\x03run\x12\x0c.udf.Request\x1a\r.udf.Response\"\x00(\x01\x30\x01\x42+Z)github.com/matrixorigin/matrixone/pkg/udfb\x06proto3') - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'udf_pb2', _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - - DESCRIPTOR._options = None - DESCRIPTOR._serialized_options = b'Z)github.com/matrixorigin/matrixone/pkg/udf' - _REQUEST_CONTEXTENTRY._options = None - _REQUEST_CONTEXTENTRY._serialized_options = b'8\001' - _globals['_REQUESTTYPE']._serialized_start=827 - _globals['_REQUESTTYPE']._serialized_end=894 - _globals['_RESPONSETYPE']._serialized_start=896 - _globals['_RESPONSETYPE']._serialized_end=965 - _globals['_DATATYPE']._serialized_start=968 - _globals['_DATATYPE']._serialized_end=1287 - _globals['_REQUEST']._serialized_start=19 - _globals['_REQUEST']._serialized_end=225 - _globals['_REQUEST_CONTEXTENTRY']._serialized_start=179 - _globals['_REQUEST_CONTEXTENTRY']._serialized_end=225 - _globals['_RESPONSE']._serialized_start=227 - _globals['_RESPONSE']._serialized_end=303 - _globals['_UDF']._serialized_start=306 - _globals['_UDF']._serialized_end=477 - _globals['_PACKAGE']._serialized_start=479 - _globals['_PACKAGE']._serialized_end=516 - _globals['_DATAVECTOR']._serialized_start=518 - _globals['_DATAVECTOR']._serialized_end=630 - _globals['_DATA']._serialized_start=633 - _globals['_DATA']._serialized_end=825 - _globals['_SERVICE']._serialized_start=1289 - _globals['_SERVICE']._serialized_end=1340 -# @@protoc_insertion_point(module_scope) diff --git a/pkg/udf/pythonservice/pyserver/udf_pb2.pyi b/pkg/udf/pythonservice/pyserver/udf_pb2.pyi deleted file mode 100644 index b3438382c2537..0000000000000 --- a/pkg/udf/pythonservice/pyserver/udf_pb2.pyi +++ /dev/null @@ -1,173 +0,0 @@ -from google.protobuf.internal import containers as _containers -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union - -DESCRIPTOR: _descriptor.FileDescriptor - -class RequestType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = [] - UnknownRequest: _ClassVar[RequestType] - DataRequest: _ClassVar[RequestType] - PkgResponse: _ClassVar[RequestType] - -class ResponseType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = [] - UnknownResponse: _ClassVar[ResponseType] - DataResponse: _ClassVar[ResponseType] - PkgRequest: _ClassVar[ResponseType] - -class DataType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = [] - UNKNOWN: _ClassVar[DataType] - BOOL: _ClassVar[DataType] - INT8: _ClassVar[DataType] - INT16: _ClassVar[DataType] - INT32: _ClassVar[DataType] - INT64: _ClassVar[DataType] - UINT8: _ClassVar[DataType] - UINT16: _ClassVar[DataType] - UINT32: _ClassVar[DataType] - UINT64: _ClassVar[DataType] - FLOAT32: _ClassVar[DataType] - FLOAT64: _ClassVar[DataType] - CHAR: _ClassVar[DataType] - VARCHAR: _ClassVar[DataType] - TEXT: _ClassVar[DataType] - JSON: _ClassVar[DataType] - UUID: _ClassVar[DataType] - TIME: _ClassVar[DataType] - DATE: _ClassVar[DataType] - DATETIME: _ClassVar[DataType] - TIMESTAMP: _ClassVar[DataType] - DECIMAL64: _ClassVar[DataType] - DECIMAL128: _ClassVar[DataType] - BINARY: _ClassVar[DataType] - VARBINARY: _ClassVar[DataType] - BLOB: _ClassVar[DataType] -UnknownRequest: RequestType -DataRequest: RequestType -PkgResponse: RequestType -UnknownResponse: ResponseType -DataResponse: ResponseType -PkgRequest: ResponseType -UNKNOWN: DataType -BOOL: DataType -INT8: DataType -INT16: DataType -INT32: DataType -INT64: DataType -UINT8: DataType -UINT16: DataType -UINT32: DataType -UINT64: DataType -FLOAT32: DataType -FLOAT64: DataType -CHAR: DataType -VARCHAR: DataType -TEXT: DataType -JSON: DataType -UUID: DataType -TIME: DataType -DATE: DataType -DATETIME: DataType -TIMESTAMP: DataType -DECIMAL64: DataType -DECIMAL128: DataType -BINARY: DataType -VARBINARY: DataType -BLOB: DataType - -class Request(_message.Message): - __slots__ = ["udf", "vectors", "length", "type", "context"] - class ContextEntry(_message.Message): - __slots__ = ["key", "value"] - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: str - def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... - UDF_FIELD_NUMBER: _ClassVar[int] - VECTORS_FIELD_NUMBER: _ClassVar[int] - LENGTH_FIELD_NUMBER: _ClassVar[int] - TYPE_FIELD_NUMBER: _ClassVar[int] - CONTEXT_FIELD_NUMBER: _ClassVar[int] - udf: Udf - vectors: _containers.RepeatedCompositeFieldContainer[DataVector] - length: int - type: RequestType - context: _containers.ScalarMap[str, str] - def __init__(self, udf: _Optional[_Union[Udf, _Mapping]] = ..., vectors: _Optional[_Iterable[_Union[DataVector, _Mapping]]] = ..., length: _Optional[int] = ..., type: _Optional[_Union[RequestType, str]] = ..., context: _Optional[_Mapping[str, str]] = ...) -> None: ... - -class Response(_message.Message): - __slots__ = ["vector", "type"] - VECTOR_FIELD_NUMBER: _ClassVar[int] - TYPE_FIELD_NUMBER: _ClassVar[int] - vector: DataVector - type: ResponseType - def __init__(self, vector: _Optional[_Union[DataVector, _Mapping]] = ..., type: _Optional[_Union[ResponseType, str]] = ...) -> None: ... - -class Udf(_message.Message): - __slots__ = ["handler", "isImport", "body", "importPkg", "retType", "language", "modifiedTime", "db"] - HANDLER_FIELD_NUMBER: _ClassVar[int] - ISIMPORT_FIELD_NUMBER: _ClassVar[int] - BODY_FIELD_NUMBER: _ClassVar[int] - IMPORTPKG_FIELD_NUMBER: _ClassVar[int] - RETTYPE_FIELD_NUMBER: _ClassVar[int] - LANGUAGE_FIELD_NUMBER: _ClassVar[int] - MODIFIEDTIME_FIELD_NUMBER: _ClassVar[int] - DB_FIELD_NUMBER: _ClassVar[int] - handler: str - isImport: bool - body: str - importPkg: Package - retType: DataType - language: str - modifiedTime: str - db: str - def __init__(self, handler: _Optional[str] = ..., isImport: bool = ..., body: _Optional[str] = ..., importPkg: _Optional[_Union[Package, _Mapping]] = ..., retType: _Optional[_Union[DataType, str]] = ..., language: _Optional[str] = ..., modifiedTime: _Optional[str] = ..., db: _Optional[str] = ...) -> None: ... - -class Package(_message.Message): - __slots__ = ["data", "last"] - DATA_FIELD_NUMBER: _ClassVar[int] - LAST_FIELD_NUMBER: _ClassVar[int] - data: bytes - last: bool - def __init__(self, data: _Optional[bytes] = ..., last: bool = ...) -> None: ... - -class DataVector(_message.Message): - __slots__ = ["data", "const", "length", "type", "scale"] - DATA_FIELD_NUMBER: _ClassVar[int] - CONST_FIELD_NUMBER: _ClassVar[int] - LENGTH_FIELD_NUMBER: _ClassVar[int] - TYPE_FIELD_NUMBER: _ClassVar[int] - SCALE_FIELD_NUMBER: _ClassVar[int] - data: _containers.RepeatedCompositeFieldContainer[Data] - const: bool - length: int - type: DataType - scale: int - def __init__(self, data: _Optional[_Iterable[_Union[Data, _Mapping]]] = ..., const: bool = ..., length: _Optional[int] = ..., type: _Optional[_Union[DataType, str]] = ..., scale: _Optional[int] = ...) -> None: ... - -class Data(_message.Message): - __slots__ = ["boolVal", "intVal", "int64Val", "uintVal", "uint64Val", "floatVal", "doubleVal", "stringVal", "bytesVal"] - BOOLVAL_FIELD_NUMBER: _ClassVar[int] - INTVAL_FIELD_NUMBER: _ClassVar[int] - INT64VAL_FIELD_NUMBER: _ClassVar[int] - UINTVAL_FIELD_NUMBER: _ClassVar[int] - UINT64VAL_FIELD_NUMBER: _ClassVar[int] - FLOATVAL_FIELD_NUMBER: _ClassVar[int] - DOUBLEVAL_FIELD_NUMBER: _ClassVar[int] - STRINGVAL_FIELD_NUMBER: _ClassVar[int] - BYTESVAL_FIELD_NUMBER: _ClassVar[int] - boolVal: bool - intVal: int - int64Val: int - uintVal: int - uint64Val: int - floatVal: float - doubleVal: float - stringVal: str - bytesVal: bytes - def __init__(self, boolVal: bool = ..., intVal: _Optional[int] = ..., int64Val: _Optional[int] = ..., uintVal: _Optional[int] = ..., uint64Val: _Optional[int] = ..., floatVal: _Optional[float] = ..., doubleVal: _Optional[float] = ..., stringVal: _Optional[str] = ..., bytesVal: _Optional[bytes] = ...) -> None: ... diff --git a/pkg/udf/pythonservice/pyserver/udf_pb2_grpc.py b/pkg/udf/pythonservice/pyserver/udf_pb2_grpc.py deleted file mode 100644 index 2707b06019282..0000000000000 --- a/pkg/udf/pythonservice/pyserver/udf_pb2_grpc.py +++ /dev/null @@ -1,72 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -"""Client and server classes corresponding to protobuf-defined services.""" -import grpc - -import udf_pb2 as udf__pb2 - - -class ServiceStub(object): - """protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./udf.proto - - """ - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.run = channel.stream_stream( - '/udf.Service/run', - request_serializer=udf__pb2.Request.SerializeToString, - response_deserializer=udf__pb2.Response.FromString, - ) - - -class ServiceServicer(object): - """protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./udf.proto - - """ - - def run(self, request_iterator, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - -def add_ServiceServicer_to_server(servicer, server): - rpc_method_handlers = { - 'run': grpc.stream_stream_rpc_method_handler( - servicer.run, - request_deserializer=udf__pb2.Request.FromString, - response_serializer=udf__pb2.Response.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - 'udf.Service', rpc_method_handlers) - server.add_generic_rpc_handlers((generic_handler,)) - - - # This class is part of an EXPERIMENTAL API. -class Service(object): - """protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./udf.proto - - """ - - @staticmethod - def run(request_iterator, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.stream_stream(request_iterator, target, '/udf.Service/run', - udf__pb2.Request.SerializeToString, - udf__pb2.Response.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/pkg/udf/pythonservice/service.go b/pkg/udf/pythonservice/service.go deleted file mode 100644 index c0d990d00ff60..0000000000000 --- a/pkg/udf/pythonservice/service.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2023 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 pythonservice - -import ( - "fmt" - "github.com/matrixorigin/matrixone/pkg/logutil" - "io" - "os" - "os/exec" - "path" - "path/filepath" - "strconv" - "sync" - "sync/atomic" -) - -type service struct { - cfg Config - process *os.Process - log io.WriteCloser - mutex sync.Mutex -} - -func NewService(cfg Config) (PythonUdfServer, error) { - err := cfg.Validate() - if err != nil { - return nil, err - } - return &service{cfg: cfg}, nil -} - -var severNo int32 = 0 - -func (s *service) Start() error { - s.mutex.Lock() - defer s.mutex.Unlock() - - if s.process == nil { - var err error - var file string - - ex, err := os.Executable() - if err != nil { - return err - } - exePath := filepath.Dir(ex) - - if path.IsAbs(file) { - file = path.Join(s.cfg.Path, "server.py") - } else { - file = path.Join(exePath, s.cfg.Path, "server.py") - } - _, err = os.Stat(file) - if err != nil { - return err - } - - no := strconv.Itoa(int(atomic.AddInt32(&severNo, 1))) - s.log, err = os.OpenFile(path.Join(exePath, "pyserver"+no+".log"), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) - if err != nil { - return err - } - defer func() { - if err != nil { - s.log.Close() - } - }() - executable := s.cfg.Python - if executable == "" { - executable = "python" - } - - cmd := exec.Command(executable, "-u", file, "--address="+s.cfg.Address) - cmd.Stdout = s.log - cmd.Stderr = s.log - go func(cmd *exec.Cmd) { - logutil.Infof("start python server process, command: %s", cmd.String()) - err := cmd.Run() - // panic the launch process if python server exit with an error - if err != nil { - panic(fmt.Sprintf("python server exit with error: %v", err)) - } - }(cmd) - - s.process = cmd.Process - } - - return nil -} - -func (s *service) Close() error { - s.mutex.Lock() - defer func() { - s.mutex.Unlock() - if s.log != nil { - s.log.Close() - } - }() - - if s.process != nil { - err := s.process.Kill() - if err != nil { - return err - } - s.process = nil - } - - return nil -} diff --git a/pkg/udf/runtime.go b/pkg/udf/runtime.go new file mode 100644 index 0000000000000..a9edc4a024492 --- /dev/null +++ b/pkg/udf/runtime.go @@ -0,0 +1,523 @@ +// Copyright 2026 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 udf contains the execution contract shared by SQL routine binders, +// CN operators, and language runtimes. Wire formats and language-specific +// adapters live below this package; the SQL engine depends only on this +// contract. +package udf + +import ( + "context" + "encoding/json" + "errors" + "sort" + "strconv" + "strings" + "sync" + "time" + + "github.com/matrixorigin/matrixone/pkg/udf/udferr" + "github.com/matrixorigin/matrixone/pkg/util/errutil" + + "github.com/matrixorigin/matrixone/pkg/common/moerr" + "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/udf/protocol" +) + +const ( + LanguageSQL = "sql" + LanguagePython = "python" + PythonABIContract = "PYTHON_ARROW" + PythonAdapterVersion = "2026-09" + PythonSDKVersion = "1.0" + // Python materializes statement timestamps as datetime.datetime. Keep the + // Go boundary identical to Python's year-1 through year-9999 UTC range; + // accepting the full int64 domain here would let a plan pass CN validation + // and fail only after the worker starts decoding its context. + minStatementTimestampUTC int64 = -62135596800000000 + maxStatementTimestampUTC int64 = 253402300799999999 + // These numeric contracts are persisted in catalog and plan records. They + // are intentionally separate from the human-facing adapter/SDK names: + // changing a wire or persistent shape must fail closed before user code is + // entered, even when the runtime happens to use the same language ABI name. + SQLDefinitionSchemaVersion = 1 + RoutinePlanContractVersion = 1 + PythonDefinitionSchemaVersion = 1 + // Kept as a source-compatible alias for the Python adapter while the + // plan field is shared by SQL and Python routine calls. + PythonPlanContractVersion = RoutinePlanContractVersion + // PythonSignatureKeySchemaVersion versions the canonical descriptor + // encoding stored on the shared Function identity. It is independent of + // the implementation body schema: changing the overload key is an + // identity/catalog migration, while changing the body is a revision. + PythonSignatureKeySchemaVersion = 1 + PythonTypeDescriptorContract = "ARROW_DESCRIPTOR" + NullCallHandler = "CALLED_ON_NULL_INPUT" + NullReturnNull = "RETURNS_NULL_ON_NULL_INPUT" + StatementContextContractVersion = 1 + SecurityFrameContractVersion = 1 +) + +// StatementContext is the typed execution-time snapshot visible to a Python +// handler. It is intentionally separate from plan metadata: a prepared plan +// may be reused by many statements, while these values are frozen once per +// execution. The JSON form is also the cross-process contract used by the +// Gateway and worker. +type StatementContext struct { + ContractVersion int `json:"contract_version"` + StatementTimestampUTC int64 `json:"statement_timestamp_utc"` + TimezoneKind string `json:"timezone_kind"` + TimezoneName string `json:"timezone_name,omitempty"` + TimezoneOffsetMinutes int32 `json:"timezone_offset_minutes"` + TimezoneDatabaseVersion string `json:"timezone_database_version,omitempty"` + SQLMode []string `json:"sql_mode"` + CurrentDatabase string `json:"current_database,omitempty"` + CurrentUser string `json:"current_user"` + CurrentRole string `json:"current_role,omitempty"` + ConnectionCollation string `json:"connection_collation"` +} + +func (c StatementContext) Validate() error { + if c.ContractVersion != StatementContextContractVersion { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: unsupported statement context contract %d", c.ContractVersion) + } + if c.StatementTimestampUTC < minStatementTimestampUTC || c.StatementTimestampUTC > maxStatementTimestampUTC { + return udferr.Newf("python udf: statement timestamp is outside the Python datetime range") + } + if c.CurrentUser == "" || c.ConnectionCollation == "" { + return udferr.Newf("python udf: statement context has no authenticated user or collation") + } + if c.TimezoneKind == "IANA" { + if c.TimezoneName == "" || c.TimezoneDatabaseVersion == "" || c.TimezoneOffsetMinutes != 0 { + return udferr.Newf("python udf: IANA statement timezone is incomplete") + } + if _, err := time.LoadLocation(c.TimezoneName); err != nil { + return errutil.Wrapf(err, "python udf: IANA statement timezone is not present in the local tzdb") + } + } else if c.TimezoneKind == "FIXED_OFFSET" { + if c.TimezoneName != "" || c.TimezoneDatabaseVersion != "" || c.TimezoneOffsetMinutes < -839 || c.TimezoneOffsetMinutes > 840 { + return udferr.Newf("python udf: fixed statement timezone is invalid") + } + } else { + return udferr.Newf("python udf: unsupported statement timezone kind %q", c.TimezoneKind) + } + mode := append([]string(nil), c.SQLMode...) + sort.Strings(mode) + for i := range mode { + if mode[i] == "" || (i > 0 && mode[i] == mode[i-1]) { + return udferr.Newf("python udf: statement sql_mode is not canonical") + } + } + if len(mode) != len(c.SQLMode) { + return udferr.Newf("python udf: statement sql_mode is not canonical") + } + for i := range mode { + if mode[i] != c.SQLMode[i] { + return udferr.Newf("python udf: statement sql_mode is not sorted") + } + } + return nil +} + +// StatementContextFromMap is the only adapter from the legacy internal map +// assembled by the SQL session to the typed runtime contract. It accepts the +// map solely at the trusted CN boundary and returns nil when no statement +// fields are present, which keeps transport/protocol unit tests able to test +// zero-row admission without manufacturing session state. +func StatementContextFromMap(values map[string]string) (*StatementContext, error) { + if len(values) == 0 { + return nil, nil + } + statementKeys := []string{ + "statement_timestamp_utc", "session_timezone_kind", "session_timezone_name", + "session_timezone_offset_minutes", "session_timezone_tzdb_version", "sql_mode", + "current_database", "current_user", "current_role", "connection_collation", + } + present := false + for _, key := range statementKeys { + if _, ok := values[key]; ok { + present = true + break + } + } + if !present { + return nil, nil + } + timestamp, err := strconv.ParseInt(values["statement_timestamp_utc"], 10, 64) + if err != nil { + return nil, errutil.Wrapf(err, "python udf: invalid statement timestamp") + } + mode := make([]string, 0) + if raw := values["sql_mode"]; raw != "" { + if err := json.Unmarshal([]byte(raw), &mode); err != nil { + return nil, errutil.Wrapf(err, "python udf: invalid statement sql_mode") + } + // The wire contract is a JSON array, including when it is empty. A + // JSON null decodes successfully into a nil Go slice, but would be + // serialized back as null and rejected by the Python context decoder. + // Reject it at the trusted CN adapter instead of carrying a malformed + // snapshot into the Flight request. + if mode == nil { + return nil, udferr.Newf("python udf: invalid statement sql_mode: expected a JSON array") + } + } + context := &StatementContext{ + ContractVersion: StatementContextContractVersion, + StatementTimestampUTC: timestamp, + TimezoneKind: strings.ToUpper(values["session_timezone_kind"]), + TimezoneName: values["session_timezone_name"], + SQLMode: mode, + CurrentDatabase: values["current_database"], + CurrentUser: values["current_user"], + CurrentRole: values["current_role"], + ConnectionCollation: values["connection_collation"], + TimezoneDatabaseVersion: values["session_timezone_tzdb_version"], + } + if raw := values["session_timezone_offset_minutes"]; raw != "" { + offset, parseErr := strconv.ParseInt(raw, 10, 32) + if parseErr != nil { + return nil, errutil.Wrapf(parseErr, "python udf: invalid fixed timezone offset") + } + context.TimezoneOffsetMinutes = int32(offset) + } + if err := context.Validate(); err != nil { + return nil, err + } + return context, nil +} + +// SecurityFrame records the principal entering this routine layer. Python +// currently supports INVOKER only, so the effective IDs must equal the +// invoker IDs. The explicit frame prevents a future definer implementation +// from silently reusing the outer session's principal. +type SecurityFrame struct { + ContractVersion int `json:"contract_version"` + Mode string `json:"mode"` + InvokerUserID uint32 `json:"invoker_user_id"` + InvokerRoleID uint32 `json:"invoker_role_id"` + EffectiveUserID uint32 `json:"effective_user_id"` + EffectiveRoleID uint32 `json:"effective_role_id"` +} + +func (f SecurityFrame) Validate() error { + if f.ContractVersion != SecurityFrameContractVersion || f.Mode != "INVOKER" { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: unsupported Python security frame") + } + if f.InvokerUserID != f.EffectiveUserID || f.InvokerRoleID != f.EffectiveRoleID { + return udferr.Newf("UNSUPPORTED_ROUTINE_VERSION: Python invoker security frame changed effective principal") + } + return nil +} + +// Invocation is the language-neutral routine call handed to an admitted +// runtime. The runtime owns transport, worker lifecycle, and Arrow +// conversion; CN owns the SQL vectors, result wrapper, and fencing identity. +type Invocation struct { + // Function identity and revision are copied from the typed plan. They are + // part of the execution grant sent to the worker; the runtime never + // resolves a function name or latest revision. + FunctionRef FunctionRef + Language string + Handler string + Source string + Args []types.Type + ReturnType types.Type + Inputs []*vector.Vector + Length int + Mode string + NullPolicy string + ABIContract string + AdapterVersion string + SDKVersion string + // These values are copied from the immutable typed implementation. The + // gateway and worker validate them before opening user code; they are not + // inferred from a mutable source path or a function name. + DefinitionSchemaVersion int + ArtifactDigest string + EnvironmentDigest string + DefinitionFingerprint string + Context map[string]string + // Common routine semantics are copied from the typed plan. The Python + // gateway refuses an invocation with absent or altered values. + CallsiteID string + MayError bool + SecurityMode string + Leakproof bool + StatementContext *StatementContext + SecurityFrame *SecurityFrame + Tuple protocol.FencingTuple +} + +// FunctionRef is the language-neutral form of the shared Catalog identity +// carried through the runtime boundary. +type FunctionRef struct { + AccountID uint64 `json:"account_id"` + DatabaseID uint64 `json:"database_id"` + FunctionID uint64 `json:"function_id"` + Revision uint64 `json:"revision"` + NamespaceVersion uint64 `json:"namespace_version"` +} + +func (r FunctionRef) Validate() error { + if r.DatabaseID == 0 || r.FunctionID == 0 || r.Revision == 0 || r.NamespaceVersion == 0 { + return moerr.NewInvalidInputNoCtx("incomplete UDF FunctionRef") + } + return nil +} + +// Runtime executes one invocation. Implementations must not retain the +// vectors or result after Execute returns. +type Runtime interface { + Language() string + Execute(context.Context, *Invocation, vector.FunctionResultWrapper, *mpool.MPool) error +} + +// RuntimeCloser is an optional lifecycle contract for runtimes that own a +// transport connection or a worker process. Execution callers only need +// Runtime; service shutdown uses this interface to close such resources. +type RuntimeCloser interface { + Runtime + Close() error +} + +// RuntimeReadiness is an optional feature-level gate. A caller uses it before +// publishing a routine so a node never persists a new external definition +// that its current runtime cannot execute. It does not affect ordinary SQL +// routines or ordinary SQL when the Python runtime is disabled. +type RuntimeReadiness interface { + CheckLanguageReady(context.Context, string) error +} + +// RuntimeStatusSnapshot is the bounded, read-only state exposed to control +// planes that need to observe a language runtime without entering the +// invocation path. A snapshot never contains source, artifacts, secrets, or +// invocation identifiers. The capability fields are a summary of the +// already negotiated worker contract; the runtime remains responsible for +// deciding whether the summary is valid. +type RuntimeStatusSnapshot struct { + Language string + Enabled bool + AllowUnisolated bool + Ready bool + ErrorClass string + Reason string + ProtocolVersion int32 + ABIContract string + AdapterVersion string + SDKVersion string + DefinitionSchemaVersion int32 + PlanContractVersion int32 + TypeDescriptorContract string + TimezoneDatabaseVersion string + WindowBatches int32 + CumulativeAck bool + MaxExecutionFrameBytes int64 + MaxHandlerProcesses int32 + MaxAccountHandlerProcesses int32 + MaxOwnerHandlerProcesses int32 + LeaseEpoch uint64 + Modes []string + NullPolicies []string +} + +const ( + RuntimeStatusReady = "READY" + RuntimeStatusDisabled = "DISABLED" + RuntimeStatusNotAllowed = "NOT_ALLOWED" + RuntimeStatusUnavailable = "UNAVAILABLE" + RuntimeStatusContractMismatch = "CONTRACT_MISMATCH" + RuntimeStatusTimeout = "TIMEOUT" + RuntimeStatusClosed = "CLOSED" + RuntimeStatusInvalid = "INVALID" + RuntimeStatusInternal = "INTERNAL" + + RuntimeStatusReasonReady = "CapabilityHandshakeReady" + RuntimeStatusReasonRuntimeDisabled = "RuntimeDisabled" + RuntimeStatusReasonUnisolatedNotAllowed = "UnisolatedExecutionNotAllowed" + RuntimeStatusReasonWorkerUnavailable = "WorkerUnavailable" + RuntimeStatusReasonCapabilityMismatch = "CapabilityContractMismatch" + RuntimeStatusReasonRequestTimeout = "CapabilityRequestTimeout" + RuntimeStatusReasonRuntimeClosed = "RuntimeClosed" + RuntimeStatusReasonStatusUnavailable = "RuntimeStatusUnavailable" + RuntimeStatusReasonInvalidLanguage = "InvalidLanguage" + RuntimeStatusReasonRuntimeError = "RuntimeError" +) + +// RuntimeStatusProvider supplies the bounded status view used by the CN query +// service. Implementations may refresh a capability handshake, but must not +// execute user code or allocate invocation/ledger state. +type RuntimeStatusProvider interface { + StatusSnapshot(context.Context, string) RuntimeStatusSnapshot +} + +// RoutineDefinition is the typed, pre-publication contract handed to a +// language runtime for definition validation. It is deliberately separate +// from Invocation: a CREATE or REPLACE has no FunctionRef/revision yet and +// must be validated before the new Catalog revision becomes visible. +// +// Source is transient create-time input. An executable plan never carries +// source; a runtime with an ArtifactResolver must resolve the same immutable +// artifact digest before sending source to the worker. +type RoutineDefinition struct { + Language string + AccountID uint64 + Handler string + Source string + Args []types.Type + ReturnType types.Type + Mode string + NullPolicy string + ABIContract string + AdapterVersion string + SDKVersion string + DefinitionSchemaVersion int + ArtifactDigest string + EnvironmentDigest string + DefinitionFingerprint string +} + +// RuntimeDefinitionValidator is an optional language runtime capability. +// Python CREATE/REPLACE requires it: the worker must compile the exact +// immutable artifact before Catalog publication. Keeping this as a separate +// capability preserves the language-neutral execution interface and lets +// ordinary SQL UDFs continue to use Runtime implementations that do not own +// a source validation protocol. +type RuntimeDefinitionValidator interface { + ValidateDefinition(context.Context, *RoutineDefinition) error +} + +// Registry dispatches to the one runtime selected by a routine's language. +// A registry is immutable after construction, so plan execution cannot race +// service registration or observe a partially initialized adapter. +func NewRuntime(runtimes ...Runtime) (Runtime, error) { + registry := &runtimeRegistry{byLanguage: make(map[string]Runtime, len(runtimes))} + for _, runtime := range runtimes { + if runtime == nil || runtime.Language() == "" { + return nil, moerr.NewInternalErrorNoCtx("invalid udf runtime") + } + if _, exists := registry.byLanguage[runtime.Language()]; exists { + return nil, moerr.NewInternalErrorNoCtx("too many " + runtime.Language() + " runtimes") + } + registry.byLanguage[runtime.Language()] = runtime + } + return registry, nil +} + +type runtimeRegistry struct { + byLanguage map[string]Runtime + closeOnce sync.Once + closeErr error +} + +func (r *runtimeRegistry) Language() string { return "multiple" } + +func (r *runtimeRegistry) Execute( + ctx context.Context, + invocation *Invocation, + result vector.FunctionResultWrapper, + mp *mpool.MPool, +) error { + if invocation == nil { + return moerr.NewInternalError(ctx, "nil udf invocation") + } + runtime := r.byLanguage[invocation.Language] + if runtime == nil { + return moerr.NewInternalError(ctx, "missing "+invocation.Language+" udf runtime") + } + return runtime.Execute(ctx, invocation, result, mp) +} + +func (r *runtimeRegistry) CheckLanguageReady(ctx context.Context, language string) error { + runtime := r.byLanguage[language] + if runtime == nil { + return moerr.NewNotSupportedf(ctx, "%s UDF runtime is not enabled", language) + } + readiness, ok := runtime.(RuntimeReadiness) + if !ok { + return moerr.NewNotSupportedf(ctx, "%s UDF runtime does not expose the current contract", language) + } + return readiness.CheckLanguageReady(ctx, language) +} + +func (r *runtimeRegistry) StatusSnapshot(ctx context.Context, language string) RuntimeStatusSnapshot { + runtime := r.byLanguage[language] + if runtime == nil { + return RuntimeStatusSnapshot{ + Language: language, + ErrorClass: RuntimeStatusDisabled, + Reason: RuntimeStatusReasonRuntimeDisabled, + } + } + if provider, ok := runtime.(RuntimeStatusProvider); ok { + return provider.StatusSnapshot(ctx, language) + } + readiness, ok := runtime.(RuntimeReadiness) + if !ok { + return RuntimeStatusSnapshot{ + Language: language, + Enabled: true, + ErrorClass: RuntimeStatusUnavailable, + Reason: RuntimeStatusReasonStatusUnavailable, + } + } + if err := readiness.CheckLanguageReady(ctx, language); err != nil { + return RuntimeStatusSnapshot{ + Language: language, + Enabled: true, + ErrorClass: RuntimeStatusUnavailable, + Reason: RuntimeStatusReasonWorkerUnavailable, + } + } + return RuntimeStatusSnapshot{ + Language: language, + Enabled: true, + Ready: true, + ErrorClass: "", + Reason: RuntimeStatusReasonReady, + } +} + +func (r *runtimeRegistry) ValidateDefinition(ctx context.Context, definition *RoutineDefinition) error { + if definition == nil { + return moerr.NewInvalidInputNoCtx("nil UDF routine definition") + } + runtime := r.byLanguage[definition.Language] + if runtime == nil { + return moerr.NewNotSupportedf(ctx, "%s UDF runtime is not enabled", definition.Language) + } + validator, ok := runtime.(RuntimeDefinitionValidator) + if !ok { + return moerr.NewNotSupportedf(ctx, "%s UDF runtime does not expose definition validation", definition.Language) + } + return validator.ValidateDefinition(ctx, definition) +} + +func (r *runtimeRegistry) Close() error { + r.closeOnce.Do(func() { + languages := make([]string, 0, len(r.byLanguage)) + for language := range r.byLanguage { + languages = append(languages, language) + } + sort.Strings(languages) + for _, language := range languages { + if closer, ok := r.byLanguage[language].(RuntimeCloser); ok { + r.closeErr = errors.Join(r.closeErr, closer.Close()) + } + } + }) + return r.closeErr +} diff --git a/pkg/udf/runtime_status_wire_test.go b/pkg/udf/runtime_status_wire_test.go new file mode 100644 index 0000000000000..3bce3cd16d052 --- /dev/null +++ b/pkg/udf/runtime_status_wire_test.go @@ -0,0 +1,50 @@ +// Copyright 2026 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 udf + +import ( + "encoding/base64" + "encoding/json" + "github.com/matrixorigin/matrixone/pkg/pb/query" + "github.com/stretchr/testify/require" + "os" + "testing" +) + +// The identical fixture is consumed by Operator's independent wire decoder. +// This prevents successful status alone from concealing fault-enum drift. +func TestPythonStatusWireContract(t *testing.T) { + expected := map[string][]string{ + "": {RuntimeStatusReasonReady}, RuntimeStatusDisabled: {RuntimeStatusReasonRuntimeDisabled}, RuntimeStatusNotAllowed: {RuntimeStatusReasonUnisolatedNotAllowed}, + RuntimeStatusUnavailable: {RuntimeStatusReasonWorkerUnavailable, RuntimeStatusReasonStatusUnavailable}, RuntimeStatusContractMismatch: {RuntimeStatusReasonCapabilityMismatch}, RuntimeStatusTimeout: {RuntimeStatusReasonRequestTimeout}, RuntimeStatusClosed: {RuntimeStatusReasonRuntimeClosed}, RuntimeStatusInvalid: {RuntimeStatusReasonInvalidLanguage}, RuntimeStatusInternal: {RuntimeStatusReasonRuntimeError}, + } + raw, err := os.ReadFile("testdata/python_status_wire.json") + require.NoError(t, err) + var rows []struct{ Class, Reason, Wire string } + require.NoError(t, json.Unmarshal(raw, &rows)) + seen := map[string][]string{} + for _, row := range rows { + wire, err := base64.StdEncoding.DecodeString(row.Wire) + require.NoError(t, err) + var response query.Response + require.NoError(t, response.Unmarshal(wire)) + require.Equal(t, query.CmdMethod_GetPythonUdfStatus, response.CmdMethod) + require.Equal(t, row.Class, response.GetPythonUdfStatus.ErrorClass) + require.Equal(t, row.Reason, response.GetPythonUdfStatus.Reason) + require.Equal(t, row.Class == "", response.GetPythonUdfStatus.Ready) + seen[row.Class] = append(seen[row.Class], row.Reason) + } + require.Equal(t, expected, seen) +} diff --git a/pkg/udf/runtime_test.go b/pkg/udf/runtime_test.go new file mode 100644 index 0000000000000..d415df5c46a6e --- /dev/null +++ b/pkg/udf/runtime_test.go @@ -0,0 +1,239 @@ +// Copyright 2026 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 udf + +import ( + "context" + "sync/atomic" + "testing" + + "github.com/matrixorigin/matrixone/pkg/common/mpool" + "github.com/matrixorigin/matrixone/pkg/container/vector" + "github.com/stretchr/testify/require" +) + +type closableRuntime struct { + language string + closed atomic.Int32 +} + +func (r *closableRuntime) Language() string { return r.language } + +func (r *closableRuntime) Execute( + context.Context, + *Invocation, + vector.FunctionResultWrapper, + *mpool.MPool, +) error { + return nil +} + +func (r *closableRuntime) Close() error { + r.closed.Add(1) + return nil +} + +type readinessRuntime struct { + *closableRuntime + readyErr error +} + +func (r *readinessRuntime) CheckLanguageReady(context.Context, string) error { + return r.readyErr +} + +func TestRuntimeRegistryClosesOwnedRuntimesOnce(t *testing.T) { + python := &closableRuntime{language: LanguagePython} + runtime, err := NewRuntime(python) + require.NoError(t, err) + closer, ok := runtime.(RuntimeCloser) + require.True(t, ok) + require.NoError(t, closer.Close()) + require.NoError(t, closer.Close()) + require.Equal(t, int32(1), python.closed.Load()) +} + +func TestRuntimeRegistryFailsClosedForMissingCapabilities(t *testing.T) { + ctx := context.Background() + registry, err := NewRuntime() + require.NoError(t, err) + provider, ok := registry.(RuntimeStatusProvider) + require.True(t, ok) + snapshot := provider.StatusSnapshot(ctx, LanguagePython) + require.Equal(t, RuntimeStatusDisabled, snapshot.ErrorClass) + require.Equal(t, RuntimeStatusReasonRuntimeDisabled, snapshot.Reason) + require.Error(t, registry.(RuntimeReadiness).CheckLanguageReady(ctx, LanguagePython)) + require.Error(t, registry.(RuntimeDefinitionValidator).ValidateDefinition(ctx, nil)) + require.Error(t, registry.Execute(ctx, nil, nil, nil)) + + plain, err := NewRuntime(&closableRuntime{language: LanguagePython}) + require.NoError(t, err) + snapshot = plain.(RuntimeStatusProvider).StatusSnapshot(ctx, LanguagePython) + require.Equal(t, RuntimeStatusUnavailable, snapshot.ErrorClass) + require.Equal(t, RuntimeStatusReasonStatusUnavailable, snapshot.Reason) + require.Error(t, plain.(RuntimeReadiness).CheckLanguageReady(ctx, LanguagePython)) + require.Error(t, plain.(RuntimeDefinitionValidator).ValidateDefinition(ctx, &RoutineDefinition{Language: LanguagePython})) + require.Error(t, plain.Execute(ctx, &Invocation{Language: "missing"}, nil, nil)) +} + +func TestRuntimeRegistryUsesReadinessFallback(t *testing.T) { + ctx := context.Background() + ready, err := NewRuntime(&readinessRuntime{closableRuntime: &closableRuntime{language: LanguagePython}}) + require.NoError(t, err) + snapshot := ready.(RuntimeStatusProvider).StatusSnapshot(ctx, LanguagePython) + require.True(t, snapshot.Ready) + require.Empty(t, snapshot.ErrorClass) + require.Equal(t, RuntimeStatusReasonReady, snapshot.Reason) + + cause := context.DeadlineExceeded + unavailable, err := NewRuntime(&readinessRuntime{ + closableRuntime: &closableRuntime{language: LanguagePython}, + readyErr: cause, + }) + require.NoError(t, err) + snapshot = unavailable.(RuntimeStatusProvider).StatusSnapshot(ctx, LanguagePython) + require.True(t, snapshot.Enabled) + require.False(t, snapshot.Ready) + require.Equal(t, RuntimeStatusUnavailable, snapshot.ErrorClass) + require.Equal(t, RuntimeStatusReasonWorkerUnavailable, snapshot.Reason) +} + +func TestNewRuntimeRejectsInvalidAndDuplicateLanguageOwners(t *testing.T) { + _, err := NewRuntime(nil) + require.Error(t, err) + _, err = NewRuntime(&closableRuntime{}) + require.Error(t, err) + _, err = NewRuntime( + &closableRuntime{language: LanguagePython}, + &closableRuntime{language: LanguagePython}, + ) + require.Error(t, err) +} + +func TestStatementContextFromMapProducesCanonicalTypedSnapshot(t *testing.T) { + snapshot, err := StatementContextFromMap(map[string]string{ + "statement_timestamp_utc": "1704067200123456", + "session_timezone_kind": "FIXED_OFFSET", + "session_timezone_offset_minutes": "+510", + "sql_mode": "[\"ANSI\",\"STRICT_TRANS_TABLES\"]", + "current_database": "app", + "current_user": "alice", + "current_role": "writer", + "connection_collation": "utf8mb4_bin", + }) + require.NoError(t, err) + require.Equal(t, int32(510), snapshot.TimezoneOffsetMinutes) + require.Equal(t, []string{"ANSI", "STRICT_TRANS_TABLES"}, snapshot.SQLMode) + require.NoError(t, snapshot.Validate()) + + snapshot.SQLMode = []string{"STRICT_TRANS_TABLES", "ANSI"} + require.ErrorContains(t, snapshot.Validate(), "not sorted") +} + +func TestStatementContextFromMapRejectsAmbiguousTimezoneAndMalformedMode(t *testing.T) { + base := map[string]string{ + "statement_timestamp_utc": "1704067200123456", + "session_timezone_kind": "FIXED_OFFSET", + "session_timezone_offset_minutes": "+480", + "sql_mode": "[]", + "current_user": "alice", + "connection_collation": "utf8mb4_bin", + } + ambiguous := make(map[string]string, len(base)+1) + for key, value := range base { + ambiguous[key] = value + } + ambiguous["session_timezone_name"] = "Asia/Shanghai" + _, err := StatementContextFromMap(ambiguous) + require.ErrorContains(t, err, "fixed statement timezone") + + malformed := make(map[string]string, len(base)) + for key, value := range base { + malformed[key] = value + } + malformed["sql_mode"] = "[\"ANSI\",\"ANSI\"]" + _, err = StatementContextFromMap(malformed) + require.ErrorContains(t, err, "not canonical") + + malformed["sql_mode"] = "null" + _, err = StatementContextFromMap(malformed) + require.ErrorContains(t, err, "expected a JSON array") +} + +func TestStatementContextAcceptsUnixEpoch(t *testing.T) { + snapshot, err := StatementContextFromMap(map[string]string{ + "statement_timestamp_utc": "0", + "session_timezone_kind": "FIXED_OFFSET", + "session_timezone_offset_minutes": "0", + "sql_mode": "[]", + "current_user": "alice", + "connection_collation": "utf8mb4_bin", + }) + require.NoError(t, err) + require.Zero(t, snapshot.StatementTimestampUTC) + require.NoError(t, snapshot.Validate()) +} + +func TestStatementContextRejectsUnknownIANAZoneBeforeTransport(t *testing.T) { + snapshot := StatementContext{ + ContractVersion: StatementContextContractVersion, + StatementTimestampUTC: 0, + TimezoneKind: "IANA", + TimezoneName: "NoSuch/Zone", + TimezoneDatabaseVersion: "2026a", + CurrentUser: "alice", + ConnectionCollation: "utf8mb4_bin", + } + require.ErrorContains(t, snapshot.Validate(), "not present in the local tzdb") +} + +func TestStatementContextAcceptsKnownIANAZone(t *testing.T) { + version, err := TimezoneDatabaseVersion() + require.NoError(t, err) + snapshot := StatementContext{ + ContractVersion: StatementContextContractVersion, + StatementTimestampUTC: 0, + TimezoneKind: "IANA", + TimezoneName: "UTC", + TimezoneDatabaseVersion: version, + CurrentUser: "alice", + ConnectionCollation: "utf8mb4_bin", + } + require.NoError(t, snapshot.Validate()) +} + +func TestStatementContextMatchesPythonDatetimeRange(t *testing.T) { + base := StatementContext{ + ContractVersion: StatementContextContractVersion, + TimezoneKind: "FIXED_OFFSET", + CurrentUser: "alice", + ConnectionCollation: "utf8mb4_bin", + } + for _, timestamp := range []int64{minStatementTimestampUTC - 1, maxStatementTimestampUTC + 1} { + context := base + context.StatementTimestampUTC = timestamp + require.ErrorContains(t, context.Validate(), "outside the Python datetime range") + } +} + +func TestSecurityFrameRejectsEffectivePrincipalChange(t *testing.T) { + frame := SecurityFrame{ + ContractVersion: SecurityFrameContractVersion, + Mode: "INVOKER", + InvokerUserID: 7, + EffectiveUserID: 8, + } + require.ErrorContains(t, frame.Validate(), "changed effective principal") +} diff --git a/pkg/udf/service.go b/pkg/udf/service.go deleted file mode 100644 index 0342bf9340a9e..0000000000000 --- a/pkg/udf/service.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2023 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 udf - -import ( - "context" - - "github.com/matrixorigin/matrixone/pkg/common/moerr" -) - -func NewService(services ...Service) (Service, error) { - srv := &service{} - srv.mapping = make(map[string]Service, len(services)) - for _, s := range services { - if srv.mapping[s.Language()] == nil { - srv.mapping[s.Language()] = s - } else { - return nil, moerr.NewInternalErrorNoCtx("too many " + s.Language() + " udf service") - } - } - return srv, nil -} - -type service struct { - mapping map[string]Service -} - -func (s *service) Language() string { - return "multiple" -} - -func (s *service) Run(ctx context.Context, request *Request, pkgReader PkgReader) (*Response, error) { - srv := s.mapping[request.Udf.Language] - if srv == nil { - return nil, moerr.NewInternalError(ctx, "missing "+request.Udf.Language+" udf service") - } - return srv.Run(ctx, request, pkgReader) -} diff --git a/pkg/udf/testdata/python_status_wire.json b/pkg/udf/testdata/python_status_wire.json new file mode 100644 index 0000000000000..6b35d431092a8 --- /dev/null +++ b/pkg/udf/testdata/python_status_wire.json @@ -0,0 +1,52 @@ +[ + { + "Class": "", + "Reason": "CapabilityHandshakeReady", + "Wire": "CAcQKdoBAOoBAPIBAPoBAIICAIoCAJICAKICAMoCANICAOICMQoEY24tMRIGcHl0aG9uGAEgASgBOhhDYXBhYmlsaXR5SGFuZHNoYWtlUmVhZHmwASo=" + }, + { + "Class": "DISABLED", + "Reason": "RuntimeDisabled", + "Wire": "CAcQKdoBAOoBAPIBAPoBAIICAIoCAJICAKICAMoCANICAOICLgoEY24tMRIGcHl0aG9uIAEyCERJU0FCTEVEOg9SdW50aW1lRGlzYWJsZWSwASo=" + }, + { + "Class": "NOT_ALLOWED", + "Reason": "UnisolatedExecutionNotAllowed", + "Wire": "CAcQKdoBAOoBAPIBAPoBAIICAIoCAJICAKICAMoCANICAOICPwoEY24tMRIGcHl0aG9uGAEyC05PVF9BTExPV0VEOh1Vbmlzb2xhdGVkRXhlY3V0aW9uTm90QWxsb3dlZLABKg==" + }, + { + "Class": "UNAVAILABLE", + "Reason": "WorkerUnavailable", + "Wire": "CAcQKdoBAOoBAPIBAPoBAIICAIoCAJICAKICAMoCANICAOICNQoEY24tMRIGcHl0aG9uGAEgATILVU5BVkFJTEFCTEU6EVdvcmtlclVuYXZhaWxhYmxlsAEq" + }, + { + "Class": "UNAVAILABLE", + "Reason": "RuntimeStatusUnavailable", + "Wire": "CAcQKdoBAOoBAPIBAPoBAIICAIoCAJICAKICAMoCANICAOICPAoEY24tMRIGcHl0aG9uGAEgATILVU5BVkFJTEFCTEU6GFJ1bnRpbWVTdGF0dXNVbmF2YWlsYWJsZbABKg==" + }, + { + "Class": "CONTRACT_MISMATCH", + "Reason": "CapabilityContractMismatch", + "Wire": "CAcQKdoBAOoBAPIBAPoBAIICAIoCAJICAKICAMoCANICAOICRAoEY24tMRIGcHl0aG9uGAEgATIRQ09OVFJBQ1RfTUlTTUFUQ0g6GkNhcGFiaWxpdHlDb250cmFjdE1pc21hdGNosAEq" + }, + { + "Class": "TIMEOUT", + "Reason": "CapabilityRequestTimeout", + "Wire": "CAcQKdoBAOoBAPIBAPoBAIICAIoCAJICAKICAMoCANICAOICOAoEY24tMRIGcHl0aG9uGAEgATIHVElNRU9VVDoYQ2FwYWJpbGl0eVJlcXVlc3RUaW1lb3V0sAEq" + }, + { + "Class": "CLOSED", + "Reason": "RuntimeClosed", + "Wire": "CAcQKdoBAOoBAPIBAPoBAIICAIoCAJICAKICAMoCANICAOICLAoEY24tMRIGcHl0aG9uGAEgATIGQ0xPU0VEOg1SdW50aW1lQ2xvc2VksAEq" + }, + { + "Class": "INVALID", + "Reason": "InvalidLanguage", + "Wire": "CAcQKdoBAOoBAPIBAPoBAIICAIoCAJICAKICAMoCANICAOICLwoEY24tMRIGcHl0aG9uGAEgATIHSU5WQUxJRDoPSW52YWxpZExhbmd1YWdlsAEq" + }, + { + "Class": "INTERNAL", + "Reason": "RuntimeError", + "Wire": "CAcQKdoBAOoBAPIBAPoBAIICAIoCAJICAKICAMoCANICAOICLQoEY24tMRIGcHl0aG9uGAEgATIISU5URVJOQUw6DFJ1bnRpbWVFcnJvcrABKg==" + } +] diff --git a/pkg/udf/timezone.go b/pkg/udf/timezone.go new file mode 100644 index 0000000000000..9053fb472087c --- /dev/null +++ b/pkg/udf/timezone.go @@ -0,0 +1,57 @@ +// Copyright 2026 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 udf + +import ( + "bufio" + "os" + "strings" + + "github.com/matrixorigin/matrixone/pkg/udf/udferr" +) + +// TimezoneDatabaseVersion returns the version of the system IANA tz database +// used by the current process. An IANA timezone is part of the Python UDF +// statement contract, so silently returning a made-up version would allow two +// hosts to interpret a DST boundary differently. +func TimezoneDatabaseVersion() (string, error) { + paths := []string{ + "/usr/share/zoneinfo/tzdata.zi", + "/usr/lib/zoneinfo/tzdata.zi", + "/usr/share/lib/zoneinfo/tzdata.zi", + "/etc/zoneinfo/tzdata.zi", + } + for _, path := range paths { + file, err := os.Open(path) + if err != nil { + continue + } + scanner := bufio.NewScanner(file) + lineOK := scanner.Scan() + line := scanner.Text() + _ = file.Close() + if !lineOK { + continue + } + const prefix = "# version " + if strings.HasPrefix(line, prefix) { + version := strings.TrimSpace(strings.TrimPrefix(line, prefix)) + if version != "" { + return version, nil + } + } + } + return "", udferr.Newf("python udf: IANA timezone database version is unavailable") +} diff --git a/pkg/udf/types.go b/pkg/udf/types.go deleted file mode 100644 index 7adc0833377fb..0000000000000 --- a/pkg/udf/types.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2023 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 udf - -import ( - "context" - "io" -) - -const ( - LanguagePython = "python" -) - -// Service handle non-sql udf in cn -type Service interface { - Language() string - Run(ctx context.Context, request *Request, pkgReader PkgReader) (*Response, error) -} - -// PkgReader read udf package from storage -type PkgReader interface { - Get(ctx context.Context, path string) (reader io.ReadCloser, err error) -} - -// PkgUploader upload udf package to storage -type PkgUploader interface { - Upload(ctx context.Context, localPath string, storageDir string) (storagePath string, err error) -} diff --git a/pkg/udf/udf.pb.go b/pkg/udf/udf.pb.go deleted file mode 100644 index 4db1253b016ca..0000000000000 --- a/pkg/udf/udf.pb.go +++ /dev/null @@ -1,1068 +0,0 @@ -// Copyright 2023 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. - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.28.1 -// protoc v3.17.0 -// source: udf.proto - -package udf - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type RequestType int32 - -const ( - RequestType_UnknownRequest RequestType = 0 - RequestType_DataRequest RequestType = 1 // request with data for function result - RequestType_PkgResponse RequestType = 2 // response with package -) - -// Enum value maps for RequestType. -var ( - RequestType_name = map[int32]string{ - 0: "UnknownRequest", - 1: "DataRequest", - 2: "PkgResponse", - } - RequestType_value = map[string]int32{ - "UnknownRequest": 0, - "DataRequest": 1, - "PkgResponse": 2, - } -) - -func (x RequestType) Enum() *RequestType { - p := new(RequestType) - *p = x - return p -} - -func (x RequestType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (RequestType) Descriptor() protoreflect.EnumDescriptor { - return file_udf_proto_enumTypes[0].Descriptor() -} - -func (RequestType) Type() protoreflect.EnumType { - return &file_udf_proto_enumTypes[0] -} - -func (x RequestType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use RequestType.Descriptor instead. -func (RequestType) EnumDescriptor() ([]byte, []int) { - return file_udf_proto_rawDescGZIP(), []int{0} -} - -type ResponseType int32 - -const ( - ResponseType_UnknownResponse ResponseType = 0 - ResponseType_DataResponse ResponseType = 1 // response with function result - ResponseType_PkgRequest ResponseType = 2 // request for package -) - -// Enum value maps for ResponseType. -var ( - ResponseType_name = map[int32]string{ - 0: "UnknownResponse", - 1: "DataResponse", - 2: "PkgRequest", - } - ResponseType_value = map[string]int32{ - "UnknownResponse": 0, - "DataResponse": 1, - "PkgRequest": 2, - } -) - -func (x ResponseType) Enum() *ResponseType { - p := new(ResponseType) - *p = x - return p -} - -func (x ResponseType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ResponseType) Descriptor() protoreflect.EnumDescriptor { - return file_udf_proto_enumTypes[1].Descriptor() -} - -func (ResponseType) Type() protoreflect.EnumType { - return &file_udf_proto_enumTypes[1] -} - -func (x ResponseType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ResponseType.Descriptor instead. -func (ResponseType) EnumDescriptor() ([]byte, []int) { - return file_udf_proto_rawDescGZIP(), []int{1} -} - -type DataType int32 - -const ( - DataType_UNKNOWN DataType = 0 - DataType_BOOL DataType = 10 - DataType_INT8 DataType = 20 - DataType_INT16 DataType = 21 - DataType_INT32 DataType = 22 - DataType_INT64 DataType = 23 - DataType_UINT8 DataType = 30 - DataType_UINT16 DataType = 31 - DataType_UINT32 DataType = 32 - DataType_UINT64 DataType = 33 - DataType_FLOAT32 DataType = 40 - DataType_FLOAT64 DataType = 41 - DataType_CHAR DataType = 50 - DataType_VARCHAR DataType = 51 - DataType_TEXT DataType = 52 - DataType_JSON DataType = 53 - DataType_UUID DataType = 54 - DataType_TIME DataType = 60 - DataType_DATE DataType = 61 - DataType_DATETIME DataType = 62 - DataType_TIMESTAMP DataType = 63 - DataType_DECIMAL64 DataType = 70 - DataType_DECIMAL128 DataType = 71 - DataType_BINARY DataType = 80 - DataType_VARBINARY DataType = 81 - DataType_BLOB DataType = 82 -) - -// Enum value maps for DataType. -var ( - DataType_name = map[int32]string{ - 0: "UNKNOWN", - 10: "BOOL", - 20: "INT8", - 21: "INT16", - 22: "INT32", - 23: "INT64", - 30: "UINT8", - 31: "UINT16", - 32: "UINT32", - 33: "UINT64", - 40: "FLOAT32", - 41: "FLOAT64", - 50: "CHAR", - 51: "VARCHAR", - 52: "TEXT", - 53: "JSON", - 54: "UUID", - 60: "TIME", - 61: "DATE", - 62: "DATETIME", - 63: "TIMESTAMP", - 70: "DECIMAL64", - 71: "DECIMAL128", - 80: "BINARY", - 81: "VARBINARY", - 82: "BLOB", - } - DataType_value = map[string]int32{ - "UNKNOWN": 0, - "BOOL": 10, - "INT8": 20, - "INT16": 21, - "INT32": 22, - "INT64": 23, - "UINT8": 30, - "UINT16": 31, - "UINT32": 32, - "UINT64": 33, - "FLOAT32": 40, - "FLOAT64": 41, - "CHAR": 50, - "VARCHAR": 51, - "TEXT": 52, - "JSON": 53, - "UUID": 54, - "TIME": 60, - "DATE": 61, - "DATETIME": 62, - "TIMESTAMP": 63, - "DECIMAL64": 70, - "DECIMAL128": 71, - "BINARY": 80, - "VARBINARY": 81, - "BLOB": 82, - } -) - -func (x DataType) Enum() *DataType { - p := new(DataType) - *p = x - return p -} - -func (x DataType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (DataType) Descriptor() protoreflect.EnumDescriptor { - return file_udf_proto_enumTypes[2].Descriptor() -} - -func (DataType) Type() protoreflect.EnumType { - return &file_udf_proto_enumTypes[2] -} - -func (x DataType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use DataType.Descriptor instead. -func (DataType) EnumDescriptor() ([]byte, []int) { - return file_udf_proto_rawDescGZIP(), []int{2} -} - -type Request struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Udf *Udf `protobuf:"bytes,1,opt,name=udf,proto3" json:"udf,omitempty"` - Vectors []*DataVector `protobuf:"bytes,2,rep,name=vectors,proto3" json:"vectors,omitempty"` - Length int64 `protobuf:"varint,3,opt,name=length,proto3" json:"length,omitempty"` - Type RequestType `protobuf:"varint,4,opt,name=type,proto3,enum=udf.RequestType" json:"type,omitempty"` - Context map[string]string `protobuf:"bytes,5,rep,name=context,proto3" json:"context,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // currently just transfer, not used -} - -func (x *Request) Reset() { - *x = Request{} - if protoimpl.UnsafeEnabled { - mi := &file_udf_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Request) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Request) ProtoMessage() {} - -func (x *Request) ProtoReflect() protoreflect.Message { - mi := &file_udf_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Request.ProtoReflect.Descriptor instead. -func (*Request) Descriptor() ([]byte, []int) { - return file_udf_proto_rawDescGZIP(), []int{0} -} - -func (x *Request) GetUdf() *Udf { - if x != nil { - return x.Udf - } - return nil -} - -func (x *Request) GetVectors() []*DataVector { - if x != nil { - return x.Vectors - } - return nil -} - -func (x *Request) GetLength() int64 { - if x != nil { - return x.Length - } - return 0 -} - -func (x *Request) GetType() RequestType { - if x != nil { - return x.Type - } - return RequestType_UnknownRequest -} - -func (x *Request) GetContext() map[string]string { - if x != nil { - return x.Context - } - return nil -} - -type Response struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Vector *DataVector `protobuf:"bytes,1,opt,name=vector,proto3" json:"vector,omitempty"` - Type ResponseType `protobuf:"varint,2,opt,name=type,proto3,enum=udf.ResponseType" json:"type,omitempty"` -} - -func (x *Response) Reset() { - *x = Response{} - if protoimpl.UnsafeEnabled { - mi := &file_udf_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Response) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Response) ProtoMessage() {} - -func (x *Response) ProtoReflect() protoreflect.Message { - mi := &file_udf_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Response.ProtoReflect.Descriptor instead. -func (*Response) Descriptor() ([]byte, []int) { - return file_udf_proto_rawDescGZIP(), []int{1} -} - -func (x *Response) GetVector() *DataVector { - if x != nil { - return x.Vector - } - return nil -} - -func (x *Response) GetType() ResponseType { - if x != nil { - return x.Type - } - return ResponseType_UnknownResponse -} - -type Udf struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Handler string `protobuf:"bytes,1,opt,name=handler,proto3" json:"handler,omitempty"` - IsImport bool `protobuf:"varint,2,opt,name=isImport,proto3" json:"isImport,omitempty"` - Body string `protobuf:"bytes,3,opt,name=body,proto3" json:"body,omitempty"` - ImportPkg *Package `protobuf:"bytes,4,opt,name=importPkg,proto3" json:"importPkg,omitempty"` - RetType DataType `protobuf:"varint,5,opt,name=retType,proto3,enum=udf.DataType" json:"retType,omitempty"` - Language string `protobuf:"bytes,6,opt,name=language,proto3" json:"language,omitempty"` - ModifiedTime string `protobuf:"bytes,7,opt,name=modifiedTime,proto3" json:"modifiedTime,omitempty"` - Db string `protobuf:"bytes,8,opt,name=db,proto3" json:"db,omitempty"` -} - -func (x *Udf) Reset() { - *x = Udf{} - if protoimpl.UnsafeEnabled { - mi := &file_udf_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Udf) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Udf) ProtoMessage() {} - -func (x *Udf) ProtoReflect() protoreflect.Message { - mi := &file_udf_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Udf.ProtoReflect.Descriptor instead. -func (*Udf) Descriptor() ([]byte, []int) { - return file_udf_proto_rawDescGZIP(), []int{2} -} - -func (x *Udf) GetHandler() string { - if x != nil { - return x.Handler - } - return "" -} - -func (x *Udf) GetIsImport() bool { - if x != nil { - return x.IsImport - } - return false -} - -func (x *Udf) GetBody() string { - if x != nil { - return x.Body - } - return "" -} - -func (x *Udf) GetImportPkg() *Package { - if x != nil { - return x.ImportPkg - } - return nil -} - -func (x *Udf) GetRetType() DataType { - if x != nil { - return x.RetType - } - return DataType_UNKNOWN -} - -func (x *Udf) GetLanguage() string { - if x != nil { - return x.Language - } - return "" -} - -func (x *Udf) GetModifiedTime() string { - if x != nil { - return x.ModifiedTime - } - return "" -} - -func (x *Udf) GetDb() string { - if x != nil { - return x.Db - } - return "" -} - -type Package struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` - Last bool `protobuf:"varint,2,opt,name=last,proto3" json:"last,omitempty"` -} - -func (x *Package) Reset() { - *x = Package{} - if protoimpl.UnsafeEnabled { - mi := &file_udf_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Package) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Package) ProtoMessage() {} - -func (x *Package) ProtoReflect() protoreflect.Message { - mi := &file_udf_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Package.ProtoReflect.Descriptor instead. -func (*Package) Descriptor() ([]byte, []int) { - return file_udf_proto_rawDescGZIP(), []int{3} -} - -func (x *Package) GetData() []byte { - if x != nil { - return x.Data - } - return nil -} - -func (x *Package) GetLast() bool { - if x != nil { - return x.Last - } - return false -} - -type DataVector struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Data []*Data `protobuf:"bytes,1,rep,name=data,proto3" json:"data,omitempty"` - Const bool `protobuf:"varint,2,opt,name=const,proto3" json:"const,omitempty"` - Length int64 `protobuf:"varint,3,opt,name=length,proto3" json:"length,omitempty"` - Type DataType `protobuf:"varint,4,opt,name=type,proto3,enum=udf.DataType" json:"type,omitempty"` - Scale int32 `protobuf:"varint,5,opt,name=scale,proto3" json:"scale,omitempty"` -} - -func (x *DataVector) Reset() { - *x = DataVector{} - if protoimpl.UnsafeEnabled { - mi := &file_udf_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DataVector) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DataVector) ProtoMessage() {} - -func (x *DataVector) ProtoReflect() protoreflect.Message { - mi := &file_udf_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DataVector.ProtoReflect.Descriptor instead. -func (*DataVector) Descriptor() ([]byte, []int) { - return file_udf_proto_rawDescGZIP(), []int{4} -} - -func (x *DataVector) GetData() []*Data { - if x != nil { - return x.Data - } - return nil -} - -func (x *DataVector) GetConst() bool { - if x != nil { - return x.Const - } - return false -} - -func (x *DataVector) GetLength() int64 { - if x != nil { - return x.Length - } - return 0 -} - -func (x *DataVector) GetType() DataType { - if x != nil { - return x.Type - } - return DataType_UNKNOWN -} - -func (x *DataVector) GetScale() int32 { - if x != nil { - return x.Scale - } - return 0 -} - -type Data struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Val: - // - // *Data_BoolVal - // *Data_IntVal - // *Data_Int64Val - // *Data_UintVal - // *Data_Uint64Val - // *Data_FloatVal - // *Data_DoubleVal - // *Data_StringVal - // *Data_BytesVal - Val isData_Val `protobuf_oneof:"val"` -} - -func (x *Data) Reset() { - *x = Data{} - if protoimpl.UnsafeEnabled { - mi := &file_udf_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Data) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Data) ProtoMessage() {} - -func (x *Data) ProtoReflect() protoreflect.Message { - mi := &file_udf_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Data.ProtoReflect.Descriptor instead. -func (*Data) Descriptor() ([]byte, []int) { - return file_udf_proto_rawDescGZIP(), []int{5} -} - -func (m *Data) GetVal() isData_Val { - if m != nil { - return m.Val - } - return nil -} - -func (x *Data) GetBoolVal() bool { - if x, ok := x.GetVal().(*Data_BoolVal); ok { - return x.BoolVal - } - return false -} - -func (x *Data) GetIntVal() int32 { - if x, ok := x.GetVal().(*Data_IntVal); ok { - return x.IntVal - } - return 0 -} - -func (x *Data) GetInt64Val() int64 { - if x, ok := x.GetVal().(*Data_Int64Val); ok { - return x.Int64Val - } - return 0 -} - -func (x *Data) GetUintVal() uint32 { - if x, ok := x.GetVal().(*Data_UintVal); ok { - return x.UintVal - } - return 0 -} - -func (x *Data) GetUint64Val() uint64 { - if x, ok := x.GetVal().(*Data_Uint64Val); ok { - return x.Uint64Val - } - return 0 -} - -func (x *Data) GetFloatVal() float32 { - if x, ok := x.GetVal().(*Data_FloatVal); ok { - return x.FloatVal - } - return 0 -} - -func (x *Data) GetDoubleVal() float64 { - if x, ok := x.GetVal().(*Data_DoubleVal); ok { - return x.DoubleVal - } - return 0 -} - -func (x *Data) GetStringVal() string { - if x, ok := x.GetVal().(*Data_StringVal); ok { - return x.StringVal - } - return "" -} - -func (x *Data) GetBytesVal() []byte { - if x, ok := x.GetVal().(*Data_BytesVal); ok { - return x.BytesVal - } - return nil -} - -type isData_Val interface { - isData_Val() -} - -type Data_BoolVal struct { - BoolVal bool `protobuf:"varint,1,opt,name=boolVal,proto3,oneof"` // bool -} - -type Data_IntVal struct { - IntVal int32 `protobuf:"zigzag32,2,opt,name=intVal,proto3,oneof"` // int8, int16, int32 -} - -type Data_Int64Val struct { - Int64Val int64 `protobuf:"zigzag64,3,opt,name=int64Val,proto3,oneof"` // int64 -} - -type Data_UintVal struct { - UintVal uint32 `protobuf:"varint,4,opt,name=uintVal,proto3,oneof"` // uint8, uint16, uint32 -} - -type Data_Uint64Val struct { - Uint64Val uint64 `protobuf:"varint,5,opt,name=uint64Val,proto3,oneof"` // uint64 -} - -type Data_FloatVal struct { - FloatVal float32 `protobuf:"fixed32,6,opt,name=floatVal,proto3,oneof"` // float32 -} - -type Data_DoubleVal struct { - DoubleVal float64 `protobuf:"fixed64,7,opt,name=doubleVal,proto3,oneof"` // float64 -} - -type Data_StringVal struct { - StringVal string `protobuf:"bytes,8,opt,name=stringVal,proto3,oneof"` // char, varchar, text, json, uuid | time, date, datetime, timestamp | Decimal64, Decimal128 -} - -type Data_BytesVal struct { - BytesVal []byte `protobuf:"bytes,9,opt,name=bytesVal,proto3,oneof"` // binary, varbinary, blob -} - -func (*Data_BoolVal) isData_Val() {} - -func (*Data_IntVal) isData_Val() {} - -func (*Data_Int64Val) isData_Val() {} - -func (*Data_UintVal) isData_Val() {} - -func (*Data_Uint64Val) isData_Val() {} - -func (*Data_FloatVal) isData_Val() {} - -func (*Data_DoubleVal) isData_Val() {} - -func (*Data_StringVal) isData_Val() {} - -func (*Data_BytesVal) isData_Val() {} - -var File_udf_proto protoreflect.FileDescriptor - -var file_udf_proto_rawDesc = []byte{ - 0x0a, 0x09, 0x75, 0x64, 0x66, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x75, 0x64, 0x66, - 0x22, 0xff, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x03, - 0x75, 0x64, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x75, 0x64, 0x66, 0x2e, - 0x55, 0x64, 0x66, 0x52, 0x03, 0x75, 0x64, 0x66, 0x12, 0x29, 0x0a, 0x07, 0x76, 0x65, 0x63, 0x74, - 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x75, 0x64, 0x66, 0x2e, - 0x44, 0x61, 0x74, 0x61, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x07, 0x76, 0x65, 0x63, 0x74, - 0x6f, 0x72, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x75, 0x64, 0x66, 0x2e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x12, 0x33, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x05, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x75, 0x64, 0x66, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x1a, 0x3a, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0x5a, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, - 0x0a, 0x06, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, - 0x2e, 0x75, 0x64, 0x66, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, - 0x06, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x25, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x75, 0x64, 0x66, 0x2e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xf4, - 0x01, 0x0a, 0x03, 0x55, 0x64, 0x66, 0x12, 0x18, 0x0a, 0x07, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, - 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, - 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x73, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x12, 0x2a, 0x0a, 0x09, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x6b, 0x67, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x75, 0x64, 0x66, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0x52, 0x09, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x6b, 0x67, 0x12, 0x27, 0x0a, 0x07, - 0x72, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0d, 0x2e, - 0x75, 0x64, 0x66, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x72, 0x65, - 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, - 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, - 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x54, 0x69, 0x6d, - 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, - 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x64, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x64, 0x62, 0x22, 0x31, 0x0a, 0x07, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, - 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, - 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x61, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x04, 0x6c, 0x61, 0x73, 0x74, 0x22, 0x92, 0x01, 0x0a, 0x0a, 0x44, 0x61, 0x74, - 0x61, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1d, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x75, 0x64, 0x66, 0x2e, 0x44, 0x61, 0x74, 0x61, - 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, - 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x12, 0x21, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x75, 0x64, 0x66, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, - 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x61, 0x6c, 0x65, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x22, 0x99, 0x02, - 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1a, 0x0a, 0x07, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, - 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x62, 0x6f, 0x6f, 0x6c, 0x56, - 0x61, 0x6c, 0x12, 0x18, 0x0a, 0x06, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x11, 0x48, 0x00, 0x52, 0x06, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x08, - 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x12, 0x48, 0x00, - 0x52, 0x08, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x12, 0x1a, 0x0a, 0x07, 0x75, 0x69, - 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x07, 0x75, - 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x12, 0x1e, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, - 0x56, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x09, 0x75, 0x69, 0x6e, - 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x08, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x56, - 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x02, 0x48, 0x00, 0x52, 0x08, 0x66, 0x6c, 0x6f, 0x61, - 0x74, 0x56, 0x61, 0x6c, 0x12, 0x1e, 0x0a, 0x09, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, - 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x09, 0x64, 0x6f, 0x75, 0x62, 0x6c, - 0x65, 0x56, 0x61, 0x6c, 0x12, 0x1e, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, - 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x73, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x56, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x08, 0x62, 0x79, 0x74, 0x65, 0x73, 0x56, 0x61, 0x6c, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x08, 0x62, 0x79, 0x74, 0x65, 0x73, 0x56, - 0x61, 0x6c, 0x42, 0x05, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x2a, 0x43, 0x0a, 0x0b, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x0e, 0x55, 0x6e, 0x6b, 0x6e, - 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, - 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x01, 0x12, 0x0f, 0x0a, - 0x0b, 0x50, 0x6b, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x10, 0x02, 0x2a, 0x45, - 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x13, - 0x0a, 0x0f, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x6b, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x10, 0x02, 0x2a, 0xbf, 0x02, 0x0a, 0x08, 0x44, 0x61, 0x74, 0x61, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, - 0x08, 0x0a, 0x04, 0x42, 0x4f, 0x4f, 0x4c, 0x10, 0x0a, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x54, - 0x38, 0x10, 0x14, 0x12, 0x09, 0x0a, 0x05, 0x49, 0x4e, 0x54, 0x31, 0x36, 0x10, 0x15, 0x12, 0x09, - 0x0a, 0x05, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x16, 0x12, 0x09, 0x0a, 0x05, 0x49, 0x4e, 0x54, - 0x36, 0x34, 0x10, 0x17, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x49, 0x4e, 0x54, 0x38, 0x10, 0x1e, 0x12, - 0x0a, 0x0a, 0x06, 0x55, 0x49, 0x4e, 0x54, 0x31, 0x36, 0x10, 0x1f, 0x12, 0x0a, 0x0a, 0x06, 0x55, - 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x20, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x49, 0x4e, 0x54, 0x36, - 0x34, 0x10, 0x21, 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x33, 0x32, 0x10, 0x28, - 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x36, 0x34, 0x10, 0x29, 0x12, 0x08, 0x0a, - 0x04, 0x43, 0x48, 0x41, 0x52, 0x10, 0x32, 0x12, 0x0b, 0x0a, 0x07, 0x56, 0x41, 0x52, 0x43, 0x48, - 0x41, 0x52, 0x10, 0x33, 0x12, 0x08, 0x0a, 0x04, 0x54, 0x45, 0x58, 0x54, 0x10, 0x34, 0x12, 0x08, - 0x0a, 0x04, 0x4a, 0x53, 0x4f, 0x4e, 0x10, 0x35, 0x12, 0x08, 0x0a, 0x04, 0x55, 0x55, 0x49, 0x44, - 0x10, 0x36, 0x12, 0x08, 0x0a, 0x04, 0x54, 0x49, 0x4d, 0x45, 0x10, 0x3c, 0x12, 0x08, 0x0a, 0x04, - 0x44, 0x41, 0x54, 0x45, 0x10, 0x3d, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x41, 0x54, 0x45, 0x54, 0x49, - 0x4d, 0x45, 0x10, 0x3e, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x49, 0x4d, 0x45, 0x53, 0x54, 0x41, 0x4d, - 0x50, 0x10, 0x3f, 0x12, 0x0d, 0x0a, 0x09, 0x44, 0x45, 0x43, 0x49, 0x4d, 0x41, 0x4c, 0x36, 0x34, - 0x10, 0x46, 0x12, 0x0e, 0x0a, 0x0a, 0x44, 0x45, 0x43, 0x49, 0x4d, 0x41, 0x4c, 0x31, 0x32, 0x38, - 0x10, 0x47, 0x12, 0x0a, 0x0a, 0x06, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x10, 0x50, 0x12, 0x0d, - 0x0a, 0x09, 0x56, 0x41, 0x52, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x10, 0x51, 0x12, 0x08, 0x0a, - 0x04, 0x42, 0x4c, 0x4f, 0x42, 0x10, 0x52, 0x32, 0x33, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x28, 0x0a, 0x03, 0x72, 0x75, 0x6e, 0x12, 0x0c, 0x2e, 0x75, 0x64, 0x66, 0x2e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0d, 0x2e, 0x75, 0x64, 0x66, 0x2e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x2b, 0x5a, 0x29, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x61, 0x74, 0x72, 0x69, - 0x78, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x6f, 0x6e, - 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x75, 0x64, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, -} - -var ( - file_udf_proto_rawDescOnce sync.Once - file_udf_proto_rawDescData = file_udf_proto_rawDesc -) - -func file_udf_proto_rawDescGZIP() []byte { - file_udf_proto_rawDescOnce.Do(func() { - file_udf_proto_rawDescData = protoimpl.X.CompressGZIP(file_udf_proto_rawDescData) - }) - return file_udf_proto_rawDescData -} - -var file_udf_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_udf_proto_msgTypes = make([]protoimpl.MessageInfo, 7) -var file_udf_proto_goTypes = []interface{}{ - (RequestType)(0), // 0: udf.RequestType - (ResponseType)(0), // 1: udf.ResponseType - (DataType)(0), // 2: udf.DataType - (*Request)(nil), // 3: udf.Request - (*Response)(nil), // 4: udf.Response - (*Udf)(nil), // 5: udf.Udf - (*Package)(nil), // 6: udf.Package - (*DataVector)(nil), // 7: udf.DataVector - (*Data)(nil), // 8: udf.Data - nil, // 9: udf.Request.ContextEntry -} -var file_udf_proto_depIdxs = []int32{ - 5, // 0: udf.Request.udf:type_name -> udf.Udf - 7, // 1: udf.Request.vectors:type_name -> udf.DataVector - 0, // 2: udf.Request.type:type_name -> udf.RequestType - 9, // 3: udf.Request.context:type_name -> udf.Request.ContextEntry - 7, // 4: udf.Response.vector:type_name -> udf.DataVector - 1, // 5: udf.Response.type:type_name -> udf.ResponseType - 6, // 6: udf.Udf.importPkg:type_name -> udf.Package - 2, // 7: udf.Udf.retType:type_name -> udf.DataType - 8, // 8: udf.DataVector.data:type_name -> udf.Data - 2, // 9: udf.DataVector.type:type_name -> udf.DataType - 3, // 10: udf.Service.run:input_type -> udf.Request - 4, // 11: udf.Service.run:output_type -> udf.Response - 11, // [11:12] is the sub-list for method output_type - 10, // [10:11] is the sub-list for method input_type - 10, // [10:10] is the sub-list for extension type_name - 10, // [10:10] is the sub-list for extension extendee - 0, // [0:10] is the sub-list for field type_name -} - -func init() { file_udf_proto_init() } -func file_udf_proto_init() { - if File_udf_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_udf_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Request); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_udf_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Response); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_udf_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Udf); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_udf_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Package); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_udf_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DataVector); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_udf_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Data); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_udf_proto_msgTypes[5].OneofWrappers = []interface{}{ - (*Data_BoolVal)(nil), - (*Data_IntVal)(nil), - (*Data_Int64Val)(nil), - (*Data_UintVal)(nil), - (*Data_Uint64Val)(nil), - (*Data_FloatVal)(nil), - (*Data_DoubleVal)(nil), - (*Data_StringVal)(nil), - (*Data_BytesVal)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_udf_proto_rawDesc, - NumEnums: 3, - NumMessages: 7, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_udf_proto_goTypes, - DependencyIndexes: file_udf_proto_depIdxs, - EnumInfos: file_udf_proto_enumTypes, - MessageInfos: file_udf_proto_msgTypes, - }.Build() - File_udf_proto = out.File - file_udf_proto_rawDesc = nil - file_udf_proto_goTypes = nil - file_udf_proto_depIdxs = nil -} diff --git a/pkg/udf/udf.proto b/pkg/udf/udf.proto deleted file mode 100644 index e21c500fab7f6..0000000000000 --- a/pkg/udf/udf.proto +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2023 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. - -syntax = "proto3"; - -package udf; - -option go_package = "github.com/matrixorigin/matrixone/pkg/udf"; - -// protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./udf.proto - -service Service { - rpc run(stream Request) returns (stream Response) {} -} - -enum RequestType { - UnknownRequest = 0; - DataRequest = 1; // request with data for function result - PkgResponse = 2; // response with package -} - -message Request { - Udf udf = 1; - repeated DataVector vectors = 2; - int64 length = 3; - RequestType type = 4; - map context = 5; // currently just transfer, not used -} - -enum ResponseType { - UnknownResponse = 0; - DataResponse = 1; // response with function result - PkgRequest = 2; // request for package -} - -message Response { - DataVector vector = 1; - ResponseType type = 2; -} - -message Udf { - string handler = 1; - bool isImport = 2; - string body = 3; - Package importPkg = 4; - DataType retType = 5; - string language = 6; - string modifiedTime = 7; - string db = 8; -} - -message Package { - bytes data = 1; - bool last = 2; -} - -message DataVector { - repeated Data data = 1; - bool const = 2; - int64 length = 3; - DataType type = 4; - int32 scale = 5; -} - -enum DataType { - UNKNOWN = 0; - - BOOL = 10; - - INT8 = 20; - INT16 = 21; - INT32 = 22; - INT64 = 23; - - UINT8 = 30; - UINT16 = 31; - UINT32 = 32; - UINT64 = 33; - - FLOAT32 = 40; - FLOAT64 = 41; - - CHAR = 50; - VARCHAR = 51; - TEXT = 52; - JSON = 53; - UUID = 54; - - TIME = 60; - DATE = 61; - DATETIME = 62; - TIMESTAMP = 63; - - DECIMAL64 = 70; - DECIMAL128 = 71; - - - BINARY = 80; - VARBINARY = 81; - BLOB = 82; -} - -message Data { - oneof val { - bool boolVal = 1; // bool - sint32 intVal = 2; // int8, int16, int32 - sint64 int64Val = 3; // int64 - uint32 uintVal = 4; // uint8, uint16, uint32 - uint64 uint64Val = 5; // uint64 - float floatVal = 6; // float32 - double doubleVal = 7; // float64 - string stringVal = 8; // char, varchar, text, json, uuid | time, date, datetime, timestamp | Decimal64, Decimal128 - bytes bytesVal = 9; // binary, varbinary, blob - } -} \ No newline at end of file diff --git a/pkg/udf/udf_grpc.pb.go b/pkg/udf/udf_grpc.pb.go deleted file mode 100644 index 5e863134bba82..0000000000000 --- a/pkg/udf/udf_grpc.pb.go +++ /dev/null @@ -1,137 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.2.0 -// - protoc v3.17.0 -// source: udf.proto - -package udf - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -// ServiceClient is the client API for Service service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type ServiceClient interface { - Run(ctx context.Context, opts ...grpc.CallOption) (Service_RunClient, error) -} - -type serviceClient struct { - cc grpc.ClientConnInterface -} - -func NewServiceClient(cc grpc.ClientConnInterface) ServiceClient { - return &serviceClient{cc} -} - -func (c *serviceClient) Run(ctx context.Context, opts ...grpc.CallOption) (Service_RunClient, error) { - stream, err := c.cc.NewStream(ctx, &Service_ServiceDesc.Streams[0], "/udf.Service/run", opts...) - if err != nil { - return nil, err - } - x := &serviceRunClient{stream} - return x, nil -} - -type Service_RunClient interface { - Send(*Request) error - Recv() (*Response, error) - grpc.ClientStream -} - -type serviceRunClient struct { - grpc.ClientStream -} - -func (x *serviceRunClient) Send(m *Request) error { - return x.ClientStream.SendMsg(m) -} - -func (x *serviceRunClient) Recv() (*Response, error) { - m := new(Response) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -// ServiceServer is the server API for Service service. -// All implementations must embed UnimplementedServiceServer -// for forward compatibility -type ServiceServer interface { - Run(Service_RunServer) error - mustEmbedUnimplementedServiceServer() -} - -// UnimplementedServiceServer must be embedded to have forward compatible implementations. -type UnimplementedServiceServer struct { -} - -func (UnimplementedServiceServer) Run(Service_RunServer) error { - return status.Errorf(codes.Unimplemented, "method Run not implemented") -} -func (UnimplementedServiceServer) mustEmbedUnimplementedServiceServer() {} - -// UnsafeServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to ServiceServer will -// result in compilation errors. -type UnsafeServiceServer interface { - mustEmbedUnimplementedServiceServer() -} - -func RegisterServiceServer(s grpc.ServiceRegistrar, srv ServiceServer) { - s.RegisterService(&Service_ServiceDesc, srv) -} - -func _Service_Run_Handler(srv interface{}, stream grpc.ServerStream) error { - return srv.(ServiceServer).Run(&serviceRunServer{stream}) -} - -type Service_RunServer interface { - Send(*Response) error - Recv() (*Request, error) - grpc.ServerStream -} - -type serviceRunServer struct { - grpc.ServerStream -} - -func (x *serviceRunServer) Send(m *Response) error { - return x.ServerStream.SendMsg(m) -} - -func (x *serviceRunServer) Recv() (*Request, error) { - m := new(Request) - if err := x.ServerStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -// Service_ServiceDesc is the grpc.ServiceDesc for Service service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var Service_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "udf.Service", - HandlerType: (*ServiceServer)(nil), - Methods: []grpc.MethodDesc{}, - Streams: []grpc.StreamDesc{ - { - StreamName: "run", - Handler: _Service_Run_Handler, - ServerStreams: true, - ClientStreams: true, - }, - }, - Metadata: "udf.proto", -} diff --git a/pkg/udf/udferr/errors.go b/pkg/udf/udferr/errors.go new file mode 100644 index 0000000000000..24f123728691f --- /dev/null +++ b/pkg/udf/udferr/errors.go @@ -0,0 +1,33 @@ +// Copyright 2026 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 udferr defines diagnostic errors for the routine catalog and external +// execution contract. These errors retain the domain's message verbatim; they +// are not MO SQL error classifications. Callers that own a specific SQL error +// must continue to construct that moerr at the SQL boundary. +package udferr + +import "fmt" + +// Error is a routine-contract diagnostic. Each construction has distinct +// identity so equal text does not accidentally alias independent sentinels. +type Error struct{ message string } + +func (e *Error) Error() string { return e.message } + +func New(message string) error { return &Error{message: message} } + +// Newf formats a leaf diagnostic. Use errutil wrapping for an existing cause; +// this function deliberately does not interpret wrapping verbs. +func Newf(format string, args ...any) error { return New(fmt.Sprintf(format, args...)) } diff --git a/pkg/udf/udferr/errors_test.go b/pkg/udf/udferr/errors_test.go new file mode 100644 index 0000000000000..4a22db7f56d26 --- /dev/null +++ b/pkg/udf/udferr/errors_test.go @@ -0,0 +1,35 @@ +// Copyright 2026 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 udferr + +import ( + "errors" + "testing" + + "github.com/matrixorigin/matrixone/pkg/util/errutil" + "github.com/stretchr/testify/require" +) + +func TestDiagnosticIdentity(t *testing.T) { + first, second := New("TYPE_CONTRACT: invalid result"), New("TYPE_CONTRACT: invalid result") + wrapped := errutil.Wrapf(first, "gateway") + require.ErrorIs(t, wrapped, first) + require.NotErrorIs(t, wrapped, second) + var diagnostic *Error + require.True(t, errors.As(wrapped, &diagnostic)) + require.Equal(t, first, diagnostic) + require.EqualError(t, wrapped, "gateway: TYPE_CONTRACT: invalid result") + require.EqualError(t, Newf("invalid dimension %d", 3), "invalid dimension 3") +} diff --git a/pkg/util/errutil/errors.go b/pkg/util/errutil/errors.go index 5805b6918fe13..5106c0d03ecec 100644 --- a/pkg/util/errutil/errors.go +++ b/pkg/util/errutil/errors.go @@ -17,6 +17,7 @@ package errutil import ( "context" "errors" + "fmt" "sync/atomic" pkgErr "github.com/pkg/errors" @@ -42,6 +43,31 @@ func Wrapf(err error, format string, args ...any) error { return pkgErr.Wrapf(err, format, args...) } +type causeFirstError struct { + cause error + message string +} + +func (e *causeFirstError) Error() string { + if e.message == "" { + return e.cause.Error() + } + return e.cause.Error() + ": " + e.message +} + +func (e *causeFirstError) Unwrap() error { + return e.cause +} + +// WrapfCauseFirst preserves cause-first wrapped-error message order while +// retaining errors.Is/errors.As identity. +func WrapfCauseFirst(err error, format string, args ...any) error { + if err == nil { + return nil + } + return &causeFirstError{cause: err, message: fmt.Sprintf(format, args...)} +} + // WalkDeep does a depth-first traversal of all errors. // The visitor function can return true to end the traversal early, otherwise false. func WalkDeep(err error, visitor func(err error) bool) bool { diff --git a/pkg/util/errutil/errors_test.go b/pkg/util/errutil/errors_test.go index a36f6cb3a2f6a..6e8f5b3485598 100644 --- a/pkg/util/errutil/errors_test.go +++ b/pkg/util/errutil/errors_test.go @@ -16,10 +16,13 @@ package errutil import ( "context" - "github.com/stretchr/testify/require" + "errors" + "os" "reflect" "sync/atomic" "testing" + + "github.com/stretchr/testify/require" ) func mockReportError(_ context.Context, err error, depth int) {} @@ -181,6 +184,23 @@ func TestWrapf(t *testing.T) { } } +func TestWrapfCauseFirst(t *testing.T) { + cause := context.Canceled + err := WrapfCauseFirst(cause, "detail %d", 7) + require.Equal(t, "context canceled: detail 7", err.Error()) + require.ErrorIs(t, err, cause) + require.Nil(t, WrapfCauseFirst(nil, "ignored")) + require.EqualError(t, WrapfCauseFirst(cause, ""), cause.Error()) + first, second := errors.New("same"), errors.New("same") + require.NotErrorIs(t, WrapfCauseFirst(first, "detail"), second) + typed := &os.PathError{Op: "read", Path: "artifact", Err: first} + nested := Wrap(WrapfCauseFirst(typed, "detail"), "gateway") + var target *os.PathError + require.ErrorAs(t, nested, &target) + require.Same(t, typed, target) + require.ErrorIs(t, nested, first) +} + func Test_noopReportError(t *testing.T) { type args struct { in0 context.Context diff --git a/pkg/vm/engine/disttae/types.go b/pkg/vm/engine/disttae/types.go index b3538baf90278..2f9b83bfaf431 100644 --- a/pkg/vm/engine/disttae/types.go +++ b/pkg/vm/engine/disttae/types.go @@ -261,7 +261,7 @@ type Engine struct { ls lockservice.LockService qc qclient.QueryClient hakeeper logservice.CNHAKeeperClient - us udf.Service + us udf.Runtime cli client.TxnClient idGen IDGenerator tnID string diff --git a/pkg/vm/process/process2.go b/pkg/vm/process/process2.go index 99345d2666305..9c76210084671 100644 --- a/pkg/vm/process/process2.go +++ b/pkg/vm/process/process2.go @@ -56,7 +56,7 @@ func NewTopProcess( fileService fileservice.FileService, lockService lockservice.LockService, queryClient qclient.QueryClient, HAKeeper logservice.CNHAKeeperClient, - udfService udf.Service, + udfService udf.Runtime, autoIncrease *defines.AutoIncrCacheManager, taskService taskservice.TaskService) *Process { diff --git a/pkg/vm/process/process_codec.go b/pkg/vm/process/process_codec.go index ae0172b45c19e..cb91f2e1e8d87 100644 --- a/pkg/vm/process/process_codec.go +++ b/pkg/vm/process/process_codec.go @@ -207,7 +207,7 @@ func NewCodecService( partitionService partitionservice.PartitionService, queryClient qclient.QueryClient, hakeeper logservice.CNHAKeeperClient, - udfService udf.Service, + udfService udf.Runtime, engine engine.Engine, ) ProcessCodecService { mp, err := mpool.NewMPool("codec", 1<<40, mpool.NoFixed) @@ -234,7 +234,7 @@ type codecService struct { partitionService partitionservice.PartitionService queryClient qclient.QueryClient hakeeper logservice.CNHAKeeperClient - udfService udf.Service + udfService udf.Runtime mp *mpool.MPool engine engine.Engine } diff --git a/pkg/vm/process/types.go b/pkg/vm/process/types.go index 39f6b3f38391c..a01a916ab5ce9 100644 --- a/pkg/vm/process/types.go +++ b/pkg/vm/process/types.go @@ -471,7 +471,7 @@ type BaseProcess struct { prepareParamsOwned bool QueryClient qclient.QueryClient Hakeeper logservice.CNHAKeeperClient - UdfService udf.Service + UdfService udf.Runtime WaitPolicy lock.WaitPolicy messageBoard *message.MessageBoard executionResourceBudgetMu sync.Mutex diff --git a/proto/plan.proto b/proto/plan.proto index c3dc24ed624fc..db7a570b3bbbd 100644 --- a/proto/plan.proto +++ b/proto/plan.proto @@ -253,6 +253,8 @@ message Function { // overload while optimizers still distinguish it from an implicit cast. // Older CNs safely ignore this unknown field and execute the legacy overload. bool syntax_explicit_cast = 5; + // Typed routine metadata. Ordinary builtin Function values leave this nil. + RoutineCall routine_call = 6; } // PreparedNumericMetadata is sparse planner provenance for a numeric overload @@ -1709,6 +1711,12 @@ message Query { // execution so a committed concurrent CREATE INDEX can rebuild the plan; // without a definition change, it returns the original key-not-found error. repeated UnresolvedIndexHint unresolved_index_hints = 16; + + // Exact routine revisions captured while binding this statement. The + // expression tree carries the call-site implementation, while this bounded + // envelope lets prepared and ordinary plan-cache reuse validate the shared + // catalog namespace without walking or reinterpreting user source. + repeated RoutinePlanDependency routine_dependencies = 17; } message TransationControl { @@ -2379,3 +2387,89 @@ message UnresolvedIndexHint { ObjectRef table = 1; string index_name = 2; } + +// FunctionRef is the exact catalog identity carried by an executable plan. +// A zero revision is invalid for external routines; the planner validates the +// complete call before a fragment is dispatched. +message FunctionRef { + uint64 function_id = 1; + uint64 revision = 2; + uint64 namespace_version = 3; + // Function identity is tenant/database scoped. These fields prevent a + // plan fragment from being interpreted in a different catalog namespace. + uint64 account_id = 4; + uint64 database_id = 5; +} + +message SqlRoutineImplementation { + bytes definition_fingerprint = 1; + int32 semantic_definition_schema_version = 2; +} + +message PythonRoutineImplementation { + string handler = 1; + // Source is retained only so an old serialized demo plan can be identified + // and rejected. A current executable plan must carry the immutable artifact + // digest and resolve the artifact through the runtime artifact store. + string source = 2 [deprecated = true]; + string abi_contract = 3; + string adapter_version = 4; + string artifact_digest = 5; + string environment_digest = 6; + string sdk_version = 7; + int32 definition_schema_version = 8; + string mode = 9; + string null_policy = 10; + string definition_fingerprint = 11; +} + +// RoutineCall is the common typed call envelope for SQL and external +// language routines. Function.Args remains the normal expression argument +// list so existing expression traversal and CASE/selection ownership stay +// intact; this field carries only immutable routine identity and semantics. +message RoutineCall { + int32 contract_version = 1; + FunctionRef function_ref = 2; + string language = 3; + repeated Type argument_types = 4; + Type return_type = 5 [(gogoproto.nullable) = false]; + string volatility = 6; + string null_policy = 7; + oneof implementation { + SqlRoutineImplementation sql = 8; + PythonRoutineImplementation python = 9; + } + // Reserved from the current executable contract. Statement identity, + // session values, and group fences are created at execution time; keeping + // them in a prepared plan would allow stale state to cross executions. + map context = 10 [deprecated = true]; + // These fields are the common semantic contract. They must survive SQL + // lowering and expression/plan cloning; the optimizer may only move a + // routine call when the attached contract permits it. + string callsite_id = 11; + bool may_error = 12; + string security_mode = 13; + bool leakproof = 14; + // State fingerprint of the complete overload namespace at binding snapshot. + // Separate from the selected immutable FunctionRef; missing means no reuse. + string namespace_fingerprint = 15; +} + +// RoutinePlanDependency is the shared cache/prepared-plan validation envelope +// for a resolved routine closure. FunctionRef is the executable identity; +// the integrity fields prove that the implementation attached to the plan is +// the same immutable revision that the resolver admitted. +message RoutinePlanDependency { + FunctionRef function_ref = 1; + string language = 2; + int32 contract_version = 3; + string definition_fingerprint = 4; + string artifact_digest = 5; + string environment_digest = 6; + string volatility = 7; + string null_policy = 8; + bool may_error = 9; + string security_mode = 10; + bool leakproof = 11; + string namespace_fingerprint = 12; +} diff --git a/proto/query.proto b/proto/query.proto index 79dce4531e1ed..836e4c204a9a6 100644 --- a/proto/query.proto +++ b/proto/query.proto @@ -110,6 +110,9 @@ enum CmdMethod { MongoDBClientRetire = 39; // RefreshSessionAuth revalidates a cached backend against the current catalog. RefreshSessionAuth = 40; + // GetPythonUdfStatus returns the bounded, read-only Python runtime status of + // the addressed CN. It is consumed by the Operator for same-Pod workers. + GetPythonUdfStatus = 41; } // QueryRequest is the common query request. It contains the query @@ -255,6 +258,8 @@ message Request { MongoDBClientRetireRequest MongoDBClientRetireRequest = 41 [ (gogoproto.nullable) = false ]; // RefreshSessionAuthRequest reauthenticates a cached backend for a new login. RefreshSessionAuthRequest RefreshSessionAuthRequest = 42; + // GetPythonUdfStatusRequest asks this CN for its local Python runtime state. + GetPythonUdfStatusRequest GetPythonUdfStatusRequest = 43 [ (gogoproto.nullable) = false ]; } // ShowProcessListResponse is the response of command ShowProcessList. @@ -325,6 +330,38 @@ message Response { MongoDBClientRetireResponse MongoDBClientRetireResponse = 42 [ (gogoproto.nullable) = false ]; // RefreshSessionAuthResponse contains the current authentication string. RefreshSessionAuthResponse RefreshSessionAuthResponse = 43; + // GetPythonUdfStatus is a bounded summary of the CN-local Python contract. + GetPythonUdfStatusResponse GetPythonUdfStatus = 44 [ (gogoproto.nullable) = false ]; +} + +message GetPythonUdfStatusRequest { +} + +message GetPythonUdfStatusResponse { + string CNUUID = 1; + string Language = 2; + bool Enabled = 3; + bool AllowUnisolated = 4; + bool Ready = 5; + string ErrorClass = 6; + string Reason = 7; + int32 ProtocolVersion = 8; + string ABIContract = 9; + string AdapterVersion = 10; + string SDKVersion = 11; + int32 DefinitionSchemaVersion = 12; + int32 PlanContractVersion = 13; + string TypeDescriptorContract = 14; + string TimezoneDatabaseVersion = 15; + int32 WindowBatches = 16; + bool CumulativeAck = 17; + int64 MaxExecutionFrameBytes = 18; + int32 MaxHandlerProcesses = 19; + int32 MaxAccountHandlerProcesses = 20; + int32 MaxOwnerHandlerProcesses = 21; + uint64 LeaseEpoch = 22; + repeated string Modes = 23; + repeated string NullPolicies = 24; } // AlterAccountRequest is the "alter account restricted" query request. diff --git a/test/distributed/cases/dml/select/sp_table.result b/test/distributed/cases/dml/select/sp_table.result index 72e09c82198c4..5455bd26b4933 100644 --- a/test/distributed/cases/dml/select/sp_table.result +++ b/test/distributed/cases/dml/select/sp_table.result @@ -19,6 +19,7 @@ mo_database r mo_feature_limit r mo_feature_registry r mo_foreign_keys r +mo_function_revisions r mo_iceberg_catalogs r mo_iceberg_maintenance_jobs r mo_iceberg_orphan_files r diff --git a/test/distributed/cases/dml/show/database_statistics.result b/test/distributed/cases/dml/show/database_statistics.result index 8a44e732fac20..3022ffc09d8cf 100644 --- a/test/distributed/cases/dml/show/database_statistics.result +++ b/test/distributed/cases/dml/show/database_statistics.result @@ -9,7 +9,7 @@ show table_number from mysql; 6 show table_number from mo_catalog; ➤ Number of tables in mo_catalog[-5,64,0] 𝄀 -59 +61 show table_number from system; [unknown result because it is related to issue#23182] use mo_task; @@ -93,7 +93,7 @@ show column_number from mo_role_privs; 10 show column_number from mo_user_defined_function; ➤ Number of columns in mo_user_defined_function[-5,64,0] 𝄀 -19 +25 show column_number from mo_tables; ➤ Number of columns in mo_tables[-5,64,0] 𝄀 19 @@ -350,7 +350,7 @@ show table_number from mysql; 6 show table_number from mo_catalog; ➤ Number of tables in mo_catalog[-5,64,0] 𝄀 -37 +38 show table_number from system_metrics; ➤ Number of tables in system_metrics[-5,64,0] 𝄀 11 @@ -430,7 +430,7 @@ show column_number from mo_role_privs; 10 show column_number from mo_user_defined_function; ➤ Number of columns in mo_user_defined_function[-5,64,0] 𝄀 -19 +25 show column_number from mo_tables; ➤ Number of columns in mo_tables[-5,64,0] 𝄀 19 diff --git a/test/distributed/cases/dml/show/show.result b/test/distributed/cases/dml/show/show.result index 36e8892e598d3..2e69146416996 100644 --- a/test/distributed/cases/dml/show/show.result +++ b/test/distributed/cases/dml/show/show.result @@ -269,6 +269,7 @@ mo_database 𝄀 mo_feature_limit 𝄀 mo_feature_registry 𝄀 mo_foreign_keys 𝄀 +mo_function_revisions 𝄀 mo_iceberg_catalogs 𝄀 mo_iceberg_maintenance_jobs 𝄀 mo_iceberg_orphan_files 𝄀 @@ -315,7 +316,7 @@ mo_view_dependencies 𝄀 mo_view_refresh show table_number from mo_catalog; ➤ Number of tables in mo_catalog[-5,64,0] 𝄀 -59 +61 show column_number from mo_database; ➤ Number of columns in mo_database[-5,64,0] 𝄀 9 diff --git a/test/distributed/cases/git4data/clone/clone_sys_db_table_to_new_db_table.result b/test/distributed/cases/git4data/clone/clone_sys_db_table_to_new_db_table.result index 6f02baf888448..0196e10e1669d 100644 --- a/test/distributed/cases/git4data/clone/clone_sys_db_table_to_new_db_table.result +++ b/test/distributed/cases/git4data/clone/clone_sys_db_table_to_new_db_table.result @@ -144,6 +144,7 @@ mo_database mo_feature_limit mo_feature_registry mo_foreign_keys +mo_function_revisions mo_iceberg_catalogs mo_iceberg_maintenance_jobs mo_iceberg_orphan_files @@ -214,6 +215,7 @@ mo_database mo_feature_limit mo_feature_registry mo_foreign_keys +mo_function_revisions mo_iceberg_catalogs mo_iceberg_maintenance_jobs mo_iceberg_orphan_files diff --git a/test/distributed/cases/git4data/clone/issue_27103_clone_external_table.result b/test/distributed/cases/git4data/clone/issue_27103_clone_external_table.result index 4e69c42722791..14e7e9fbc2fe2 100644 --- a/test/distributed/cases/git4data/clone/issue_27103_clone_external_table.result +++ b/test/distributed/cases/git4data/clone/issue_27103_clone_external_table.result @@ -29,7 +29,7 @@ fields terminated by ','; create function issue_27103_live_src.f_control() returns int language sql as 'select count(*) from issue_27103_live_src.control_t'; create function issue_27103_live_src.py_add(x int) returns int language python as -'return x + 1' handler 'py_add'; +'def py_add(ctx, x): return x + 1' handler 'py_add'; create function issue_27103_live_src.f_external() returns int language sql as 'select count(*) from issue_27103_live_src.ext_t'; create function issue_27103_live_src.f_transitive() returns int language sql as @@ -112,7 +112,7 @@ fields terminated by ','; create function issue_27103_snapshot_src.f_control() returns int language sql as 'select count(*) from issue_27103_snapshot_src.control_t'; create function issue_27103_snapshot_src.py_add(x int) returns int language python as -'return x + 1' handler 'py_add'; +'def py_add(ctx, x): return x + 1' handler 'py_add'; create function issue_27103_snapshot_src.f_external() returns int language sql as 'select count(*) from issue_27103_snapshot_src.ext_t'; create function issue_27103_snapshot_src.f_transitive() returns int language sql as diff --git a/test/distributed/cases/git4data/clone/issue_27103_clone_external_table.sql b/test/distributed/cases/git4data/clone/issue_27103_clone_external_table.sql index d4645ada92d90..a6bdc887a6d96 100644 --- a/test/distributed/cases/git4data/clone/issue_27103_clone_external_table.sql +++ b/test/distributed/cases/git4data/clone/issue_27103_clone_external_table.sql @@ -31,7 +31,7 @@ fields terminated by ','; create function issue_27103_live_src.f_control() returns int language sql as 'select count(*) from issue_27103_live_src.control_t'; create function issue_27103_live_src.py_add(x int) returns int language python as -'return x + 1' handler 'py_add'; +'def py_add(ctx, x): return x + 1' handler 'py_add'; create function issue_27103_live_src.f_external() returns int language sql as 'select count(*) from issue_27103_live_src.ext_t'; create function issue_27103_live_src.f_transitive() returns int language sql as @@ -84,7 +84,7 @@ fields terminated by ','; create function issue_27103_snapshot_src.f_control() returns int language sql as 'select count(*) from issue_27103_snapshot_src.control_t'; create function issue_27103_snapshot_src.py_add(x int) returns int language python as -'return x + 1' handler 'py_add'; +'def py_add(ctx, x): return x + 1' handler 'py_add'; create function issue_27103_snapshot_src.f_external() returns int language sql as 'select count(*) from issue_27103_snapshot_src.ext_t'; create function issue_27103_snapshot_src.f_transitive() returns int language sql as diff --git a/test/distributed/cases/metadata/information_schema.result b/test/distributed/cases/metadata/information_schema.result index 596d68a566859..9ed0b41bd8747 100644 --- a/test/distributed/cases/metadata/information_schema.result +++ b/test/distributed/cases/metadata/information_schema.result @@ -38,6 +38,7 @@ def mo_catalog mo_database BASE TABLE Tae def mo_catalog mo_feature_limit BASE TABLE Tae def mo_catalog mo_feature_registry BASE TABLE Tae def mo_catalog mo_foreign_keys BASE TABLE Tae +def mo_catalog mo_function_revisions BASE TABLE Tae def mo_catalog mo_iceberg_catalogs BASE TABLE Tae def mo_catalog mo_iceberg_maintenance_jobs BASE TABLE Tae def mo_catalog mo_iceberg_orphan_files BASE TABLE Tae diff --git a/test/distributed/cases/mo_cloud/mo_cloud.result b/test/distributed/cases/mo_cloud/mo_cloud.result index 0d523e8d4125f..47809b077b26c 100644 --- a/test/distributed/cases/mo_cloud/mo_cloud.result +++ b/test/distributed/cases/mo_cloud/mo_cloud.result @@ -810,6 +810,7 @@ mo_catalog ¦ mo_columns ¦ r ¦ - 𝄀 mo_catalog ¦ mo_configurations ¦ v ¦ accountadmin 𝄀 mo_catalog ¦ mo_database ¦ r ¦ - 𝄀 mo_catalog ¦ mo_foreign_keys ¦ r ¦ accountadmin 𝄀 +mo_catalog ¦ mo_function_revisions ¦ r ¦ accountadmin 𝄀 mo_catalog ¦ mo_iceberg_catalogs ¦ r ¦ accountadmin 𝄀 mo_catalog ¦ mo_iceberg_maintenance_jobs ¦ r ¦ accountadmin 𝄀 mo_catalog ¦ mo_iceberg_orphan_files ¦ r ¦ accountadmin 𝄀 diff --git a/test/distributed/cases/snapshot/cluster/restore_cluster_table.result b/test/distributed/cases/snapshot/cluster/restore_cluster_table.result index 05ce577ace6ad..a457338d12e6e 100644 --- a/test/distributed/cases/snapshot/cluster/restore_cluster_table.result +++ b/test/distributed/cases/snapshot/cluster/restore_cluster_table.result @@ -231,8 +231,8 @@ create function `addAB`(x int, y int) returns int language sql as '$1 + $2'; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db2 test_account 2025-11-24 15:27:40 2025-11-24 15:27:40 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db2 test_account 2025-11-24 15:27:40 2025-11-24 15:27:40 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop stage if exists my_ext_stage; create stage my_ext_stage URL='s3://load/files/'; drop stage if exists my_ext_stage1; @@ -421,6 +421,7 @@ mo_database mo_feature_limit mo_feature_registry mo_foreign_keys +mo_function_revisions mo_iceberg_catalogs mo_iceberg_maintenance_jobs mo_iceberg_orphan_files @@ -484,8 +485,8 @@ create function `add`(x int, y int) returns int language sql as '$1 + $2'; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -2 add 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db2 test_account 2025-11-24 15:27:40 2025-11-24 15:27:40 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +2 1 1 add 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db2 test_account 2025-11-24 15:27:40 2025-11-24 15:27:40 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop database test01; use test02; select * from v01; @@ -552,6 +553,7 @@ mo_database mo_feature_limit mo_feature_registry mo_foreign_keys +mo_function_revisions mo_iceberg_catalogs mo_iceberg_maintenance_jobs mo_iceberg_orphan_files @@ -612,8 +614,8 @@ stage_id stage_name url stage_credentials stage_status created_ti 1 my_ext_stage s3://load/files/ in_use 2025-11-24 15:27:40 2 my_ext_stage1 s3://load/files/ AWS_KEY_ID=1a2b3c,AWS_SECRET_KEY=4x5y6z in_use 2025-11-24 15:27:40 select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db2 test_account 2025-11-24 15:27:40 2025-11-24 15:27:40 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db2 test_account 2025-11-24 15:27:40 2025-11-24 15:27:40 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG select * from test01.sales; id sale_date amount 1 2018-12-25 100.00 diff --git a/test/distributed/cases/snapshot/cluster/restore_cluster_table.sql b/test/distributed/cases/snapshot/cluster/restore_cluster_table.sql index bf28a6b2db10d..a34e41ca34850 100644 --- a/test/distributed/cases/snapshot/cluster/restore_cluster_table.sql +++ b/test/distributed/cases/snapshot/cluster/restore_cluster_table.sql @@ -230,7 +230,7 @@ use udf_db2; create function `addAB`(x int, y int) returns int language sql as '$1 + $2'; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; drop stage if exists my_ext_stage; @@ -376,7 +376,7 @@ use udf_db2; create function `add`(x int, y int) returns int language sql as '$1 + $2'; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @session @@ -427,7 +427,7 @@ select * from mo_catalog.mo_stored_procedure; -- @session:id=2&user=acc02:test_account&password=111 -- @ignore:0,5 select * from mo_catalog.mo_stages; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @session diff --git a/test/distributed/cases/snapshot/cluster_level_snapshot_restore_cluster.result b/test/distributed/cases/snapshot/cluster_level_snapshot_restore_cluster.result index d52ecf13024ca..3cbc5e0e46b42 100644 --- a/test/distributed/cases/snapshot/cluster_level_snapshot_restore_cluster.result +++ b/test/distributed/cases/snapshot/cluster_level_snapshot_restore_cluster.result @@ -266,8 +266,8 @@ create function `addAB`(x int, y int) returns int language sql as '$1 + $2'; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db2 test_account 2025-11-24 15:26:50 2025-11-24 15:26:50 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db2 test_account 2025-11-24 15:26:50 2025-11-24 15:26:50 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop stage if exists my_ext_stage; create stage my_ext_stage URL='s3://load/files/'; drop stage if exists my_ext_stage1; @@ -456,6 +456,7 @@ mo_database mo_feature_limit mo_feature_registry mo_foreign_keys +mo_function_revisions mo_iceberg_catalogs mo_iceberg_maintenance_jobs mo_iceberg_orphan_files @@ -520,8 +521,8 @@ create function `add`(x int, y int) returns int language sql as '$1 + $2'; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -2 add 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db2 test_account 2025-11-24 15:26:50 2025-11-24 15:26:50 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +2 1 1 add 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db2 test_account 2025-11-24 15:26:50 2025-11-24 15:26:50 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop database test01; use test02; select * from v01; @@ -593,6 +594,7 @@ mo_database mo_feature_limit mo_feature_registry mo_foreign_keys +mo_function_revisions mo_iceberg_catalogs mo_iceberg_maintenance_jobs mo_iceberg_orphan_files @@ -661,8 +663,8 @@ stage_id stage_name url stage_credentials stage_status created_ti 1 my_ext_stage s3://load/files/ in_use 2025-11-24 15:26:50 2 my_ext_stage1 s3://load/files/ AWS_KEY_ID=1a2b3c,AWS_SECRET_KEY=4x5y6z in_use 2025-11-24 15:26:50 select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db2 test_account 2025-11-24 15:26:50 2025-11-24 15:26:50 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db2 test_account 2025-11-24 15:26:50 2025-11-24 15:26:50 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG use test02; select * from v01; id sale_date amount diff --git a/test/distributed/cases/snapshot/cluster_level_snapshot_restore_cluster.sql b/test/distributed/cases/snapshot/cluster_level_snapshot_restore_cluster.sql index 0e471507c3db9..1aa5f112e674c 100644 --- a/test/distributed/cases/snapshot/cluster_level_snapshot_restore_cluster.sql +++ b/test/distributed/cases/snapshot/cluster_level_snapshot_restore_cluster.sql @@ -245,7 +245,7 @@ use udf_db2; create function `addAB`(x int, y int) returns int language sql as '$1 + $2'; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; drop stage if exists my_ext_stage; @@ -395,7 +395,7 @@ use udf_db2; create function `add`(x int, y int) returns int language sql as '$1 + $2'; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @session @@ -447,7 +447,7 @@ select * from mo_catalog.mo_stored_procedure; -- @session:id=2&user=acc02:test_account&password=111 -- @ignore:0,5 select * from mo_catalog.mo_stages; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @session diff --git a/test/distributed/cases/snapshot/cluster_level_snapshot_restore_system_table_to_nonsys.result b/test/distributed/cases/snapshot/cluster_level_snapshot_restore_system_table_to_nonsys.result index 9400c311f646e..9d09f869d7b46 100644 --- a/test/distributed/cases/snapshot/cluster_level_snapshot_restore_system_table_to_nonsys.result +++ b/test/distributed/cases/snapshot/cluster_level_snapshot_restore_system_table_to_nonsys.result @@ -54,23 +54,23 @@ udf_dsp03 2025-07-19 05:49:43.416853 cluster udf_dsp02 2025-07-19 05:49:43.394563 cluster udf_dsp01 2025-07-19 05:49:43.382694 cluster select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -2 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] varchar $1 + $2 sql udf_db test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -3 subab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 - $2 sql udf_db2 test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +2 1 1 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] 0 varchar $1 + $2 sql udf_db test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +3 1 1 subab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 - $2 sql udf_db2 test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop function subab(x int,y int); drop function udf_db.concatenate(str1 varchar(255), str2 varchar(255)); restore account acc01{snapshot="udf_dsp03"}; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -2 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] varchar $1 + $2 sql udf_db test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -3 subab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 - $2 sql udf_db2 test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +2 1 1 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] 0 varchar $1 + $2 sql udf_db test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +3 1 1 subab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 - $2 sql udf_db2 test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG restore account acc01{snapshot="udf_dsp02"}; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -2 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] varchar $1 + $2 sql udf_db test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +2 1 1 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] 0 varchar $1 + $2 sql udf_db test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop database udf_db; drop snapshot udf_dsp01; drop snapshot udf_dsp02; @@ -82,17 +82,17 @@ create function `addab`(x int, y int) returns int language sql as '$1 + $2'; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -10001 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db2 test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +10001 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db2 test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop snapshot if exists udf_sp04; create snapshot udf_sp04 for cluster; drop database udf_db2; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode restore account acc01{snapshot="udf_sp04"}; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -10001 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db2 test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +10001 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db2 test_account 2025-07-19 05:49:43 2025-07-19 05:49:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop database udf_db2; drop snapshot udf_sp04; drop database if exists procedure_test; diff --git a/test/distributed/cases/snapshot/cluster_level_snapshot_restore_system_table_to_nonsys.sql b/test/distributed/cases/snapshot/cluster_level_snapshot_restore_system_table_to_nonsys.sql index dc3faa13dd891..b786725664269 100644 --- a/test/distributed/cases/snapshot/cluster_level_snapshot_restore_system_table_to_nonsys.sql +++ b/test/distributed/cases/snapshot/cluster_level_snapshot_restore_system_table_to_nonsys.sql @@ -52,7 +52,7 @@ create snapshot udf_dsp03 for cluster; show snapshots; -- @session:id=1&user=acc01:test_account&password=111 --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; drop function subab(x int,y int); drop function udf_db.concatenate(str1 varchar(255), str2 varchar(255)); @@ -61,14 +61,14 @@ drop function udf_db.concatenate(str1 varchar(255), str2 varchar(255)); restore account acc01{snapshot="udf_dsp03"}; -- @session:id=1&user=acc01:test_account&password=111 --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @session restore account acc01{snapshot="udf_dsp02"}; -- @session:id=1&user=acc01:test_account&password=111 --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @session @@ -90,7 +90,7 @@ use udf_db2; create function `addab`(x int, y int) returns int language sql as '$1 + $2'; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @session @@ -99,14 +99,14 @@ create snapshot udf_sp04 for cluster; -- @session:id=1&user=acc01:test_account&password=111 drop database udf_db2; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @session restore account acc01{snapshot="udf_sp04"}; -- @session:id=1&user=acc01:test_account&password=111 --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; drop database udf_db2; -- @session diff --git a/test/distributed/cases/snapshot/cluster_level_snapshot_restore_system_table_to_sys_account.result b/test/distributed/cases/snapshot/cluster_level_snapshot_restore_system_table_to_sys_account.result index b45565cde0830..c6f28e62c6c28 100644 --- a/test/distributed/cases/snapshot/cluster_level_snapshot_restore_system_table_to_sys_account.result +++ b/test/distributed/cases/snapshot/cluster_level_snapshot_restore_system_table_to_sys_account.result @@ -52,18 +52,18 @@ udf_dsp03 2025-07-19 05:49:49.217379 cluster udf_dsp02 2025-07-19 05:49:49.192607 cluster udf_dsp01 2025-07-19 05:49:49.180259 cluster select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1250000 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -1250001 concatenate 0 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] varchar $1 + $2 sql udf_db dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -1250002 subab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 - $2 sql udf_db2 dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1250000 1 1 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +1250001 1 1 concatenate 0 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] 0 varchar $1 + $2 sql udf_db dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +1250002 1 1 subab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 - $2 sql udf_db2 dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop function subab(x int,y int); drop function udf_db.concatenate(str1 varchar(255), str2 varchar(255)); restore account sys{snapshot="udf_dsp03"}; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1250000 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -1250001 concatenate 0 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] varchar $1 + $2 sql udf_db dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -1250002 subab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 - $2 sql udf_db2 dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1250000 1 1 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +1250001 1 1 concatenate 0 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] 0 varchar $1 + $2 sql udf_db dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +1250002 1 1 subab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 - $2 sql udf_db2 dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG show snapshots; SNAPSHOT_NAME TIMESTAMP SNAPSHOT_LEVEL ACCOUNT_NAME DATABASE_NAME TABLE_NAME udf_dsp03 2025-07-19 05:49:49.217379 cluster @@ -71,9 +71,9 @@ udf_dsp02 2025-07-19 05:49:49.192607 cluster udf_dsp01 2025-07-19 05:49:49.180259 cluster restore account sys{snapshot="udf_dsp02"}; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1250000 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -1250001 concatenate 0 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] varchar $1 + $2 sql udf_db dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1250000 1 1 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +1250001 1 1 concatenate 0 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] 0 varchar $1 + $2 sql udf_db dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG show snapshots; SNAPSHOT_NAME TIMESTAMP SNAPSHOT_LEVEL ACCOUNT_NAME DATABASE_NAME TABLE_NAME udf_dsp03 2025-07-19 05:49:49.217379 cluster @@ -90,17 +90,17 @@ create function `addab`(x int, y int) returns int language sql as '$1 + $2'; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1260000 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db2 dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1260000 1 1 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db2 dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop snapshot if exists udf_sp04; create snapshot udf_sp04 for cluster; drop database udf_db2; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode restore account sys{snapshot="udf_sp04"}; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1260000 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db2 dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1260000 1 1 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db2 dump 2025-07-19 05:49:49 2025-07-19 05:49:49 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop database udf_db2; drop snapshot udf_sp04; drop database if exists procedure_test; diff --git a/test/distributed/cases/snapshot/cluster_level_snapshot_restore_system_table_to_sys_account.sql b/test/distributed/cases/snapshot/cluster_level_snapshot_restore_system_table_to_sys_account.sql index 102958a93ed79..09e35f428202a 100644 --- a/test/distributed/cases/snapshot/cluster_level_snapshot_restore_system_table_to_sys_account.sql +++ b/test/distributed/cases/snapshot/cluster_level_snapshot_restore_system_table_to_sys_account.sql @@ -43,20 +43,20 @@ create snapshot udf_dsp03 for cluster; -- @ignore:0,1 show snapshots; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; drop function subab(x int,y int); drop function udf_db.concatenate(str1 varchar(255), str2 varchar(255)); restore account sys{snapshot="udf_dsp03"}; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @ignore:0,1 show snapshots; restore account sys{snapshot="udf_dsp02"}; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @ignore:0,1 show snapshots; @@ -76,7 +76,7 @@ use udf_db2; create function `addab`(x int, y int) returns int language sql as '$1 + $2'; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; drop snapshot if exists udf_sp04; @@ -86,7 +86,7 @@ drop database udf_db2; select * from mo_catalog.mo_user_defined_function; restore account sys{snapshot="udf_sp04"}; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; drop database udf_db2; drop snapshot udf_sp04; diff --git a/test/distributed/cases/snapshot/nonsys_restore_system_table_to_nonsys_account.result b/test/distributed/cases/snapshot/nonsys_restore_system_table_to_nonsys_account.result index 90421a7e5c04e..09aa8d9cee4e1 100644 --- a/test/distributed/cases/snapshot/nonsys_restore_system_table_to_nonsys_account.result +++ b/test/distributed/cases/snapshot/nonsys_restore_system_table_to_nonsys_account.result @@ -54,18 +54,18 @@ udf_dsp03 2025-07-19 05:50:25.393332 account acc01 udf_dsp02 2025-07-19 05:50:25.371637 account acc01 udf_dsp01 2025-07-19 05:50:25.354111 account acc01 select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -2 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] varchar $1 + $2 sql udf_db test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -3 subab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 - $2 sql udf_db2 test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +2 1 1 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] 0 varchar $1 + $2 sql udf_db test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +3 1 1 subab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 - $2 sql udf_db2 test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop function subab(x int,y int); drop function udf_db.concatenate(str1 varchar(255), str2 varchar(255)); restore account acc01{snapshot="udf_dsp03"}; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -2 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] varchar $1 + $2 sql udf_db test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -3 subab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 - $2 sql udf_db2 test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +2 1 1 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] 0 varchar $1 + $2 sql udf_db test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +3 1 1 subab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 - $2 sql udf_db2 test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG show snapshots; SNAPSHOT_NAME TIMESTAMP SNAPSHOT_LEVEL ACCOUNT_NAME DATABASE_NAME TABLE_NAME udf_dsp03 2025-07-19 05:50:25.393332 account acc01 @@ -73,9 +73,9 @@ udf_dsp02 2025-07-19 05:50:25.371637 account acc01 udf_dsp01 2025-07-19 05:50:25.354111 account acc01 restore account acc01{snapshot="udf_dsp02"}; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -2 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] varchar $1 + $2 sql udf_db test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +2 1 1 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] 0 varchar $1 + $2 sql udf_db test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG show snapshots; SNAPSHOT_NAME TIMESTAMP SNAPSHOT_LEVEL ACCOUNT_NAME DATABASE_NAME TABLE_NAME udf_dsp03 2025-07-19 05:50:25.393332 account acc01 @@ -92,17 +92,17 @@ create function `addAB`(x int, y int) returns int language sql as '$1 + $2'; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -10001 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db2 test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +10001 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db2 test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop snapshot if exists udf_sp04; create snapshot udf_sp04 for account acc01; drop database udf_db2; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode restore account acc01{snapshot="udf_sp04"}; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -10001 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db2 test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +10001 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db2 test_account 2025-07-19 05:50:25 2025-07-19 05:50:25 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop database udf_db2; drop snapshot udf_sp04; drop database if exists procedure_test; diff --git a/test/distributed/cases/snapshot/nonsys_restore_system_table_to_nonsys_account.sql b/test/distributed/cases/snapshot/nonsys_restore_system_table_to_nonsys_account.sql index 8e04ccaf9653c..307ea3c26803c 100644 --- a/test/distributed/cases/snapshot/nonsys_restore_system_table_to_nonsys_account.sql +++ b/test/distributed/cases/snapshot/nonsys_restore_system_table_to_nonsys_account.sql @@ -46,20 +46,20 @@ create snapshot udf_dsp03 for account acc01; -- @ignore:1 show snapshots; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; drop function subab(x int,y int); drop function udf_db.concatenate(str1 varchar(255), str2 varchar(255)); restore account acc01{snapshot="udf_dsp03"}; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @ignore:1 show snapshots; restore account acc01{snapshot="udf_dsp02"}; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @ignore:1 show snapshots; @@ -79,7 +79,7 @@ use udf_db2; create function `addAB`(x int, y int) returns int language sql as '$1 + $2'; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; drop snapshot if exists udf_sp04; @@ -89,7 +89,7 @@ drop database udf_db2; select * from mo_catalog.mo_user_defined_function; restore account acc01{snapshot="udf_sp04"}; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; drop database udf_db2; drop snapshot udf_sp04; diff --git a/test/distributed/cases/snapshot/sys_restore_system_table_to_newnonsys_account.result b/test/distributed/cases/snapshot/sys_restore_system_table_to_newnonsys_account.result index 938b13d74d6a0..9a03d829a5cbe 100644 --- a/test/distributed/cases/snapshot/sys_restore_system_table_to_newnonsys_account.result +++ b/test/distributed/cases/snapshot/sys_restore_system_table_to_newnonsys_account.result @@ -56,23 +56,23 @@ udf_dsp03 2025-07-19 05:52:33.805599 account acc01 udf_dsp02 2025-07-19 05:52:33.782182 account acc01 udf_dsp01 2025-07-19 05:52:33.77066 account acc01 select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db test_account 2025-07-19 05:52:33 2025-07-19 05:52:33 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -2 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] varchar $1 + $2 sql udf_db test_account 2025-07-19 05:52:33 2025-07-19 05:52:33 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -3 subab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 - $2 sql udf_db2 test_account 2025-07-19 05:52:33 2025-07-19 05:52:33 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db test_account 2025-07-19 05:52:33 2025-07-19 05:52:33 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +2 1 1 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] 0 varchar $1 + $2 sql udf_db test_account 2025-07-19 05:52:33 2025-07-19 05:52:33 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +3 1 1 subab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 - $2 sql udf_db2 test_account 2025-07-19 05:52:33 2025-07-19 05:52:33 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop function subab(x int,y int); drop function udf_db.concatenate(str1 varchar(255), str2 varchar(255)); restore account acc01{snapshot="udf_dsp03"} to account acc02; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db test_account 2025-07-19 05:52:33 2025-07-19 05:52:33 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -2 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] varchar $1 + $2 sql udf_db test_account 2025-07-19 05:52:33 2025-07-19 05:52:33 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -3 subab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 - $2 sql udf_db2 test_account 2025-07-19 05:52:33 2025-07-19 05:52:33 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db test_account 2025-07-19 05:52:33 2025-07-19 05:52:33 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +2 1 1 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] 0 varchar $1 + $2 sql udf_db test_account 2025-07-19 05:52:33 2025-07-19 05:52:33 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +3 1 1 subab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 - $2 sql udf_db2 test_account 2025-07-19 05:52:33 2025-07-19 05:52:33 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG restore account acc01{snapshot="udf_dsp02"} to account acc02; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db test_account 2025-07-19 05:52:33 2025-07-19 05:52:33 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -2 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] varchar $1 + $2 sql udf_db test_account 2025-07-19 05:52:33 2025-07-19 05:52:33 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db test_account 2025-07-19 05:52:33 2025-07-19 05:52:33 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +2 1 1 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] 0 varchar $1 + $2 sql udf_db test_account 2025-07-19 05:52:33 2025-07-19 05:52:33 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop database udf_db; drop snapshot udf_dsp01; drop snapshot udf_dsp02; @@ -86,17 +86,17 @@ create function `addAB`(x int, y int) returns int language sql as '$1 + $2'; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -4 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db2 test_account 2025-07-19 05:52:34 2025-07-19 05:52:34 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +4 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db2 test_account 2025-07-19 05:52:34 2025-07-19 05:52:34 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop snapshot if exists udf_sp04; create snapshot udf_sp04 for account acc01; drop database udf_db2; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode restore account acc01{snapshot="udf_sp04"} to account acc02; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -4 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db2 test_account 2025-07-19 05:52:34 2025-07-19 05:52:34 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +4 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db2 test_account 2025-07-19 05:52:34 2025-07-19 05:52:34 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop database udf_db2; drop snapshot udf_sp04; drop database if exists procedure_test; diff --git a/test/distributed/cases/snapshot/sys_restore_system_table_to_newnonsys_account.sql b/test/distributed/cases/snapshot/sys_restore_system_table_to_newnonsys_account.sql index 6a92ed8abd7a9..3f0f65d37a318 100644 --- a/test/distributed/cases/snapshot/sys_restore_system_table_to_newnonsys_account.sql +++ b/test/distributed/cases/snapshot/sys_restore_system_table_to_newnonsys_account.sql @@ -54,7 +54,7 @@ create snapshot udf_dsp03 for account acc01; show snapshots; -- @session:id=1&user=acc01:test_account&password=111 --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; drop function subab(x int,y int); drop function udf_db.concatenate(str1 varchar(255), str2 varchar(255)); @@ -63,13 +63,13 @@ drop function udf_db.concatenate(str1 varchar(255), str2 varchar(255)); restore account acc01{snapshot="udf_dsp03"} to account acc02; -- @session:id=2&user=acc02:test_account&password=111 --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @session restore account acc01{snapshot="udf_dsp02"} to account acc02; -- @session:id=2&user=acc02:test_account&password=111 --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; drop database udf_db; -- @session @@ -94,7 +94,7 @@ use udf_db2; create function `addAB`(x int, y int) returns int language sql as '$1 + $2'; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @session @@ -109,7 +109,7 @@ select * from mo_catalog.mo_user_defined_function; restore account acc01{snapshot="udf_sp04"} to account acc02; -- @session:id=2&user=acc02:test_account&password=111 --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; drop database udf_db2; -- @session diff --git a/test/distributed/cases/snapshot/sys_restore_system_table_to_nonsys_account.result b/test/distributed/cases/snapshot/sys_restore_system_table_to_nonsys_account.result index 8109f9316452a..542ab75a09ff4 100644 --- a/test/distributed/cases/snapshot/sys_restore_system_table_to_nonsys_account.result +++ b/test/distributed/cases/snapshot/sys_restore_system_table_to_nonsys_account.result @@ -54,23 +54,23 @@ udf_dsp03 2025-07-19 05:52:41.738562 account acc01 udf_dsp02 2025-07-19 05:52:41.609162 account acc01 udf_dsp01 2025-07-19 05:52:41.560453 account acc01 select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db test_account 2025-07-19 05:52:41 2025-07-19 05:52:41 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -2 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] varchar $1 + $2 sql udf_db test_account 2025-07-19 05:52:41 2025-07-19 05:52:41 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -3 subab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 - $2 sql udf_db2 test_account 2025-07-19 05:52:41 2025-07-19 05:52:41 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db test_account 2025-07-19 05:52:41 2025-07-19 05:52:41 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +2 1 1 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] 0 varchar $1 + $2 sql udf_db test_account 2025-07-19 05:52:41 2025-07-19 05:52:41 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +3 1 1 subab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 - $2 sql udf_db2 test_account 2025-07-19 05:52:41 2025-07-19 05:52:41 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop function subab(x int,y int); drop function udf_db.concatenate(str1 varchar(255), str2 varchar(255)); restore account acc01{snapshot="udf_dsp03"}; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db test_account 2025-07-19 05:52:41 2025-07-19 05:52:41 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -2 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] varchar $1 + $2 sql udf_db test_account 2025-07-19 05:52:41 2025-07-19 05:52:41 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -3 subab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 - $2 sql udf_db2 test_account 2025-07-19 05:52:41 2025-07-19 05:52:41 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db test_account 2025-07-19 05:52:41 2025-07-19 05:52:41 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +2 1 1 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] 0 varchar $1 + $2 sql udf_db test_account 2025-07-19 05:52:41 2025-07-19 05:52:41 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +3 1 1 subab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 - $2 sql udf_db2 test_account 2025-07-19 05:52:41 2025-07-19 05:52:41 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG restore account acc01{snapshot="udf_dsp02"}; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db test_account 2025-07-19 05:52:41 2025-07-19 05:52:41 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -2 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] varchar $1 + $2 sql udf_db test_account 2025-07-19 05:52:41 2025-07-19 05:52:41 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db test_account 2025-07-19 05:52:41 2025-07-19 05:52:41 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +2 1 1 concatenate 2 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] 0 varchar $1 + $2 sql udf_db test_account 2025-07-19 05:52:41 2025-07-19 05:52:41 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop database udf_db; drop snapshot udf_dsp01; drop snapshot udf_dsp02; @@ -82,17 +82,17 @@ create function `addab`(x int, y int) returns int language sql as '$1 + $2'; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -10001 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db2 test_account 2025-07-19 05:52:43 2025-07-19 05:52:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +10001 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db2 test_account 2025-07-19 05:52:43 2025-07-19 05:52:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop snapshot if exists udf_sp04; create snapshot udf_sp04 for account acc01; drop database udf_db2; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode restore account acc01{snapshot="udf_sp04"}; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -10001 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db2 test_account 2025-07-19 05:52:43 2025-07-19 05:52:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +10001 1 1 addab 2 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db2 test_account 2025-07-19 05:52:43 2025-07-19 05:52:43 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop database udf_db2; drop snapshot udf_sp04; drop database if exists procedure_test; diff --git a/test/distributed/cases/snapshot/sys_restore_system_table_to_nonsys_account.sql b/test/distributed/cases/snapshot/sys_restore_system_table_to_nonsys_account.sql index 8d7e630fe7468..7d085efd06d6b 100644 --- a/test/distributed/cases/snapshot/sys_restore_system_table_to_nonsys_account.sql +++ b/test/distributed/cases/snapshot/sys_restore_system_table_to_nonsys_account.sql @@ -52,7 +52,7 @@ create snapshot udf_dsp03 for account acc01; show snapshots; -- @session:id=1&user=acc01:test_account&password=111 --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; drop function subab(x int,y int); drop function udf_db.concatenate(str1 varchar(255), str2 varchar(255)); @@ -61,14 +61,14 @@ drop function udf_db.concatenate(str1 varchar(255), str2 varchar(255)); restore account acc01{snapshot="udf_dsp03"}; -- @session:id=1&user=acc01:test_account&password=111 --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @session restore account acc01{snapshot="udf_dsp02"}; -- @session:id=1&user=acc01:test_account&password=111 --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @session @@ -90,7 +90,7 @@ use udf_db2; create function `addab`(x int, y int) returns int language sql as '$1 + $2'; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @session @@ -99,14 +99,14 @@ create snapshot udf_sp04 for account acc01; -- @session:id=1&user=acc01:test_account&password=111 drop database udf_db2; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @session restore account acc01{snapshot="udf_sp04"}; -- @session:id=1&user=acc01:test_account&password=111 --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; drop database udf_db2; -- @session diff --git a/test/distributed/cases/snapshot/sys_restore_system_table_to_sys_account.result b/test/distributed/cases/snapshot/sys_restore_system_table_to_sys_account.result index ff0f04f4581d5..361e8f6a17e88 100644 --- a/test/distributed/cases/snapshot/sys_restore_system_table_to_sys_account.result +++ b/test/distributed/cases/snapshot/sys_restore_system_table_to_sys_account.result @@ -52,18 +52,18 @@ udf_dsp03 2025-07-19 05:52:48.557367 account sys udf_dsp02 2025-07-19 05:52:48.529274 account sys udf_dsp01 2025-07-19 05:52:48.516842 account sys select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1890000 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -1890001 concatenate 0 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] varchar $1 + $2 sql udf_db dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -1890002 subab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 - $2 sql udf_db2 dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1890000 1 1 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +1890001 1 1 concatenate 0 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] 0 varchar $1 + $2 sql udf_db dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +1890002 1 1 subab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 - $2 sql udf_db2 dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop function subab(x int,y int); drop function udf_db.concatenate(str1 varchar(255), str2 varchar(255)); restore account sys{snapshot="udf_dsp03"}; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1890000 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -1890001 concatenate 0 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] varchar $1 + $2 sql udf_db dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -1890002 subab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 - $2 sql udf_db2 dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1890000 1 1 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +1890001 1 1 concatenate 0 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] 0 varchar $1 + $2 sql udf_db dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +1890002 1 1 subab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 - $2 sql udf_db2 dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG show snapshots; SNAPSHOT_NAME TIMESTAMP SNAPSHOT_LEVEL ACCOUNT_NAME DATABASE_NAME TABLE_NAME udf_dsp03 2025-07-19 05:52:48.557367 account sys @@ -71,9 +71,9 @@ udf_dsp02 2025-07-19 05:52:48.529274 account sys udf_dsp01 2025-07-19 05:52:48.516842 account sys restore account sys{snapshot="udf_dsp02"}; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1890000 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG -1890001 concatenate 0 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] varchar $1 + $2 sql udf_db dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1890000 1 1 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +1890001 1 1 concatenate 0 [{"name": "str1", "type": "varchar"}, {"name": "str2", "type": "varchar"}] ["varchar", "varchar"] 0 varchar $1 + $2 sql udf_db dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG show snapshots; SNAPSHOT_NAME TIMESTAMP SNAPSHOT_LEVEL ACCOUNT_NAME DATABASE_NAME TABLE_NAME udf_dsp03 2025-07-19 05:52:48.557367 account sys @@ -90,17 +90,17 @@ create function `addab`(x int, y int) returns int language sql as '$1 + $2'; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1900000 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db2 dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1900000 1 1 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db2 dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop snapshot if exists udf_sp04; create snapshot udf_sp04 for account; drop database udf_db2; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode restore account sys{snapshot="udf_sp04"}; select * from mo_catalog.mo_user_defined_function; -function_id name owner args arg_types rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode -1900000 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] int $1 + $2 sql udf_db2 dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG +function_id active_revision namespace_version name owner args arg_types canonical_input_descriptor return_descriptor signature_key_schema_version signature_fingerprint rettype body language db definer modified_time created_time type security_type comment character_set_client collation_connection database_collation sql_mode +1900000 1 1 addab 0 [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}] ["int", "int"] 0 int $1 + $2 sql udf_db2 dump 2025-07-19 05:52:48 2025-07-19 05:52:48 FUNCTION DEFINER utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ENABLE_BOOL_SUMAVG drop database udf_db2; drop snapshot udf_sp04; drop database if exists procedure_test; diff --git a/test/distributed/cases/snapshot/sys_restore_system_table_to_sys_account.sql b/test/distributed/cases/snapshot/sys_restore_system_table_to_sys_account.sql index 78587e4498806..e9eacb3058ba3 100644 --- a/test/distributed/cases/snapshot/sys_restore_system_table_to_sys_account.sql +++ b/test/distributed/cases/snapshot/sys_restore_system_table_to_sys_account.sql @@ -43,20 +43,20 @@ create snapshot udf_dsp03 for account; -- @ignore:0,1 show snapshots; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; drop function subab(x int,y int); drop function udf_db.concatenate(str1 varchar(255), str2 varchar(255)); restore account sys{snapshot="udf_dsp03"}; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @ignore:0,1 show snapshots; restore account sys{snapshot="udf_dsp02"}; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; -- @ignore:0,1 show snapshots; @@ -76,7 +76,7 @@ use udf_db2; create function `addab`(x int, y int) returns int language sql as '$1 + $2'; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; drop snapshot if exists udf_sp04; @@ -86,7 +86,7 @@ drop database udf_db2; select * from mo_catalog.mo_user_defined_function; restore account sys{snapshot="udf_sp04"}; --- @ignore:0,10,11 +-- @ignore:0,16,17 select * from mo_catalog.mo_user_defined_function; drop database udf_db2; drop snapshot udf_sp04; diff --git a/test/distributed/cases/tenant/privilege/create_user_default_role.result b/test/distributed/cases/tenant/privilege/create_user_default_role.result index 74f2e50aa285c..71daf963301cb 100644 --- a/test/distributed/cases/tenant/privilege/create_user_default_role.result +++ b/test/distributed/cases/tenant/privilege/create_user_default_role.result @@ -37,6 +37,7 @@ mo_database mo_feature_limit mo_feature_registry mo_foreign_keys +mo_function_revisions mo_iceberg_catalogs mo_iceberg_maintenance_jobs mo_iceberg_orphan_files diff --git a/test/distributed/cases/udf/overload_namespace.result b/test/distributed/cases/udf/overload_namespace.result new file mode 100644 index 0000000000000..ff683f260eaef --- /dev/null +++ b/test/distributed/cases/udf/overload_namespace.result @@ -0,0 +1,57 @@ +drop database if exists udf_sql_namespace_bvt; +create database udf_sql_namespace_bvt; +use udf_sql_namespace_bvt; +create table namespace_values(x smallint); +insert into namespace_values values (1),(2); +create function overload(x bigint) returns bigint language sql as '$1 + 100'; +select overload(x) as result from namespace_values order by x; +➤ result[-5,64,0] 𝄀 +101 𝄀 +102 +prepare namespace_plan from 'select overload(x) as result from namespace_values order by x'; +execute namespace_plan; +➤ result[-5,64,0] 𝄀 +101 𝄀 +102 +use udf_sql_namespace_bvt; +create function overload(x smallint) returns bigint language sql as '$1 + 200'; +execute namespace_plan; +➤ result[-5,64,0] 𝄀 +201 𝄀 +202 +select overload(x) as result from namespace_values order by x; +➤ result[-5,64,0] 𝄀 +201 𝄀 +202 +use udf_sql_namespace_bvt; +create or replace function overload(x smallint) returns bigint language sql as '$1 + 300'; +execute namespace_plan; +➤ result[-5,64,0] 𝄀 +301 𝄀 +302 +select overload(x) as result from namespace_values order by x; +➤ result[-5,64,0] 𝄀 +301 𝄀 +302 +use udf_sql_namespace_bvt; +drop function overload(smallint); +execute namespace_plan; +➤ result[-5,64,0] 𝄀 +101 𝄀 +102 +select overload(x) as result from namespace_values order by x; +➤ result[-5,64,0] 𝄀 +101 𝄀 +102 +use udf_sql_namespace_bvt; +create function overload(x smallint) returns bigint language sql as '$1 + 400'; +execute namespace_plan; +➤ result[-5,64,0] 𝄀 +401 𝄀 +402 +select overload(x) as result from namespace_values order by x; +➤ result[-5,64,0] 𝄀 +401 𝄀 +402 +deallocate prepare namespace_plan; +drop database udf_sql_namespace_bvt; diff --git a/test/distributed/cases/udf/overload_namespace.sql b/test/distributed/cases/udf/overload_namespace.sql new file mode 100644 index 0000000000000..fb6f89938b7b5 --- /dev/null +++ b/test/distributed/cases/udf/overload_namespace.sql @@ -0,0 +1,35 @@ +drop database if exists udf_sql_namespace_bvt; +create database udf_sql_namespace_bvt; +use udf_sql_namespace_bvt; +create table namespace_values(x smallint); +insert into namespace_values values (1),(2); +create function overload(x bigint) returns bigint language sql as '$1 + 100'; +select overload(x) as result from namespace_values order by x; +prepare namespace_plan from 'select overload(x) as result from namespace_values order by x'; +execute namespace_plan; +-- @session:id=1 +use udf_sql_namespace_bvt; +create function overload(x smallint) returns bigint language sql as '$1 + 200'; +-- @session +execute namespace_plan; +select overload(x) as result from namespace_values order by x; +-- @session:id=1 +use udf_sql_namespace_bvt; +create or replace function overload(x smallint) returns bigint language sql as '$1 + 300'; +-- @session +execute namespace_plan; +select overload(x) as result from namespace_values order by x; +-- @session:id=1 +use udf_sql_namespace_bvt; +drop function overload(smallint); +-- @session +execute namespace_plan; +select overload(x) as result from namespace_values order by x; +-- @session:id=1 +use udf_sql_namespace_bvt; +create function overload(x smallint) returns bigint language sql as '$1 + 400'; +-- @session +execute namespace_plan; +select overload(x) as result from namespace_values order by x; +deallocate prepare namespace_plan; +drop database udf_sql_namespace_bvt; diff --git a/test/distributed/cases/udf_python/README.md b/test/distributed/cases/udf_python/README.md new file mode 100644 index 0000000000000..3a342a0113043 --- /dev/null +++ b/test/distributed/cases/udf_python/README.md @@ -0,0 +1,90 @@ +# Python UDF BVT cases + +Put SQL cases that require the Python UDF worker in this directory. Each case +needs a matching `.result` file generated by `mo-tester`. These cases are part +of the ordinary BVT suite and run with the other SQL cases. + +For a local launch BVT, install the locked worker dependency once and use the +normal BVT commands. `run_bvt.sh . launch` selects the explicit +worker-enabled manifest for this ordinary BVT entry point; starting +`etc/launch/launch.toml` directly leaves Python disabled. + +```bash +python3.12 -m venv /path/to/python-udf-test-venv +source /path/to/python-udf-test-venv/bin/activate +python3 -m pip install --only-binary=:all: -r pkg/udf/python/worker/requirements.txt +./optools/run_bvt.sh . launch +cd /path/to/mo-tester +./run.sh -n -g -o -p /path/to/matrixone/test/distributed/cases +``` + +The Go UDF package tests also start real Flight workers. Keep the same venv on +`PATH` when running them: installing PyArrow into another interpreter will not +satisfy `exec.LookPath("python3")`. The shared CI UT and coverage setup uses +Python 3.12 and the checked-out requirements file; this is a test environment +choice, not an exact-minor production compatibility rule. + +For fresh local data, the worker-enabled CN and its TN both use the same +`DISK-V2` FileService directories. Do not mix that configuration with an +existing `DISK` data directory. Container BVT also requires CN and worker +images with the same IANA database; both full-build and prebuilt runtime image +recipes install tzdata before the strict capability handshake. + +To create or refresh a result file after reviewing the expected output, keep +the normal worker-enabled launch running and use `mo-tester`'s `genrs` mode: + +```bash +SKIP_JSTFU=true ./optools/run_bvt.sh . launch +cd /path/to/mo-tester +./run.sh -p /path/to/matrixone/test/distributed/cases/udf_python/control_flow.sql -m genrs -g +``` + +The ordinary BVT launch starts one worker for the single CN. Compose BVT starts +one dedicated worker service per CN, built from the same Dockerfile and +dependency lock. These workers are unisolated adapters; a separate process or +container does not establish tenant isolation. Adding a SQL case here does +not require another CI workflow. + +The cases keep the data sets small and target contract boundaries: + +- `control_flow.sql` checks NULL delivery, handler-produced NULL, multiple + arguments, zero-argument scalar calls, CASE selection, and empty input. +- `numeric_boundaries.sql` checks signed and unsigned integer limits, floating + point values, booleans, decimal scale, and NULL. +- `value_types.sql` checks empty and Unicode text, binary values, canonical JSON, + UUID round trips, and NULL. +- `temporal_boundaries.sql` checks leap days, microseconds, TIME limits, SQL + zero-date values, and NULL. +- `relational_positions.sql` checks UDF evaluation in WHERE, JOIN ON and outer + join predicates, aggregate arguments, window ordering, and nested calls. +- `dml_positions.sql` checks UDF evaluation in INSERT values, UPDATE + assignments, and DELETE predicates while preserving SQL NULL filtering. +- `dml_error_paths.sql` checks that handler failures abort UPDATE, INSERT + SELECT, and DELETE atomically without publishing partial changes. +- `revision_lifecycle.sql` checks create, immutable-revision replacement, + prepared-plan invalidation, drop, and recreate on the same SQL signature. +- `overload_namespace.sql` checks cross-session overload changes invalidate + prepared/cache plans and DROP distinguishes exact decimal scales. +- `snapshot_restore.sql` restores revision A into a different account after + replacing the source with revision B, checking exact catalog bytes, execution, + account-scoped artifact publication, a SQL UDF control and teardown. +- `vector_mode.sql` checks Arrow VECTOR handlers, zero-argument batch shape, + NULL policies, and handler validation during create and replace. +- `arrow_compute_arithmetic.sql` checks `pyarrow.compute` arithmetic, + conditional, fill-null, and validity kernels while preserving NULLs and + batch length. +- `arrow_compute_selection.sql` checks Arrow take, sort-indices, comparison, + physical cast kernels with indexed and NULL input, and rejects a shortened + vector result. +- `arrow_compute_strings.sql` checks UTF-8 uppercasing, case-sensitive + substring matching, repeated replacement, and code-point length for empty, + Unicode, and NULL values. + +The shape follows established correctness coverage from +[DuckDB's scalar UDF tests](https://github.com/duckdb/duckdb-go/blob/main/scalar_udf_test.go) +(NULLs, multiple rows, multiple arguments, and errors), and the added compute +cases use the common kernels documented by +[PyArrow's compute API](https://arrow.apache.org/docs/python/compute.html) +(arithmetic, validity, selection, cast, and UTF-8). The SQL cases adapt those +ideas to MatrixOne's Python Arrow boundary rather than copying another +project's implementation. diff --git a/test/distributed/cases/udf_python/arrow_compute_arithmetic.result b/test/distributed/cases/udf_python/arrow_compute_arithmetic.result new file mode 100644 index 0000000000000..69ee2d94e0b96 --- /dev/null +++ b/test/distributed/cases/udf_python/arrow_compute_arithmetic.result @@ -0,0 +1,51 @@ +drop database if exists udf_python_arrow_compute_arithmetic_bvt; +create database udf_python_arrow_compute_arithmetic_bvt; +use udf_python_arrow_compute_arithmetic_bvt; +create function python_bvt_pc_add (x int) returns int language python as 'python_bvt_pc_add = lambda ctx, values: __import__("pyarrow.compute", fromlist=["add"]).add(values, __import__("pyarrow").scalar(10, type=__import__("pyarrow").int32()))' handler 'python_bvt_pc_add' mode vector; +create function python_bvt_pc_multiply (x int, y int) returns int language python as 'python_bvt_pc_multiply = lambda ctx, left, right: __import__("pyarrow.compute", fromlist=["multiply"]).multiply(left, right)' handler 'python_bvt_pc_multiply' mode vector; +create function python_bvt_pc_if_else (flag bool, x int, y int) returns int language python as 'python_bvt_pc_if_else = lambda ctx, flag, left, right: __import__("pyarrow.compute", fromlist=["if_else"]).if_else(flag, left, right)' handler 'python_bvt_pc_if_else' mode vector; +create function python_bvt_pc_fill_null (x int) returns int language python as 'python_bvt_pc_fill_null = lambda ctx, values: __import__("pyarrow.compute", fromlist=["fill_null"]).fill_null(values, __import__("pyarrow").scalar(-7, type=__import__("pyarrow").int32()))' handler 'python_bvt_pc_fill_null' mode vector; +create function python_bvt_pc_is_null (x int) returns bool language python as 'python_bvt_pc_is_null = lambda ctx, values: __import__("pyarrow.compute", fromlist=["is_null"]).is_null(values)' handler 'python_bvt_pc_is_null' mode vector; +create function python_bvt_pc_float_add (x float) returns float language python as 'python_bvt_pc_float_add = lambda ctx, values: __import__("pyarrow.compute", fromlist=["add"]).add(values, __import__("pyarrow").scalar(0.5, type=__import__("pyarrow").float32()))' handler 'python_bvt_pc_float_add' mode vector; +create function python_bvt_pc_double_add (x double) returns double language python as 'python_bvt_pc_double_add = lambda ctx, values: __import__("pyarrow.compute", fromlist=["add"]).add(values, __import__("pyarrow").scalar(0.5, type=__import__("pyarrow").float64()))' handler 'python_bvt_pc_double_add' mode vector; +create table arithmetic_values (id int, flag bool, left_value int, right_value int); +insert into arithmetic_values values +(1, true, 1, 10), +(2, false, null, 20), +(3, null, 3, null), +(4, true, null, null); +select id, +python_bvt_pc_add(left_value) as added, +python_bvt_pc_multiply(left_value, right_value) as multiplied, +python_bvt_pc_if_else(flag, left_value, right_value) as selected, +python_bvt_pc_fill_null(left_value) as filled, +python_bvt_pc_is_null(left_value) as is_null +from arithmetic_values order by id; +➤ id[4,32,0] ¦ added[4,32,0] ¦ multiplied[4,32,0] ¦ selected[4,32,0] ¦ filled[4,32,0] ¦ is_null[-7,1,0] 𝄀 +1 ¦ 11 ¦ 10 ¦ 1 ¦ 1 ¦ 0 𝄀 +2 ¦ null ¦ null ¦ 20 ¦ -7 ¦ 1 𝄀 +3 ¦ 13 ¦ null ¦ null ¦ 3 ¦ 0 𝄀 +4 ¦ null ¦ null ¦ null ¦ -7 ¦ 1 +create table float_values (id int, float_value float, double_value double); +insert into float_values values +(1, -1.25, 1.0), +(2, null, -2.5), +(3, 3.5, null); +select id, +python_bvt_pc_float_add(float_value) as float_added, +python_bvt_pc_double_add(double_value) as double_added +from float_values order by id; +➤ id[4,32,0] ¦ float_added[7,23,31] ¦ double_added[8,53,31] 𝄀 +1 ¦ -0.75 ¦ 1.5 𝄀 +2 ¦ null ¦ -2.0 𝄀 +3 ¦ 4.0 ¦ null +drop function python_bvt_pc_add(int); +drop function python_bvt_pc_multiply(int, int); +drop function python_bvt_pc_if_else(bool, int, int); +drop function python_bvt_pc_fill_null(int); +drop function python_bvt_pc_is_null(int); +drop function python_bvt_pc_float_add(float); +drop function python_bvt_pc_double_add(double); +drop table float_values; +drop table arithmetic_values; +drop database udf_python_arrow_compute_arithmetic_bvt; diff --git a/test/distributed/cases/udf_python/arrow_compute_arithmetic.sql b/test/distributed/cases/udf_python/arrow_compute_arithmetic.sql new file mode 100644 index 0000000000000..65f164f789c3e --- /dev/null +++ b/test/distributed/cases/udf_python/arrow_compute_arithmetic.sql @@ -0,0 +1,51 @@ +-- Arrow compute arithmetic and validity kernels through the SQL UDF boundary. +drop database if exists udf_python_arrow_compute_arithmetic_bvt; +create database udf_python_arrow_compute_arithmetic_bvt; +use udf_python_arrow_compute_arithmetic_bvt; + +create function python_bvt_pc_add (x int) returns int language python as 'python_bvt_pc_add = lambda ctx, values: __import__("pyarrow.compute", fromlist=["add"]).add(values, __import__("pyarrow").scalar(10, type=__import__("pyarrow").int32()))' handler 'python_bvt_pc_add' mode vector; +create function python_bvt_pc_multiply (x int, y int) returns int language python as 'python_bvt_pc_multiply = lambda ctx, left, right: __import__("pyarrow.compute", fromlist=["multiply"]).multiply(left, right)' handler 'python_bvt_pc_multiply' mode vector; +create function python_bvt_pc_if_else (flag bool, x int, y int) returns int language python as 'python_bvt_pc_if_else = lambda ctx, flag, left, right: __import__("pyarrow.compute", fromlist=["if_else"]).if_else(flag, left, right)' handler 'python_bvt_pc_if_else' mode vector; +create function python_bvt_pc_fill_null (x int) returns int language python as 'python_bvt_pc_fill_null = lambda ctx, values: __import__("pyarrow.compute", fromlist=["fill_null"]).fill_null(values, __import__("pyarrow").scalar(-7, type=__import__("pyarrow").int32()))' handler 'python_bvt_pc_fill_null' mode vector; +create function python_bvt_pc_is_null (x int) returns bool language python as 'python_bvt_pc_is_null = lambda ctx, values: __import__("pyarrow.compute", fromlist=["is_null"]).is_null(values)' handler 'python_bvt_pc_is_null' mode vector; +create function python_bvt_pc_float_add (x float) returns float language python as 'python_bvt_pc_float_add = lambda ctx, values: __import__("pyarrow.compute", fromlist=["add"]).add(values, __import__("pyarrow").scalar(0.5, type=__import__("pyarrow").float32()))' handler 'python_bvt_pc_float_add' mode vector; +create function python_bvt_pc_double_add (x double) returns double language python as 'python_bvt_pc_double_add = lambda ctx, values: __import__("pyarrow.compute", fromlist=["add"]).add(values, __import__("pyarrow").scalar(0.5, type=__import__("pyarrow").float64()))' handler 'python_bvt_pc_double_add' mode vector; + +create table arithmetic_values (id int, flag bool, left_value int, right_value int); +insert into arithmetic_values values + (1, true, 1, 10), + (2, false, null, 20), + (3, null, 3, null), + (4, true, null, null); + +-- These kernels must preserve Arrow validity instead of converting NULL to a +-- value or changing the batch length. +select id, + python_bvt_pc_add(left_value) as added, + python_bvt_pc_multiply(left_value, right_value) as multiplied, + python_bvt_pc_if_else(flag, left_value, right_value) as selected, + python_bvt_pc_fill_null(left_value) as filled, + python_bvt_pc_is_null(left_value) as is_null +from arithmetic_values order by id; + +create table float_values (id int, float_value float, double_value double); +insert into float_values values + (1, -1.25, 1.0), + (2, null, -2.5), + (3, 3.5, null); + +select id, + python_bvt_pc_float_add(float_value) as float_added, + python_bvt_pc_double_add(double_value) as double_added +from float_values order by id; + +drop function python_bvt_pc_add(int); +drop function python_bvt_pc_multiply(int, int); +drop function python_bvt_pc_if_else(bool, int, int); +drop function python_bvt_pc_fill_null(int); +drop function python_bvt_pc_is_null(int); +drop function python_bvt_pc_float_add(float); +drop function python_bvt_pc_double_add(double); +drop table float_values; +drop table arithmetic_values; +drop database udf_python_arrow_compute_arithmetic_bvt; diff --git a/test/distributed/cases/udf_python/arrow_compute_selection.result b/test/distributed/cases/udf_python/arrow_compute_selection.result new file mode 100644 index 0000000000000..52ab101d55735 --- /dev/null +++ b/test/distributed/cases/udf_python/arrow_compute_selection.result @@ -0,0 +1,44 @@ +drop database if exists udf_python_arrow_compute_selection_bvt; +create database udf_python_arrow_compute_selection_bvt; +use udf_python_arrow_compute_selection_bvt; +create function python_bvt_pc_take (x int, index_value int) returns int language python as 'python_bvt_pc_take = lambda ctx, values, indices: __import__("pyarrow.compute", fromlist=["take"]).take(values, indices, boundscheck=True)' handler 'python_bvt_pc_take' mode vector; +create function python_bvt_pc_sort_take (x int) returns int language python as 'python_bvt_pc_sort_take = lambda ctx, values: __import__("pyarrow.compute", fromlist=["take"]).take(values, __import__("pyarrow.compute", fromlist=["sort_indices"]).sort_indices(values, null_placement="at_end"))' handler 'python_bvt_pc_sort_take' mode vector; +create function python_bvt_pc_sort_indices (x int) returns bigint unsigned language python as 'python_bvt_pc_sort_indices = lambda ctx, values: __import__("pyarrow.compute", fromlist=["sort_indices"]).sort_indices(values, null_placement="at_end")' handler 'python_bvt_pc_sort_indices' mode vector; +create function python_bvt_pc_equal (x int) returns bool language python as 'python_bvt_pc_equal = lambda ctx, values: __import__("pyarrow.compute", fromlist=["equal"]).equal(values, __import__("pyarrow").scalar(20, type=__import__("pyarrow").int32()))' handler 'python_bvt_pc_equal' mode vector; +create function python_bvt_pc_cast (x int) returns bigint language python as 'python_bvt_pc_cast = lambda ctx, values: __import__("pyarrow.compute", fromlist=["cast"]).cast(values, __import__("pyarrow").int64(), safe=True)' handler 'python_bvt_pc_cast' mode vector; +create function python_bvt_pc_filter (x int) returns int language python as 'python_bvt_pc_filter = lambda ctx, values: __import__("pyarrow.compute", fromlist=["filter"]).filter(values, __import__("pyarrow.compute", fromlist=["greater_equal"]).greater_equal(values, 20), null_selection_behavior="drop")' handler 'python_bvt_pc_filter' mode vector; +create table selection_values (id int, value int, index_value int); +insert into selection_values values +(1, 30, 2), +(2, null, 0), +(3, 20, 1), +(4, 10, 3), +(5, 40, null); +select id, +python_bvt_pc_take(value, index_value) as taken, +python_bvt_pc_sort_take(value) as sorted_value, +python_bvt_pc_sort_indices(value) as sorted_index, +python_bvt_pc_equal(value) as equals_twenty, +python_bvt_pc_cast(value) as cast_value +from selection_values order by id; +➤ id[4,32,0] ¦ taken[4,32,0] ¦ sorted_value[4,32,0] ¦ sorted_index[-5,64,0] ¦ equals_twenty[-7,1,0] ¦ cast_value[-5,64,0] 𝄀 +1 ¦ 20 ¦ 10 ¦ 3 ¦ 0 ¦ 30 𝄀 +2 ¦ 30 ¦ 20 ¦ 2 ¦ null ¦ null 𝄀 +3 ¦ null ¦ 30 ¦ 0 ¦ 1 ¦ 20 𝄀 +4 ¦ 10 ¦ 40 ¦ 4 ¦ 0 ¦ 10 𝄀 +5 ¦ null ¦ null ¦ 1 ¦ 0 ¦ 40 +select python_bvt_pc_filter(value) from selection_values order by id; +python udf: worker error: TYPE_CONTRACT: result length does not match input rows +create table invalid_selection_values (value int, index_value int); +insert into invalid_selection_values values (30, 99); +select python_bvt_pc_take(value, index_value) from invalid_selection_values; +python udf: worker error: USER_CODE: handler or runtime failed +drop function python_bvt_pc_take(int, int); +drop function python_bvt_pc_sort_take(int); +drop function python_bvt_pc_sort_indices(int); +drop function python_bvt_pc_equal(int); +drop function python_bvt_pc_cast(int); +drop function python_bvt_pc_filter(int); +drop table invalid_selection_values; +drop table selection_values; +drop database udf_python_arrow_compute_selection_bvt; diff --git a/test/distributed/cases/udf_python/arrow_compute_selection.sql b/test/distributed/cases/udf_python/arrow_compute_selection.sql new file mode 100644 index 0000000000000..224caf9f4fe51 --- /dev/null +++ b/test/distributed/cases/udf_python/arrow_compute_selection.sql @@ -0,0 +1,52 @@ +-- Arrow compute selection, ordering, comparison, and cast kernels. +drop database if exists udf_python_arrow_compute_selection_bvt; +create database udf_python_arrow_compute_selection_bvt; +use udf_python_arrow_compute_selection_bvt; + +create function python_bvt_pc_take (x int, index_value int) returns int language python as 'python_bvt_pc_take = lambda ctx, values, indices: __import__("pyarrow.compute", fromlist=["take"]).take(values, indices, boundscheck=True)' handler 'python_bvt_pc_take' mode vector; +create function python_bvt_pc_sort_take (x int) returns int language python as 'python_bvt_pc_sort_take = lambda ctx, values: __import__("pyarrow.compute", fromlist=["take"]).take(values, __import__("pyarrow.compute", fromlist=["sort_indices"]).sort_indices(values, null_placement="at_end"))' handler 'python_bvt_pc_sort_take' mode vector; +create function python_bvt_pc_sort_indices (x int) returns bigint unsigned language python as 'python_bvt_pc_sort_indices = lambda ctx, values: __import__("pyarrow.compute", fromlist=["sort_indices"]).sort_indices(values, null_placement="at_end")' handler 'python_bvt_pc_sort_indices' mode vector; +create function python_bvt_pc_equal (x int) returns bool language python as 'python_bvt_pc_equal = lambda ctx, values: __import__("pyarrow.compute", fromlist=["equal"]).equal(values, __import__("pyarrow").scalar(20, type=__import__("pyarrow").int32()))' handler 'python_bvt_pc_equal' mode vector; +create function python_bvt_pc_cast (x int) returns bigint language python as 'python_bvt_pc_cast = lambda ctx, values: __import__("pyarrow.compute", fromlist=["cast"]).cast(values, __import__("pyarrow").int64(), safe=True)' handler 'python_bvt_pc_cast' mode vector; +create function python_bvt_pc_filter (x int) returns int language python as 'python_bvt_pc_filter = lambda ctx, values: __import__("pyarrow.compute", fromlist=["filter"]).filter(values, __import__("pyarrow.compute", fromlist=["greater_equal"]).greater_equal(values, 20), null_selection_behavior="drop")' handler 'python_bvt_pc_filter' mode vector; + +create table selection_values (id int, value int, index_value int); +insert into selection_values values + (1, 30, 2), + (2, null, 0), + (3, 20, 1), + (4, 10, 3), + (5, 40, null); + +-- take uses an Arrow index array, sort_indices keeps NULL placement explicit, +-- and cast proves that the physical Arrow type can change within the declared +-- SQL type contract. +select id, + python_bvt_pc_take(value, index_value) as taken, + python_bvt_pc_sort_take(value) as sorted_value, + python_bvt_pc_sort_indices(value) as sorted_index, + python_bvt_pc_equal(value) as equals_twenty, + python_bvt_pc_cast(value) as cast_value +from selection_values order by id; + +-- A filtering kernel shortens the Arrow array. The external evaluator must +-- reject the result instead of silently misaligning rows. +--error +select python_bvt_pc_filter(value) from selection_values order by id; + +create table invalid_selection_values (value int, index_value int); +insert into invalid_selection_values values (30, 99); + +-- boundscheck=True must turn an out-of-range index into a handler error. +--error +select python_bvt_pc_take(value, index_value) from invalid_selection_values; + +drop function python_bvt_pc_take(int, int); +drop function python_bvt_pc_sort_take(int); +drop function python_bvt_pc_sort_indices(int); +drop function python_bvt_pc_equal(int); +drop function python_bvt_pc_cast(int); +drop function python_bvt_pc_filter(int); +drop table invalid_selection_values; +drop table selection_values; +drop database udf_python_arrow_compute_selection_bvt; diff --git a/test/distributed/cases/udf_python/arrow_compute_strings.result b/test/distributed/cases/udf_python/arrow_compute_strings.result new file mode 100644 index 0000000000000..0e094d9bbad58 --- /dev/null +++ b/test/distributed/cases/udf_python/arrow_compute_strings.result @@ -0,0 +1,34 @@ +drop database if exists udf_python_arrow_compute_strings_bvt; +create database udf_python_arrow_compute_strings_bvt; +use udf_python_arrow_compute_strings_bvt; +create function python_bvt_pc_upper (x varchar(64)) returns varchar(64) language python as 'python_bvt_pc_upper = lambda ctx, values: __import__("pyarrow.compute", fromlist=["utf8_upper"]).utf8_upper(values)' handler 'python_bvt_pc_upper' mode vector; +create function python_bvt_pc_contains (x varchar(64)) returns bool language python as 'python_bvt_pc_contains = lambda ctx, values: __import__("pyarrow.compute", fromlist=["match_substring"]).match_substring(values, "a", ignore_case=False)' handler 'python_bvt_pc_contains' mode vector; +create function python_bvt_pc_replace (x varchar(64)) returns varchar(64) language python as 'python_bvt_pc_replace = lambda ctx, values: __import__("pyarrow.compute", fromlist=["replace_substring"]).replace_substring(values, "a", "X", max_replacements=-1)' handler 'python_bvt_pc_replace' mode vector; +create function python_bvt_pc_length (x varchar(64)) returns int language python as 'python_bvt_pc_length = lambda ctx, values: __import__("pyarrow.compute", fromlist=["utf8_length"]).utf8_length(values)' handler 'python_bvt_pc_length' mode vector; +create table string_values (id int, value varchar(64)); +insert into string_values values +(1, ''), +(2, 'Alpha'), +(3, '中a😀'), +(4, 'banana'), +(5, 'A'), +(6, null); +select id, +python_bvt_pc_upper(value) as upper_value, +python_bvt_pc_contains(value) as contains_a, +python_bvt_pc_replace(value) as replaced_value, +python_bvt_pc_length(value) as codepoint_length +from string_values order by id; +➤ id[4,32,0] ¦ upper_value[12,64,0] ¦ contains_a[-7,1,0] ¦ replaced_value[12,64,0] ¦ codepoint_length[4,32,0] 𝄀 +1 ¦ ¦ 0 ¦ ¦ 0 𝄀 +2 ¦ ALPHA ¦ 1 ¦ AlphX ¦ 5 𝄀 +3 ¦ 中A😀 ¦ 1 ¦ 中X😀 ¦ 3 𝄀 +4 ¦ BANANA ¦ 1 ¦ bXnXnX ¦ 6 𝄀 +5 ¦ A ¦ 0 ¦ A ¦ 1 𝄀 +6 ¦ null ¦ null ¦ null ¦ null +drop function python_bvt_pc_upper(varchar(64)); +drop function python_bvt_pc_contains(varchar(64)); +drop function python_bvt_pc_replace(varchar(64)); +drop function python_bvt_pc_length(varchar(64)); +drop table string_values; +drop database udf_python_arrow_compute_strings_bvt; diff --git a/test/distributed/cases/udf_python/arrow_compute_strings.sql b/test/distributed/cases/udf_python/arrow_compute_strings.sql new file mode 100644 index 0000000000000..eb5c01dd20040 --- /dev/null +++ b/test/distributed/cases/udf_python/arrow_compute_strings.sql @@ -0,0 +1,36 @@ +-- Arrow UTF-8 compute kernels with empty, Unicode, and NULL values. +drop database if exists udf_python_arrow_compute_strings_bvt; +create database udf_python_arrow_compute_strings_bvt; +use udf_python_arrow_compute_strings_bvt; + +create function python_bvt_pc_upper (x varchar(64)) returns varchar(64) language python as 'python_bvt_pc_upper = lambda ctx, values: __import__("pyarrow.compute", fromlist=["utf8_upper"]).utf8_upper(values)' handler 'python_bvt_pc_upper' mode vector; +create function python_bvt_pc_contains (x varchar(64)) returns bool language python as 'python_bvt_pc_contains = lambda ctx, values: __import__("pyarrow.compute", fromlist=["match_substring"]).match_substring(values, "a", ignore_case=False)' handler 'python_bvt_pc_contains' mode vector; +create function python_bvt_pc_replace (x varchar(64)) returns varchar(64) language python as 'python_bvt_pc_replace = lambda ctx, values: __import__("pyarrow.compute", fromlist=["replace_substring"]).replace_substring(values, "a", "X", max_replacements=-1)' handler 'python_bvt_pc_replace' mode vector; +create function python_bvt_pc_length (x varchar(64)) returns int language python as 'python_bvt_pc_length = lambda ctx, values: __import__("pyarrow.compute", fromlist=["utf8_length"]).utf8_length(values)' handler 'python_bvt_pc_length' mode vector; + +create table string_values (id int, value varchar(64)); +insert into string_values values + (1, ''), + (2, 'Alpha'), + (3, '中a😀'), + (4, 'banana'), + (5, 'A'), + (6, null); + +-- The kernels must preserve empty strings and NULL validity. utf8_length +-- counts Unicode code points, so the Unicode value has length three. The +-- repeated and uppercase samples distinguish all-replacement behavior from +-- a single replacement and case-sensitive matching from case folding. +select id, + python_bvt_pc_upper(value) as upper_value, + python_bvt_pc_contains(value) as contains_a, + python_bvt_pc_replace(value) as replaced_value, + python_bvt_pc_length(value) as codepoint_length +from string_values order by id; + +drop function python_bvt_pc_upper(varchar(64)); +drop function python_bvt_pc_contains(varchar(64)); +drop function python_bvt_pc_replace(varchar(64)); +drop function python_bvt_pc_length(varchar(64)); +drop table string_values; +drop database udf_python_arrow_compute_strings_bvt; diff --git a/test/distributed/cases/udf_python/control_flow.result b/test/distributed/cases/udf_python/control_flow.result new file mode 100644 index 0000000000000..f850f15cf9194 --- /dev/null +++ b/test/distributed/cases/udf_python/control_flow.result @@ -0,0 +1,57 @@ +drop database if exists udf_python_control_bvt; +create database udf_python_control_bvt; +use udf_python_control_bvt; +create function python_bvt_mark_null (x varchar(32)) returns varchar(64) language python as 'def python_bvt_mark_null(ctx, x): return "" if x is None else "<" + x + ">"' handler 'python_bvt_mark_null'; +create function python_bvt_add_one (x int) returns int language python as 'def python_bvt_add_one(ctx, x): return None if x is None else x + 1' handler 'python_bvt_add_one'; +create function python_bvt_add_pair (x int, y int) returns int language python as 'def python_bvt_add_pair(ctx, x, y): return None if x is None or y is None else x + y' handler 'python_bvt_add_pair'; +create function python_bvt_zero_arg () returns int language python as 'def python_bvt_zero_arg(ctx): return 7' handler 'python_bvt_zero_arg'; +create function python_bvt_must_not_run (x int) returns int language python as 'def python_bvt_must_not_run(ctx, x): raise RuntimeError("unselected Python branch was executed")' handler 'python_bvt_must_not_run'; +create function python_bvt_empty_input (x int) returns int language python as 'def python_bvt_empty_input(ctx, x): raise RuntimeError("empty input was executed")' handler 'python_bvt_empty_input'; +create table control_values (id int, label varchar(32), value int); +insert into control_values values +(1, 'empty', 1), +(2, '中😀', 2), +(3, null, 3); +select id, python_bvt_mark_null(label) as marked +from control_values order by id; +➤ id[4,32,0] ¦ marked[12,64,0] 𝄀 +1 ¦ 𝄀 +2 ¦ <中😀> 𝄀 +3 ¦ +select id, python_bvt_add_one(case when id = 3 then null else value end) as plus_one +from control_values order by id; +➤ id[4,32,0] ¦ plus_one[4,32,0] 𝄀 +1 ¦ 2 𝄀 +2 ¦ 3 𝄀 +3 ¦ null +select id, python_bvt_zero_arg() as constant +from control_values order by id; +➤ id[4,32,0] ¦ constant[4,32,0] 𝄀 +1 ¦ 7 𝄀 +2 ¦ 7 𝄀 +3 ¦ 7 +select id, python_bvt_add_pair(value, case when id = 3 then null else id end) as pair_sum +from control_values order by id; +➤ id[4,32,0] ¦ pair_sum[4,32,0] 𝄀 +1 ¦ 2 𝄀 +2 ¦ 4 𝄀 +3 ¦ null +select id, +case when value < 0 then python_bvt_must_not_run(value) +else 99 end as guarded +from control_values order by id; +➤ id[4,32,0] ¦ guarded[-5,64,0] 𝄀 +1 ¦ 99 𝄀 +2 ¦ 99 𝄀 +3 ¦ 99 +select python_bvt_empty_input(value) as never_returned +from control_values where 1 = 0; +➤ never_returned[4,32,0] +drop function python_bvt_mark_null(varchar(32)); +drop function python_bvt_add_one(int); +drop function python_bvt_add_pair(int, int); +drop function python_bvt_zero_arg(); +drop function python_bvt_must_not_run(int); +drop function python_bvt_empty_input(int); +drop table control_values; +drop database udf_python_control_bvt; diff --git a/test/distributed/cases/udf_python/control_flow.sql b/test/distributed/cases/udf_python/control_flow.sql new file mode 100644 index 0000000000000..9e3652cae5c93 --- /dev/null +++ b/test/distributed/cases/udf_python/control_flow.sql @@ -0,0 +1,53 @@ +-- Correctness boundaries for scalar invocation, NULL handling, empty input, +-- zero-argument calls, and CASE selection masks. +drop database if exists udf_python_control_bvt; +create database udf_python_control_bvt; +use udf_python_control_bvt; + +create function python_bvt_mark_null (x varchar(32)) returns varchar(64) language python as 'def python_bvt_mark_null(ctx, x): return "" if x is None else "<" + x + ">"' handler 'python_bvt_mark_null'; +create function python_bvt_add_one (x int) returns int language python as 'def python_bvt_add_one(ctx, x): return None if x is None else x + 1' handler 'python_bvt_add_one'; +create function python_bvt_add_pair (x int, y int) returns int language python as 'def python_bvt_add_pair(ctx, x, y): return None if x is None or y is None else x + y' handler 'python_bvt_add_pair'; +create function python_bvt_zero_arg () returns int language python as 'def python_bvt_zero_arg(ctx): return 7' handler 'python_bvt_zero_arg'; +create function python_bvt_must_not_run (x int) returns int language python as 'def python_bvt_must_not_run(ctx, x): raise RuntimeError("unselected Python branch was executed")' handler 'python_bvt_must_not_run'; +create function python_bvt_empty_input (x int) returns int language python as 'def python_bvt_empty_input(ctx, x): raise RuntimeError("empty input was executed")' handler 'python_bvt_empty_input'; + +create table control_values (id int, label varchar(32), value int); +insert into control_values values + (1, 'empty', 1), + (2, '中😀', 2), + (3, null, 3); + +-- The default policy passes NULL to the handler and preserves a handler NULL. +select id, python_bvt_mark_null(label) as marked +from control_values order by id; + +-- A scalar handler must be invoked once per row and preserve a handler NULL. +select id, python_bvt_add_one(case when id = 3 then null else value end) as plus_one +from control_values order by id; + +-- A zero-argument scalar still produces one result per input row. +select id, python_bvt_zero_arg() as constant +from control_values order by id; + +-- Multiple arguments preserve row order and NULLs independently. +select id, python_bvt_add_pair(value, case when id = 3 then null else id end) as pair_sum +from control_values order by id; + +-- A CASE branch with no selected rows must not invoke its Python handler. +select id, + case when value < 0 then python_bvt_must_not_run(value) + else 99 end as guarded +from control_values order by id; + +-- An empty input batch must finish without opening a worker invocation. +select python_bvt_empty_input(value) as never_returned +from control_values where 1 = 0; + +drop function python_bvt_mark_null(varchar(32)); +drop function python_bvt_add_one(int); +drop function python_bvt_add_pair(int, int); +drop function python_bvt_zero_arg(); +drop function python_bvt_must_not_run(int); +drop function python_bvt_empty_input(int); +drop table control_values; +drop database udf_python_control_bvt; diff --git a/test/distributed/cases/udf_python/dml_error_paths.result b/test/distributed/cases/udf_python/dml_error_paths.result new file mode 100644 index 0000000000000..f1eaa4c487777 --- /dev/null +++ b/test/distributed/cases/udf_python/dml_error_paths.result @@ -0,0 +1,30 @@ +drop database if exists udf_python_dml_errors_bvt; +create database udf_python_dml_errors_bvt; +use udf_python_dml_errors_bvt; +create function python_bvt_dml_fail (x int) returns int language python as 'def python_bvt_dml_fail(ctx, x): return x if x != 2 else 1 / 0' handler 'python_bvt_dml_fail'; +create table source_values (id int primary key, value int); +insert into source_values values (1, 1), (2, 2), (3, 3); +update source_values set value = python_bvt_dml_fail(value); +python udf: worker error: USER_CODE: handler or runtime failed +select id, value from source_values order by id; +➤ id[4,32,0] ¦ value[4,32,0] 𝄀 +1 ¦ 1 𝄀 +2 ¦ 2 𝄀 +3 ¦ 3 +create table inserted_values (id int primary key, value int); +insert into inserted_values select id, python_bvt_dml_fail(value) from source_values; +python udf: worker error: USER_CODE: handler or runtime failed +select count(*) as inserted_rows from inserted_values; +➤ inserted_rows[-5,64,0] 𝄀 +0 +delete from source_values where python_bvt_dml_fail(value) > 0; +python udf: worker error: USER_CODE: handler or runtime failed +select id, value from source_values order by id; +➤ id[4,32,0] ¦ value[4,32,0] 𝄀 +1 ¦ 1 𝄀 +2 ¦ 2 𝄀 +3 ¦ 3 +drop function python_bvt_dml_fail(int); +drop table inserted_values; +drop table source_values; +drop database udf_python_dml_errors_bvt; diff --git a/test/distributed/cases/udf_python/dml_error_paths.sql b/test/distributed/cases/udf_python/dml_error_paths.sql new file mode 100644 index 0000000000000..5e7b4d562b889 --- /dev/null +++ b/test/distributed/cases/udf_python/dml_error_paths.sql @@ -0,0 +1,31 @@ +-- A Python failure is a statement failure. The DML operator must not publish +-- rows that were evaluated before the handler raised an error. +drop database if exists udf_python_dml_errors_bvt; +create database udf_python_dml_errors_bvt; +use udf_python_dml_errors_bvt; + +create function python_bvt_dml_fail (x int) returns int language python as 'def python_bvt_dml_fail(ctx, x): return x if x != 2 else 1 / 0' handler 'python_bvt_dml_fail'; +create table source_values (id int primary key, value int); +insert into source_values values (1, 1), (2, 2), (3, 3); + +-- UPDATE evaluates row 1 before row 2 raises. The original table must remain +-- unchanged after the failed statement. +--error +update source_values set value = python_bvt_dml_fail(value); +select id, value from source_values order by id; + +create table inserted_values (id int primary key, value int); +-- INSERT ... SELECT must publish no row after the same handler failure. +--error +insert into inserted_values select id, python_bvt_dml_fail(value) from source_values; +select count(*) as inserted_rows from inserted_values; + +-- DELETE must also leave all source rows intact when its predicate fails. +--error +delete from source_values where python_bvt_dml_fail(value) > 0; +select id, value from source_values order by id; + +drop function python_bvt_dml_fail(int); +drop table inserted_values; +drop table source_values; +drop database udf_python_dml_errors_bvt; diff --git a/test/distributed/cases/udf_python/dml_positions.result b/test/distributed/cases/udf_python/dml_positions.result new file mode 100644 index 0000000000000..8b284aaf5211e --- /dev/null +++ b/test/distributed/cases/udf_python/dml_positions.result @@ -0,0 +1,17 @@ +drop database if exists udf_python_dml_bvt; +create database udf_python_dml_bvt; +use udf_python_dml_bvt; +create function python_bvt_dml_add (x int) returns int language python as 'def python_bvt_dml_add(ctx, x): return None if x is None else x + 1' handler 'python_bvt_dml_add'; +create table dml_values (id int primary key, value int); +insert into dml_values values (1, 1), (2, 2), (3, null); +insert into dml_values values (4, python_bvt_dml_add(3)); +update dml_values set value = python_bvt_dml_add(value) where id = 1; +delete from dml_values where python_bvt_dml_add(value) >= 4; +select id, value from dml_values order by id; +➤ id[4,32,0] ¦ value[4,32,0] 𝄀 +1 ¦ 2 𝄀 +2 ¦ 2 𝄀 +3 ¦ null +drop function python_bvt_dml_add(int); +drop table dml_values; +drop database udf_python_dml_bvt; diff --git a/test/distributed/cases/udf_python/dml_positions.sql b/test/distributed/cases/udf_python/dml_positions.sql new file mode 100644 index 0000000000000..f956d284924af --- /dev/null +++ b/test/distributed/cases/udf_python/dml_positions.sql @@ -0,0 +1,25 @@ +-- Exercise Python UDFs in INSERT values, UPDATE assignments, and DELETE +-- predicates. Every mutation is observed by the final SELECT. +drop database if exists udf_python_dml_bvt; +create database udf_python_dml_bvt; +use udf_python_dml_bvt; + +create function python_bvt_dml_add (x int) returns int language python as 'def python_bvt_dml_add(ctx, x): return None if x is None else x + 1' handler 'python_bvt_dml_add'; +create table dml_values (id int primary key, value int); +insert into dml_values values (1, 1), (2, 2), (3, null); + +-- INSERT must evaluate the routine for the incoming row. +insert into dml_values values (4, python_bvt_dml_add(3)); + +-- UPDATE must evaluate the routine against the target row image. +update dml_values set value = python_bvt_dml_add(value) where id = 1; + +-- DELETE must keep the routine in its target predicate. NULL remains unknown +-- and therefore must not be deleted. +delete from dml_values where python_bvt_dml_add(value) >= 4; + +select id, value from dml_values order by id; + +drop function python_bvt_dml_add(int); +drop table dml_values; +drop database udf_python_dml_bvt; diff --git a/test/distributed/cases/udf_python/numeric_boundaries.result b/test/distributed/cases/udf_python/numeric_boundaries.result new file mode 100644 index 0000000000000..c368b8dac5cac --- /dev/null +++ b/test/distributed/cases/udf_python/numeric_boundaries.result @@ -0,0 +1,75 @@ +drop database if exists udf_python_numeric_bvt; +create database udf_python_numeric_bvt; +use udf_python_numeric_bvt; +create function python_bvt_tinyint (x tinyint) returns tinyint language python as 'def python_bvt_tinyint(ctx, x): return x' handler 'python_bvt_tinyint'; +create function python_bvt_smallint (x smallint) returns smallint language python as 'def python_bvt_smallint(ctx, x): return x' handler 'python_bvt_smallint'; +create function python_bvt_int (x int) returns int language python as 'def python_bvt_int(ctx, x): return x' handler 'python_bvt_int'; +create function python_bvt_bigint (x bigint) returns bigint language python as 'def python_bvt_bigint(ctx, x): return x' handler 'python_bvt_bigint'; +create function python_bvt_tinyuint (x tinyint unsigned) returns tinyint unsigned language python as 'def python_bvt_tinyuint(ctx, x): return x' handler 'python_bvt_tinyuint'; +create function python_bvt_smalluint (x smallint unsigned) returns smallint unsigned language python as 'def python_bvt_smalluint(ctx, x): return x' handler 'python_bvt_smalluint'; +create function python_bvt_uint (x int unsigned) returns int unsigned language python as 'def python_bvt_uint(ctx, x): return x' handler 'python_bvt_uint'; +create function python_bvt_biguint (x bigint unsigned) returns bigint unsigned language python as 'def python_bvt_biguint(ctx, x): return x' handler 'python_bvt_biguint'; +create function python_bvt_float (x float) returns float language python as 'def python_bvt_float(ctx, x): return x' handler 'python_bvt_float'; +create function python_bvt_double (x double) returns double language python as 'def python_bvt_double(ctx, x): return x' handler 'python_bvt_double'; +create function python_bvt_bool (x bool) returns bool language python as 'def python_bvt_bool(ctx, x): return x' handler 'python_bvt_bool'; +create function python_bvt_decimal64 (x decimal(18,6)) returns decimal(18,6) language python as 'def python_bvt_decimal64(ctx, x): return x' handler 'python_bvt_decimal64'; +create function python_bvt_decimal128 (x decimal(38,10)) returns decimal(38,10) language python as 'def python_bvt_decimal128(ctx, x): return x' handler 'python_bvt_decimal128'; +create function python_bvt_decimal_rescale (x decimal(18,6)) returns decimal(18,6) language python as 'def python_bvt_decimal_rescale(ctx, x): return x' handler 'python_bvt_decimal_rescale'; +create table numeric_values ( +tiny_v tinyint, +small_v smallint, +int_v int, +big_v bigint, +tiny_u tinyint unsigned, +small_u smallint unsigned, +int_u int unsigned, +big_u bigint unsigned, +float_v float, +double_v double, +bool_v bool, +decimal64_v decimal(18,6), +decimal128_v decimal(38,10) +); +insert into numeric_values values +(-128, -32768, -2147483648, -9223372036854775808, +0, 0, 0, 0, -0.0, -0.0, false, -0.000001, -9999999999999999999999999999.9999999999), +(127, 32767, 2147483647, 9223372036854775807, +255, 65535, 4294967295, 18446744073709551615, 3.25, 1.0, true, 999999999999.999999, 9999999999999999999999999999.9999999999), +(null, null, null, null, null, null, null, null, null, null, null, null, null); +select python_bvt_tinyint(tiny_v) as tiny_v, +python_bvt_smallint(small_v) as small_v, +python_bvt_int(int_v) as int_v, +python_bvt_bigint(big_v) as big_v, +python_bvt_tinyuint(tiny_u) as tiny_u, +python_bvt_smalluint(small_u) as small_u, +python_bvt_uint(int_u) as int_u, +python_bvt_biguint(big_u) as big_u, +python_bvt_float(float_v) as float_v, +python_bvt_double(double_v) as double_v, +python_bvt_bool(bool_v) as bool_v, +python_bvt_decimal64(decimal64_v) as decimal64_v, +python_bvt_decimal128(decimal128_v) as decimal128_v +from numeric_values order by big_v is null, big_v; +➤ tiny_v[-6,8,0] ¦ small_v[5,16,0] ¦ int_v[4,32,0] ¦ big_v[-5,64,0] ¦ tiny_u[-6,8,0] ¦ small_u[5,16,0] ¦ int_u[4,32,0] ¦ big_u[-5,64,0] ¦ float_v[7,23,31] ¦ double_v[8,53,31] ¦ bool_v[-7,1,0] ¦ decimal64_v[3,18,6] ¦ decimal128_v[3,38,10] 𝄀 +-128 ¦ -32768 ¦ -2147483648 ¦ -9223372036854775808 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ -0.0 ¦ -0.0 ¦ 0 ¦ -0.000001 ¦ -9999999999999999999999999999.9999999999 𝄀 +127 ¦ 32767 ¦ 2147483647 ¦ 9223372036854775807 ¦ 255 ¦ 65535 ¦ 4294967295 ¦ 18446744073709551615 ¦ 3.25 ¦ 1.0 ¦ 1 ¦ 999999999999.999999 ¦ 9999999999999999999999999999.9999999999 𝄀 +null ¦ null ¦ null ¦ null ¦ null ¦ null ¦ null ¦ null ¦ null ¦ null ¦ null ¦ null ¦ null +select python_bvt_decimal_rescale(cast('1.23' as decimal(18,2))) as decimal_rescaled; +➤ decimal_rescaled[3,18,6] 𝄀 +1.230000 +drop function python_bvt_tinyint(tinyint); +drop function python_bvt_smallint(smallint); +drop function python_bvt_int(int); +drop function python_bvt_bigint(bigint); +drop function python_bvt_tinyuint(tinyint unsigned); +drop function python_bvt_smalluint(smallint unsigned); +drop function python_bvt_uint(int unsigned); +drop function python_bvt_biguint(bigint unsigned); +drop function python_bvt_float(float); +drop function python_bvt_double(double); +drop function python_bvt_bool(bool); +drop function python_bvt_decimal64(decimal(18,6)); +drop function python_bvt_decimal128(decimal(38,10)); +drop function python_bvt_decimal_rescale(decimal(18,6)); +drop table numeric_values; +drop database udf_python_numeric_bvt; diff --git a/test/distributed/cases/udf_python/numeric_boundaries.sql b/test/distributed/cases/udf_python/numeric_boundaries.sql new file mode 100644 index 0000000000000..9d63739488d49 --- /dev/null +++ b/test/distributed/cases/udf_python/numeric_boundaries.sql @@ -0,0 +1,78 @@ +-- Small, exact boundary values for every scalar numeric family supported by +-- the Python Arrow adapter. +drop database if exists udf_python_numeric_bvt; +create database udf_python_numeric_bvt; +use udf_python_numeric_bvt; + +create function python_bvt_tinyint (x tinyint) returns tinyint language python as 'def python_bvt_tinyint(ctx, x): return x' handler 'python_bvt_tinyint'; +create function python_bvt_smallint (x smallint) returns smallint language python as 'def python_bvt_smallint(ctx, x): return x' handler 'python_bvt_smallint'; +create function python_bvt_int (x int) returns int language python as 'def python_bvt_int(ctx, x): return x' handler 'python_bvt_int'; +create function python_bvt_bigint (x bigint) returns bigint language python as 'def python_bvt_bigint(ctx, x): return x' handler 'python_bvt_bigint'; +create function python_bvt_tinyuint (x tinyint unsigned) returns tinyint unsigned language python as 'def python_bvt_tinyuint(ctx, x): return x' handler 'python_bvt_tinyuint'; +create function python_bvt_smalluint (x smallint unsigned) returns smallint unsigned language python as 'def python_bvt_smalluint(ctx, x): return x' handler 'python_bvt_smalluint'; +create function python_bvt_uint (x int unsigned) returns int unsigned language python as 'def python_bvt_uint(ctx, x): return x' handler 'python_bvt_uint'; +create function python_bvt_biguint (x bigint unsigned) returns bigint unsigned language python as 'def python_bvt_biguint(ctx, x): return x' handler 'python_bvt_biguint'; +create function python_bvt_float (x float) returns float language python as 'def python_bvt_float(ctx, x): return x' handler 'python_bvt_float'; +create function python_bvt_double (x double) returns double language python as 'def python_bvt_double(ctx, x): return x' handler 'python_bvt_double'; +create function python_bvt_bool (x bool) returns bool language python as 'def python_bvt_bool(ctx, x): return x' handler 'python_bvt_bool'; +create function python_bvt_decimal64 (x decimal(18,6)) returns decimal(18,6) language python as 'def python_bvt_decimal64(ctx, x): return x' handler 'python_bvt_decimal64'; +create function python_bvt_decimal128 (x decimal(38,10)) returns decimal(38,10) language python as 'def python_bvt_decimal128(ctx, x): return x' handler 'python_bvt_decimal128'; +create function python_bvt_decimal_rescale (x decimal(18,6)) returns decimal(18,6) language python as 'def python_bvt_decimal_rescale(ctx, x): return x' handler 'python_bvt_decimal_rescale'; + +create table numeric_values ( + tiny_v tinyint, + small_v smallint, + int_v int, + big_v bigint, + tiny_u tinyint unsigned, + small_u smallint unsigned, + int_u int unsigned, + big_u bigint unsigned, + float_v float, + double_v double, + bool_v bool, + decimal64_v decimal(18,6), + decimal128_v decimal(38,10) +); +insert into numeric_values values + (-128, -32768, -2147483648, -9223372036854775808, + 0, 0, 0, 0, -0.0, -0.0, false, -0.000001, -9999999999999999999999999999.9999999999), + (127, 32767, 2147483647, 9223372036854775807, + 255, 65535, 4294967295, 18446744073709551615, 3.25, 1.0, true, 999999999999.999999, 9999999999999999999999999999.9999999999), + (null, null, null, null, null, null, null, null, null, null, null, null, null); + +select python_bvt_tinyint(tiny_v) as tiny_v, + python_bvt_smallint(small_v) as small_v, + python_bvt_int(int_v) as int_v, + python_bvt_bigint(big_v) as big_v, + python_bvt_tinyuint(tiny_u) as tiny_u, + python_bvt_smalluint(small_u) as small_u, + python_bvt_uint(int_u) as int_u, + python_bvt_biguint(big_u) as big_u, + python_bvt_float(float_v) as float_v, + python_bvt_double(double_v) as double_v, + python_bvt_bool(bool_v) as bool_v, + python_bvt_decimal64(decimal64_v) as decimal64_v, + python_bvt_decimal128(decimal128_v) as decimal128_v +from numeric_values order by big_v is null, big_v; + +-- The planner must normalize DECIMAL(18,2) to the declared scale before the +-- Arrow encoder sees the coefficient; 1.23 must remain 1.230000. +select python_bvt_decimal_rescale(cast('1.23' as decimal(18,2))) as decimal_rescaled; + +drop function python_bvt_tinyint(tinyint); +drop function python_bvt_smallint(smallint); +drop function python_bvt_int(int); +drop function python_bvt_bigint(bigint); +drop function python_bvt_tinyuint(tinyint unsigned); +drop function python_bvt_smalluint(smallint unsigned); +drop function python_bvt_uint(int unsigned); +drop function python_bvt_biguint(bigint unsigned); +drop function python_bvt_float(float); +drop function python_bvt_double(double); +drop function python_bvt_bool(bool); +drop function python_bvt_decimal64(decimal(18,6)); +drop function python_bvt_decimal128(decimal(38,10)); +drop function python_bvt_decimal_rescale(decimal(18,6)); +drop table numeric_values; +drop database udf_python_numeric_bvt; diff --git a/test/distributed/cases/udf_python/overload_namespace.result b/test/distributed/cases/udf_python/overload_namespace.result new file mode 100644 index 0000000000000..c75e6546a3527 --- /dev/null +++ b/test/distributed/cases/udf_python/overload_namespace.result @@ -0,0 +1,70 @@ +drop database if exists udf_python_namespace_bvt; +create database udf_python_namespace_bvt; +use udf_python_namespace_bvt; +create table namespace_values(x smallint); +insert into namespace_values values (1),(2); +create function overload(x bigint) returns bigint language python as 'def overload(ctx,x): return x + 100' handler 'overload'; +select overload(x) as result from namespace_values order by x; +➤ result[-5,64,0] 𝄀 +101 𝄀 +102 +prepare namespace_plan from 'select overload(x) as result from namespace_values order by x'; +execute namespace_plan; +➤ result[-5,64,0] 𝄀 +101 𝄀 +102 +use udf_python_namespace_bvt; +create function overload(x smallint) returns bigint language python as 'def overload(ctx,x): return x + 200' handler 'overload'; +execute namespace_plan; +➤ result[-5,64,0] 𝄀 +201 𝄀 +202 +select overload(x) as result from namespace_values order by x; +➤ result[-5,64,0] 𝄀 +201 𝄀 +202 +use udf_python_namespace_bvt; +create or replace function overload(x smallint) returns bigint language python as 'def overload(ctx,x): return x + 300' handler 'overload'; +execute namespace_plan; +➤ result[-5,64,0] 𝄀 +301 𝄀 +302 +select overload(x) as result from namespace_values order by x; +➤ result[-5,64,0] 𝄀 +301 𝄀 +302 +use udf_python_namespace_bvt; +drop function overload(smallint); +execute namespace_plan; +➤ result[-5,64,0] 𝄀 +101 𝄀 +102 +select overload(x) as result from namespace_values order by x; +➤ result[-5,64,0] 𝄀 +101 𝄀 +102 +use udf_python_namespace_bvt; +create function overload(x smallint) returns bigint language python as 'def overload(ctx,x): return x + 400' handler 'overload'; +execute namespace_plan; +➤ result[-5,64,0] 𝄀 +401 𝄀 +402 +select overload(x) as result from namespace_values order by x; +➤ result[-5,64,0] 𝄀 +401 𝄀 +402 +deallocate prepare namespace_plan; +create function exact_decimal(x decimal(18,2)) returns int language python as 'def exact_decimal(ctx,x): return 2' handler 'exact_decimal'; +create function exact_decimal(x decimal(18,6)) returns int language python as 'def exact_decimal(ctx,x): return 6' handler 'exact_decimal'; +drop function exact_decimal(decimal(18,2)); +select count(*) as remaining_heads from mo_catalog.mo_user_defined_function where db = 'udf_python_namespace_bvt' and name = 'exact_decimal'; +➤ remaining_heads[-5,64,0] 𝄀 +1 +select count(*) as remaining_revisions from mo_catalog.mo_function_revisions r join mo_catalog.mo_user_defined_function f on r.function_id = f.function_id where f.db = 'udf_python_namespace_bvt' and f.name = 'exact_decimal'; +➤ remaining_revisions[-5,64,0] 𝄀 +1 +select exact_decimal(cast(1.23 as decimal(18,6))) as surviving_overload; +➤ surviving_overload[4,32,0] 𝄀 +6 +drop function exact_decimal(decimal(18,6)); +drop database udf_python_namespace_bvt; diff --git a/test/distributed/cases/udf_python/overload_namespace.sql b/test/distributed/cases/udf_python/overload_namespace.sql new file mode 100644 index 0000000000000..f9dd31556db9b --- /dev/null +++ b/test/distributed/cases/udf_python/overload_namespace.sql @@ -0,0 +1,43 @@ +drop database if exists udf_python_namespace_bvt; +create database udf_python_namespace_bvt; +use udf_python_namespace_bvt; +create table namespace_values(x smallint); +insert into namespace_values values (1),(2); +create function overload(x bigint) returns bigint language python as 'def overload(ctx,x): return x + 100' handler 'overload'; +select overload(x) as result from namespace_values order by x; +prepare namespace_plan from 'select overload(x) as result from namespace_values order by x'; +execute namespace_plan; +-- @session:id=1 +use udf_python_namespace_bvt; +create function overload(x smallint) returns bigint language python as 'def overload(ctx,x): return x + 200' handler 'overload'; +-- @session +execute namespace_plan; +select overload(x) as result from namespace_values order by x; +-- @session:id=1 +use udf_python_namespace_bvt; +create or replace function overload(x smallint) returns bigint language python as 'def overload(ctx,x): return x + 300' handler 'overload'; +-- @session +execute namespace_plan; +select overload(x) as result from namespace_values order by x; +-- @session:id=1 +use udf_python_namespace_bvt; +drop function overload(smallint); +-- @session +execute namespace_plan; +select overload(x) as result from namespace_values order by x; +-- @session:id=1 +use udf_python_namespace_bvt; +create function overload(x smallint) returns bigint language python as 'def overload(ctx,x): return x + 400' handler 'overload'; +-- @session +execute namespace_plan; +select overload(x) as result from namespace_values order by x; +deallocate prepare namespace_plan; +-- Exact input descriptors, including scale, select the identity removed by DROP. +create function exact_decimal(x decimal(18,2)) returns int language python as 'def exact_decimal(ctx,x): return 2' handler 'exact_decimal'; +create function exact_decimal(x decimal(18,6)) returns int language python as 'def exact_decimal(ctx,x): return 6' handler 'exact_decimal'; +drop function exact_decimal(decimal(18,2)); +select count(*) as remaining_heads from mo_catalog.mo_user_defined_function where db = 'udf_python_namespace_bvt' and name = 'exact_decimal'; +select count(*) as remaining_revisions from mo_catalog.mo_function_revisions r join mo_catalog.mo_user_defined_function f on r.function_id = f.function_id where f.db = 'udf_python_namespace_bvt' and f.name = 'exact_decimal'; +select exact_decimal(cast(1.23 as decimal(18,6))) as surviving_overload; +drop function exact_decimal(decimal(18,6)); +drop database udf_python_namespace_bvt; diff --git a/test/distributed/cases/udf_python/relational_positions.result b/test/distributed/cases/udf_python/relational_positions.result new file mode 100644 index 0000000000000..3ccca0c83215c --- /dev/null +++ b/test/distributed/cases/udf_python/relational_positions.result @@ -0,0 +1,59 @@ +drop database if exists udf_python_positions_bvt; +create database udf_python_positions_bvt; +use udf_python_positions_bvt; +create function python_bvt_position_add (x int) returns int language python as 'def python_bvt_position_add(ctx, x): return None if x is None else x + 1' handler 'python_bvt_position_add'; +create function python_bvt_position_twice (x int) returns int language python as 'def python_bvt_position_twice(ctx, x): return None if x is None else x * 2' handler 'python_bvt_position_twice'; +create table position_left (id int, join_key int, value int); +create table position_right (join_key int, tag varchar(8)); +insert into position_left values (1, 10, 1), (2, 20, 2), (3, 30, null); +insert into position_right values (11, 'a'), (21, 'b'), (40, 'd'); +select id, python_bvt_position_add(value) as plus +from position_left +where python_bvt_position_add(value) > 1 +order by id; +➤ id[4,32,0] ¦ plus[4,32,0] 𝄀 +1 ¦ 2 𝄀 +2 ¦ 3 +select l.id, r.tag +from position_left l join position_right r +on python_bvt_position_add(l.join_key) = r.join_key +order by l.id; +➤ id[4,32,0] ¦ tag[12,8,0] 𝄀 +1 ¦ a 𝄀 +2 ¦ b +select l.id, r.tag +from position_left l left join position_right r +on python_bvt_position_add(l.join_key) = r.join_key +order by l.id; +➤ id[4,32,0] ¦ tag[12,8,0] 𝄀 +1 ¦ a 𝄀 +2 ¦ b 𝄀 +3 ¦ null +select join_key, sum(python_bvt_position_add(value)) as total +from position_left +group by join_key +order by join_key; +➤ join_key[4,32,0] ¦ total[-5,64,0] 𝄀 +10 ¦ 2 𝄀 +20 ¦ 3 𝄀 +30 ¦ null +select id, python_bvt_position_add(value) as plus, +row_number() over (order by python_bvt_position_add(value)) as rn +from position_left +order by id; +➤ id[4,32,0] ¦ plus[4,32,0] ¦ rn[-5,64,0] 𝄀 +1 ¦ 2 ¦ 2 𝄀 +2 ¦ 3 ¦ 3 𝄀 +3 ¦ null ¦ 1 +select id, python_bvt_position_twice(python_bvt_position_add(value)) as nested +from position_left +order by id; +➤ id[4,32,0] ¦ nested[4,32,0] 𝄀 +1 ¦ 4 𝄀 +2 ¦ 6 𝄀 +3 ¦ null +drop function python_bvt_position_add(int); +drop function python_bvt_position_twice(int); +drop table position_left; +drop table position_right; +drop database udf_python_positions_bvt; diff --git a/test/distributed/cases/udf_python/relational_positions.sql b/test/distributed/cases/udf_python/relational_positions.sql new file mode 100644 index 0000000000000..8ec2e716f4470 --- /dev/null +++ b/test/distributed/cases/udf_python/relational_positions.sql @@ -0,0 +1,54 @@ +-- Exercise the current SQL execution positions that must preserve the +-- Python call's row mapping: WHERE, JOIN ON, outer join, aggregate, window, +-- and a dependent call g(f(x)). +drop database if exists udf_python_positions_bvt; +create database udf_python_positions_bvt; +use udf_python_positions_bvt; + +create function python_bvt_position_add (x int) returns int language python as 'def python_bvt_position_add(ctx, x): return None if x is None else x + 1' handler 'python_bvt_position_add'; +create function python_bvt_position_twice (x int) returns int language python as 'def python_bvt_position_twice(ctx, x): return None if x is None else x * 2' handler 'python_bvt_position_twice'; + +create table position_left (id int, join_key int, value int); +create table position_right (join_key int, tag varchar(8)); +insert into position_left values (1, 10, 1), (2, 20, 2), (3, 30, null); +insert into position_right values (11, 'a'), (21, 'b'), (40, 'd'); + +-- The predicate and projection both use Python, with NULL filtered by SQL. +select id, python_bvt_position_add(value) as plus +from position_left +where python_bvt_position_add(value) > 1 +order by id; + +-- The UDF remains part of JOIN ON and must not be rewritten as a post-join +-- filter, so the LEFT JOIN keeps the unmatched outer row. +select l.id, r.tag +from position_left l join position_right r + on python_bvt_position_add(l.join_key) = r.join_key +order by l.id; + +select l.id, r.tag +from position_left l left join position_right r + on python_bvt_position_add(l.join_key) = r.join_key +order by l.id; + +-- Aggregate input and window ordering both consume a Python expression. +select join_key, sum(python_bvt_position_add(value)) as total +from position_left +group by join_key +order by join_key; + +select id, python_bvt_position_add(value) as plus, + row_number() over (order by python_bvt_position_add(value)) as rn +from position_left +order by id; + +-- The outer call consumes the inner call's result and must retain NULL. +select id, python_bvt_position_twice(python_bvt_position_add(value)) as nested +from position_left +order by id; + +drop function python_bvt_position_add(int); +drop function python_bvt_position_twice(int); +drop table position_left; +drop table position_right; +drop database udf_python_positions_bvt; diff --git a/test/distributed/cases/udf_python/revision_lifecycle.result b/test/distributed/cases/udf_python/revision_lifecycle.result new file mode 100644 index 0000000000000..9cc809811a16c --- /dev/null +++ b/test/distributed/cases/udf_python/revision_lifecycle.result @@ -0,0 +1,35 @@ +drop database if exists udf_python_revision_bvt; +create database udf_python_revision_bvt; +use udf_python_revision_bvt; +create function python_bvt_revision (x int) returns int language python as 'def python_bvt_revision(ctx, x): return None if x is None else x + 1' handler 'python_bvt_revision'; +create table revision_values (id int, value int); +insert into revision_values values (1, 1), (2, null); +select id, python_bvt_revision(value) as result from revision_values order by id; +➤ id[4,32,0] ¦ result[4,32,0] 𝄀 +1 ¦ 2 𝄀 +2 ¦ null +create or replace function python_bvt_revision (x int) returns int language python as 'def python_bvt_revision(ctx, x): return None if x is None else x + 2' handler 'python_bvt_revision'; +select id, python_bvt_revision(value) as result from revision_values order by id; +➤ id[4,32,0] ¦ result[4,32,0] 𝄀 +1 ¦ 3 𝄀 +2 ¦ null +prepare python_revision_plan from 'select id, python_bvt_revision(value) as result from revision_values order by id'; +execute python_revision_plan; +➤ id[4,32,0] ¦ result[4,32,0] 𝄀 +1 ¦ 3 𝄀 +2 ¦ null +create or replace function python_bvt_revision (x int) returns int language python as 'def python_bvt_revision(ctx, x): return None if x is None else x + 4' handler 'python_bvt_revision'; +execute python_revision_plan; +➤ id[4,32,0] ¦ result[4,32,0] 𝄀 +1 ¦ 5 𝄀 +2 ¦ null +deallocate prepare python_revision_plan; +drop function python_bvt_revision(int); +create function python_bvt_revision (x int) returns int language python as 'def python_bvt_revision(ctx, x): return None if x is None else x + 3' handler 'python_bvt_revision'; +select id, python_bvt_revision(value) as result from revision_values order by id; +➤ id[4,32,0] ¦ result[4,32,0] 𝄀 +1 ¦ 4 𝄀 +2 ¦ null +drop function python_bvt_revision(int); +drop table revision_values; +drop database udf_python_revision_bvt; diff --git a/test/distributed/cases/udf_python/revision_lifecycle.sql b/test/distributed/cases/udf_python/revision_lifecycle.sql new file mode 100644 index 0000000000000..dbb28f1abd098 --- /dev/null +++ b/test/distributed/cases/udf_python/revision_lifecycle.sql @@ -0,0 +1,20 @@ +drop database if exists udf_python_revision_bvt; +create database udf_python_revision_bvt; +use udf_python_revision_bvt; +create function python_bvt_revision (x int) returns int language python as 'def python_bvt_revision(ctx, x): return None if x is None else x + 1' handler 'python_bvt_revision'; +create table revision_values (id int, value int); +insert into revision_values values (1, 1), (2, null); +select id, python_bvt_revision(value) as result from revision_values order by id; +create or replace function python_bvt_revision (x int) returns int language python as 'def python_bvt_revision(ctx, x): return None if x is None else x + 2' handler 'python_bvt_revision'; +select id, python_bvt_revision(value) as result from revision_values order by id; +prepare python_revision_plan from 'select id, python_bvt_revision(value) as result from revision_values order by id'; +execute python_revision_plan; +create or replace function python_bvt_revision (x int) returns int language python as 'def python_bvt_revision(ctx, x): return None if x is None else x + 4' handler 'python_bvt_revision'; +execute python_revision_plan; +deallocate prepare python_revision_plan; +drop function python_bvt_revision(int); +create function python_bvt_revision (x int) returns int language python as 'def python_bvt_revision(ctx, x): return None if x is None else x + 3' handler 'python_bvt_revision'; +select id, python_bvt_revision(value) as result from revision_values order by id; +drop function python_bvt_revision(int); +drop table revision_values; +drop database udf_python_revision_bvt; diff --git a/test/distributed/cases/udf_python/snapshot_restore.result b/test/distributed/cases/udf_python/snapshot_restore.result new file mode 100644 index 0000000000000..15b3d027484e5 --- /dev/null +++ b/test/distributed/cases/udf_python/snapshot_restore.result @@ -0,0 +1,40 @@ +drop snapshot if exists python_udf_revision_snapshot; +drop account if exists python_udf_restore_target; +drop account if exists python_udf_restore_source; +create account python_udf_restore_source admin_name = 'udf_admin' identified by '111'; +create account python_udf_restore_target admin_name = 'udf_admin' identified by '111'; +create database udf_restore; +use udf_restore; +create function restored_python(x int) returns int language python as 'def restored_python(ctx,x): return x + 10' handler 'restored_python'; +create function restored_sql(x int) returns int language sql as '$1 + 20'; +create table expected_revisions as select f.name, f.function_id, f.active_revision, r.body from mo_catalog.mo_user_defined_function f join mo_catalog.mo_function_revisions r on f.function_id = r.function_id and f.active_revision = r.revision where f.db = 'udf_restore'; +select restored_python(1) as python_value, restored_sql(1) as sql_value; +➤ python_value[4,32,0] ¦ sql_value[-5,64,0] 𝄀 +11 ¦ 21 +create snapshot python_udf_revision_snapshot for account python_udf_restore_source; +use udf_restore; +create or replace function restored_python(x int) returns int language python as 'def restored_python(ctx,x): return x + 100' handler 'restored_python'; +select restored_python(1) as source_value; +➤ source_value[4,32,0] 𝄀 +101 +restore account python_udf_restore_source{snapshot="python_udf_revision_snapshot"} to account python_udf_restore_target; +use udf_restore; +select restored_python(1) as python_value, restored_sql(1) as sql_value; +➤ python_value[4,32,0] ¦ sql_value[-5,64,0] 𝄀 +11 ¦ 21 +select count(*) as exact_restored_revisions from expected_revisions e join mo_catalog.mo_user_defined_function f on e.function_id = f.function_id and e.name = f.name and e.active_revision = f.active_revision join mo_catalog.mo_function_revisions r on f.function_id = r.function_id and f.active_revision = r.revision where f.db = 'udf_restore' and e.body = r.body; +➤ exact_restored_revisions[-5,64,0] 𝄀 +2 +use udf_restore; +select restored_python(1) as source_unchanged; +➤ source_unchanged[4,32,0] 𝄀 +101 +drop snapshot python_udf_revision_snapshot; +drop account python_udf_restore_target; +drop account python_udf_restore_source; +select count(*) as leftover_accounts from mo_catalog.mo_account where account_name in ('python_udf_restore_source','python_udf_restore_target'); +➤ leftover_accounts[-5,64,0] 𝄀 +0 +select count(*) as leftover_snapshots from mo_catalog.mo_snapshots where sname = 'python_udf_revision_snapshot'; +➤ leftover_snapshots[-5,64,0] 𝄀 +0 diff --git a/test/distributed/cases/udf_python/snapshot_restore.sql b/test/distributed/cases/udf_python/snapshot_restore.sql new file mode 100644 index 0000000000000..b123d80b68ab3 --- /dev/null +++ b/test/distributed/cases/udf_python/snapshot_restore.sql @@ -0,0 +1,34 @@ +-- Restore into a different account must republish the account-scoped artifact. +drop snapshot if exists python_udf_revision_snapshot; +drop account if exists python_udf_restore_target; +drop account if exists python_udf_restore_source; +create account python_udf_restore_source admin_name = 'udf_admin' identified by '111'; +create account python_udf_restore_target admin_name = 'udf_admin' identified by '111'; +-- @session:id=1&user=python_udf_restore_source:udf_admin&password=111 +create database udf_restore; +use udf_restore; +create function restored_python(x int) returns int language python as 'def restored_python(ctx,x): return x + 10' handler 'restored_python'; +create function restored_sql(x int) returns int language sql as '$1 + 20'; +create table expected_revisions as select f.name, f.function_id, f.active_revision, r.body from mo_catalog.mo_user_defined_function f join mo_catalog.mo_function_revisions r on f.function_id = r.function_id and f.active_revision = r.revision where f.db = 'udf_restore'; +select restored_python(1) as python_value, restored_sql(1) as sql_value; +-- @session +create snapshot python_udf_revision_snapshot for account python_udf_restore_source; +-- @session:id=1&user=python_udf_restore_source:udf_admin&password=111 +use udf_restore; +create or replace function restored_python(x int) returns int language python as 'def restored_python(ctx,x): return x + 100' handler 'restored_python'; +select restored_python(1) as source_value; +-- @session +restore account python_udf_restore_source{snapshot="python_udf_revision_snapshot"} to account python_udf_restore_target; +-- @session:id=2&user=python_udf_restore_target:udf_admin&password=111 +use udf_restore; +select restored_python(1) as python_value, restored_sql(1) as sql_value; +select count(*) as exact_restored_revisions from expected_revisions e join mo_catalog.mo_user_defined_function f on e.function_id = f.function_id and e.name = f.name and e.active_revision = f.active_revision join mo_catalog.mo_function_revisions r on f.function_id = r.function_id and f.active_revision = r.revision where f.db = 'udf_restore' and e.body = r.body; +-- @session:id=1&user=python_udf_restore_source:udf_admin&password=111 +use udf_restore; +select restored_python(1) as source_unchanged; +-- @session +drop snapshot python_udf_revision_snapshot; +drop account python_udf_restore_target; +drop account python_udf_restore_source; +select count(*) as leftover_accounts from mo_catalog.mo_account where account_name in ('python_udf_restore_source','python_udf_restore_target'); +select count(*) as leftover_snapshots from mo_catalog.mo_snapshots where sname = 'python_udf_revision_snapshot'; diff --git a/test/distributed/cases/udf_python/temporal_boundaries.result b/test/distributed/cases/udf_python/temporal_boundaries.result new file mode 100644 index 0000000000000..1c90a1f65d00a --- /dev/null +++ b/test/distributed/cases/udf_python/temporal_boundaries.result @@ -0,0 +1,41 @@ +drop database if exists udf_python_temporal_bvt; +create database udf_python_temporal_bvt; +use udf_python_temporal_bvt; +create function python_bvt_date (x date) returns date language python as 'def python_bvt_date(ctx, x): return x' handler 'python_bvt_date'; +create function python_bvt_datetime (x datetime(6)) returns datetime(6) language python as 'def python_bvt_datetime(ctx, x): return x' handler 'python_bvt_datetime'; +create function python_bvt_timestamp (x timestamp(6)) returns timestamp(6) language python as 'def python_bvt_timestamp(ctx, x): return x' handler 'python_bvt_timestamp'; +create function python_bvt_time (x time(6)) returns time(6) language python as 'def python_bvt_time(ctx, x): return x' handler 'python_bvt_time'; +create table temporal_values ( +id int, +date_v date, +datetime_v datetime(6), +timestamp_v timestamp(6), +time_v time(6) +); +insert into temporal_values values +(1, '2024-02-29', '2024-02-29 23:59:59.123456', '2024-02-29 23:59:59.123456', '-838:59:59'), +(2, '2024-03-01', '2024-03-01 00:00:00.000000', '2024-03-01 00:00:00.000000', '838:59:59'), +(3, null, null, null, null); +select id, python_bvt_date(date_v) as date_v, +python_bvt_datetime(datetime_v) as datetime_v, +python_bvt_timestamp(timestamp_v) as timestamp_v, +python_bvt_time(time_v) as time_v +from temporal_values order by id; +➤ id[4,32,0] ¦ date_v[91,10,0] ¦ datetime_v[93,26,0] ¦ timestamp_v[93,26,0] ¦ time_v[92,17,0] 𝄀 +1 ¦ 2024-02-29 ¦ 2024-02-29 23:59:59.123456000 ¦ 2024-02-29 23:59:59.123456000 ¦ -838:59:59 𝄀 +2 ¦ 2024-03-01 ¦ 2024-03-01 00:00:00 ¦ 2024-03-01 00:00:00 ¦ 838:59:59 𝄀 +3 ¦ null ¦ null ¦ null ¦ null +set @udf_python_saved_sql_mode = @@sql_mode; +set session sql_mode = ''; +select python_bvt_date(cast('0000-00-00' as date)) as zero_date, +python_bvt_datetime(cast('0000-00-00 00:00:00' as datetime(6))) as zero_datetime, +python_bvt_timestamp(cast('0000-00-00 00:00:00' as timestamp(6))) as zero_timestamp; +➤ zero_date[91,10,0] ¦ zero_datetime[93,26,0] ¦ zero_timestamp[93,26,0] 𝄀 +0000-00-00 ¦ 0000-00-00 00:00:00 ¦ 0000-00-00 00:00:00 +set session sql_mode = @udf_python_saved_sql_mode; +drop function python_bvt_date(date); +drop function python_bvt_datetime(datetime(6)); +drop function python_bvt_timestamp(timestamp(6)); +drop function python_bvt_time(time(6)); +drop table temporal_values; +drop database udf_python_temporal_bvt; diff --git a/test/distributed/cases/udf_python/temporal_boundaries.sql b/test/distributed/cases/udf_python/temporal_boundaries.sql new file mode 100644 index 0000000000000..502107777c7bb --- /dev/null +++ b/test/distributed/cases/udf_python/temporal_boundaries.sql @@ -0,0 +1,43 @@ +-- SQL temporal values, including the explicit zero-date representation that +-- cannot be represented by Python's datetime.date/datetime classes. +drop database if exists udf_python_temporal_bvt; +create database udf_python_temporal_bvt; +use udf_python_temporal_bvt; + +create function python_bvt_date (x date) returns date language python as 'def python_bvt_date(ctx, x): return x' handler 'python_bvt_date'; +create function python_bvt_datetime (x datetime(6)) returns datetime(6) language python as 'def python_bvt_datetime(ctx, x): return x' handler 'python_bvt_datetime'; +create function python_bvt_timestamp (x timestamp(6)) returns timestamp(6) language python as 'def python_bvt_timestamp(ctx, x): return x' handler 'python_bvt_timestamp'; +create function python_bvt_time (x time(6)) returns time(6) language python as 'def python_bvt_time(ctx, x): return x' handler 'python_bvt_time'; + +create table temporal_values ( + id int, + date_v date, + datetime_v datetime(6), + timestamp_v timestamp(6), + time_v time(6) +); +insert into temporal_values values + (1, '2024-02-29', '2024-02-29 23:59:59.123456', '2024-02-29 23:59:59.123456', '-838:59:59'), + (2, '2024-03-01', '2024-03-01 00:00:00.000000', '2024-03-01 00:00:00.000000', '838:59:59'), + (3, null, null, null, null); + +select id, python_bvt_date(date_v) as date_v, + python_bvt_datetime(datetime_v) as datetime_v, + python_bvt_timestamp(timestamp_v) as timestamp_v, + python_bvt_time(time_v) as time_v +from temporal_values order by id; + +-- Zero temporal values are valid values and must stay distinct from SQL NULL. +set @udf_python_saved_sql_mode = @@sql_mode; +set session sql_mode = ''; +select python_bvt_date(cast('0000-00-00' as date)) as zero_date, + python_bvt_datetime(cast('0000-00-00 00:00:00' as datetime(6))) as zero_datetime, + python_bvt_timestamp(cast('0000-00-00 00:00:00' as timestamp(6))) as zero_timestamp; +set session sql_mode = @udf_python_saved_sql_mode; + +drop function python_bvt_date(date); +drop function python_bvt_datetime(datetime(6)); +drop function python_bvt_timestamp(timestamp(6)); +drop function python_bvt_time(time(6)); +drop table temporal_values; +drop database udf_python_temporal_bvt; diff --git a/test/distributed/cases/udf_python/udf_python.result b/test/distributed/cases/udf_python/udf_python.result new file mode 100644 index 0000000000000..3f0984316c0bf --- /dev/null +++ b/test/distributed/cases/udf_python/udf_python.result @@ -0,0 +1,33 @@ +drop database if exists udf_python_bvt; +create database udf_python_bvt; +use udf_python_bvt; +create function python_bvt_add (x int) returns int language python as 'def python_bvt_add(ctx, x): return None if x is None else x + 1' handler 'python_bvt_add'; +create table input_values (v int); +insert into input_values values (1), (null), (3); +select v, python_bvt_add(v) as plus_one from input_values order by v is null, v; +➤ v[4,32,0] ¦ plus_one[4,32,0] 𝄀 +1 ¦ 2 𝄀 +3 ¦ 4 𝄀 +null ¦ null +select case when v is null then 99 else python_bvt_add(v) end as guarded from input_values order by v is null, v; +➤ guarded[-5,64,0] 𝄀 +2 𝄀 +4 𝄀 +99 +create function python_bvt_bad_syntax (x int) returns int language python as 'def python_bvt_bad_syntax(ctx, x) return x' handler 'python_bvt_bad_syntax'; +-- @regex("Python syntax error at line", true) +USER_CODE: Python syntax error at line 1, column 35: expected ':' +create function python_bvt_replace (x int) returns int language python as 'def python_bvt_replace(ctx, x): return x + 10' handler 'python_bvt_replace'; +select python_bvt_replace(1); +➤ python_bvt_replace(1)[4,32,0] 𝄀 +11 +create or replace function python_bvt_replace (x int) returns int language python as 'def python_bvt_replace(ctx, x) return x + 20' handler 'python_bvt_replace'; +-- @regex("Python syntax error at line", true) +USER_CODE: Python syntax error at line 1, column 32: expected ':' +select python_bvt_replace(1); +➤ python_bvt_replace(1)[4,32,0] 𝄀 +11 +drop function python_bvt_add(int); +drop function python_bvt_replace(int); +drop table input_values; +drop database udf_python_bvt; diff --git a/test/distributed/cases/udf_python/udf_python.sql b/test/distributed/cases/udf_python/udf_python.sql new file mode 100644 index 0000000000000..e0f580774427b --- /dev/null +++ b/test/distributed/cases/udf_python/udf_python.sql @@ -0,0 +1,27 @@ +drop database if exists udf_python_bvt; +create database udf_python_bvt; +use udf_python_bvt; + +create function python_bvt_add (x int) returns int language python as 'def python_bvt_add(ctx, x): return None if x is None else x + 1' handler 'python_bvt_add'; +create table input_values (v int); +insert into input_values values (1), (null), (3); + +select v, python_bvt_add(v) as plus_one from input_values order by v is null, v; +select case when v is null then 99 else python_bvt_add(v) end as guarded from input_values order by v is null, v; + +-- Python source is compiled by the current worker before a Catalog identity +-- or revision is published. +-- @regex("Python syntax error at line",true) +create function python_bvt_bad_syntax (x int) returns int language python as 'def python_bvt_bad_syntax(ctx, x) return x' handler 'python_bvt_bad_syntax'; + +-- A failed replacement keeps the previous immutable active revision usable. +create function python_bvt_replace (x int) returns int language python as 'def python_bvt_replace(ctx, x): return x + 10' handler 'python_bvt_replace'; +select python_bvt_replace(1); +-- @regex("Python syntax error at line",true) +create or replace function python_bvt_replace (x int) returns int language python as 'def python_bvt_replace(ctx, x) return x + 20' handler 'python_bvt_replace'; +select python_bvt_replace(1); + +drop function python_bvt_add(int); +drop function python_bvt_replace(int); +drop table input_values; +drop database udf_python_bvt; diff --git a/test/distributed/cases/udf_python/value_types.result b/test/distributed/cases/udf_python/value_types.result new file mode 100644 index 0000000000000..26b59820c098e --- /dev/null +++ b/test/distributed/cases/udf_python/value_types.result @@ -0,0 +1,72 @@ +drop database if exists udf_python_values_bvt; +create database udf_python_values_bvt; +use udf_python_values_bvt; +create function python_bvt_varchar (x varchar(64)) returns varchar(64) language python as 'def python_bvt_varchar(ctx, x): return x' handler 'python_bvt_varchar'; +create function python_bvt_text (x text) returns text language python as 'def python_bvt_text(ctx, x): return x' handler 'python_bvt_text'; +create function python_bvt_varbinary (x varbinary(8)) returns varbinary(8) language python as 'def python_bvt_varbinary(ctx, x): return x' handler 'python_bvt_varbinary'; +create function python_bvt_blob (x blob) returns blob language python as 'def python_bvt_blob(ctx, x): return x' handler 'python_bvt_blob'; +create function python_bvt_json (x json) returns json language python as 'def python_bvt_json(ctx, x): return None if x is None else __import__("json").dumps(__import__("json").loads(x), ensure_ascii=False, separators=(",", ":"))' handler 'python_bvt_json'; +create function python_bvt_uuid (x uuid) returns uuid language python as 'def python_bvt_uuid(ctx, x): return x' handler 'python_bvt_uuid'; +create table text_values (id int, value varchar(64), long_value text); +insert into text_values values +(1, '', repeat('a', 64)), +(2, '中😀', '数据库'), +(3, repeat('v', 64), repeat('b', 64)), +(4, null, null); +select id, python_bvt_varchar(value) as value, +python_bvt_text(long_value) as long_value +from text_values order by id; +➤ id[4,32,0] ¦ value[12,64,0] ¦ long_value[-1,16383,0] 𝄀 +1 ¦ ¦ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 𝄀 +2 ¦ 中😀 ¦ 数据库 𝄀 +3 ¦ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv ¦ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 𝄀 +4 ¦ null ¦ null +create table binary_values (id int, var_value varbinary(8), blob_value blob); +insert into binary_values values +(1, unhex(''), unhex('')), +(2, unhex('00010203ff'), unhex('00ff10')), +(3, unhex('00010203ff060708'), unhex('00010203ff060708')), +(4, null, null); +select id, hex(python_bvt_varbinary(var_value)) as var_value, +hex(python_bvt_blob(blob_value)) as blob_value +from binary_values order by id; +➤ id[4,32,0] ¦ var_value[12,16,0] ¦ blob_value[-1,16383,0] 𝄀 +1 ¦ ¦ 𝄀 +2 ¦ 00010203FF ¦ 00FF10 𝄀 +3 ¦ 00010203FF060708 ¦ 00010203FF060708 𝄀 +4 ¦ null ¦ null +create table json_values (id int, value json); +insert into json_values values +(1, '{}'), +(2, '{"a":1,"b":[true,null,"中"]}'), +(3, '1'), +(4, null); +select id, python_bvt_json(value) as value +from json_values order by id; +➤ id[4,32,0] ¦ value[-1,2147483647,0] 𝄀 +1 ¦ {} 𝄀 +2 ¦ {"a": 1, "b": [true, null, "中"]} 𝄀 +3 ¦ 1 𝄀 +4 ¦ null +create table uuid_values (id int, value uuid); +insert into uuid_values values +(1, cast('00000000-0000-0000-0000-000000000000' as uuid)), +(2, cast('123e4567-e89b-12d3-a456-426614174000' as uuid)), +(3, null); +select id, python_bvt_uuid(value) as value +from uuid_values order by id; +➤ id[4,32,0] ¦ value[12,-1,0] 𝄀 +1 ¦ 00000000-0000-0000-0000-000000000000 𝄀 +2 ¦ 123e4567-e89b-12d3-a456-426614174000 𝄀 +3 ¦ null +drop function python_bvt_varchar(varchar(64)); +drop function python_bvt_text(text); +drop function python_bvt_varbinary(varbinary(8)); +drop function python_bvt_blob(blob); +drop function python_bvt_json(json); +drop function python_bvt_uuid(uuid); +drop table text_values; +drop table binary_values; +drop table json_values; +drop table uuid_values; +drop database udf_python_values_bvt; diff --git a/test/distributed/cases/udf_python/value_types.sql b/test/distributed/cases/udf_python/value_types.sql new file mode 100644 index 0000000000000..a9497376d4fb0 --- /dev/null +++ b/test/distributed/cases/udf_python/value_types.sql @@ -0,0 +1,64 @@ +-- Boundary values for variable-width text, binary payloads, JSON, and UUID. +drop database if exists udf_python_values_bvt; +create database udf_python_values_bvt; +use udf_python_values_bvt; + +create function python_bvt_varchar (x varchar(64)) returns varchar(64) language python as 'def python_bvt_varchar(ctx, x): return x' handler 'python_bvt_varchar'; +create function python_bvt_text (x text) returns text language python as 'def python_bvt_text(ctx, x): return x' handler 'python_bvt_text'; +create function python_bvt_varbinary (x varbinary(8)) returns varbinary(8) language python as 'def python_bvt_varbinary(ctx, x): return x' handler 'python_bvt_varbinary'; +create function python_bvt_blob (x blob) returns blob language python as 'def python_bvt_blob(ctx, x): return x' handler 'python_bvt_blob'; +create function python_bvt_json (x json) returns json language python as 'def python_bvt_json(ctx, x): return None if x is None else __import__("json").dumps(__import__("json").loads(x), ensure_ascii=False, separators=(",", ":"))' handler 'python_bvt_json'; +create function python_bvt_uuid (x uuid) returns uuid language python as 'def python_bvt_uuid(ctx, x): return x' handler 'python_bvt_uuid'; + +create table text_values (id int, value varchar(64), long_value text); +insert into text_values values + (1, '', repeat('a', 64)), + (2, '中😀', '数据库'), + (3, repeat('v', 64), repeat('b', 64)), + (4, null, null); + +select id, python_bvt_varchar(value) as value, + python_bvt_text(long_value) as long_value +from text_values order by id; + +create table binary_values (id int, var_value varbinary(8), blob_value blob); +insert into binary_values values + (1, unhex(''), unhex('')), + (2, unhex('00010203ff'), unhex('00ff10')), + (3, unhex('00010203ff060708'), unhex('00010203ff060708')), + (4, null, null); + +select id, hex(python_bvt_varbinary(var_value)) as var_value, + hex(python_bvt_blob(blob_value)) as blob_value +from binary_values order by id; + +create table json_values (id int, value json); +insert into json_values values + (1, '{}'), + (2, '{"a":1,"b":[true,null,"中"]}'), + (3, '1'), + (4, null); + +select id, python_bvt_json(value) as value +from json_values order by id; + +create table uuid_values (id int, value uuid); +insert into uuid_values values + (1, cast('00000000-0000-0000-0000-000000000000' as uuid)), + (2, cast('123e4567-e89b-12d3-a456-426614174000' as uuid)), + (3, null); + +select id, python_bvt_uuid(value) as value +from uuid_values order by id; + +drop function python_bvt_varchar(varchar(64)); +drop function python_bvt_text(text); +drop function python_bvt_varbinary(varbinary(8)); +drop function python_bvt_blob(blob); +drop function python_bvt_json(json); +drop function python_bvt_uuid(uuid); +drop table text_values; +drop table binary_values; +drop table json_values; +drop table uuid_values; +drop database udf_python_values_bvt; diff --git a/test/distributed/cases/udf_python/vector_mode.result b/test/distributed/cases/udf_python/vector_mode.result new file mode 100644 index 0000000000000..aed22dc97f8b7 --- /dev/null +++ b/test/distributed/cases/udf_python/vector_mode.result @@ -0,0 +1,47 @@ +drop database if exists udf_python_vector_bvt; +create database udf_python_vector_bvt; +use udf_python_vector_bvt; +create function python_bvt_vector (x int) returns int language python as 'python_bvt_vector = lambda ctx, values: __import__("pyarrow").array([-99 if value.as_py() is None else value.as_py() + 10 for value in values], type=__import__("pyarrow").int32())' handler 'python_bvt_vector' mode vector; +create function python_bvt_vector_strict (x int) returns int language python as 'python_bvt_vector_strict = lambda ctx, values: __import__("pyarrow").array([value.as_py() + 10 for value in values], type=__import__("pyarrow").int32())' handler 'python_bvt_vector_strict' mode vector returns null on null input; +create function python_bvt_zero_vector () returns int language python as 'python_bvt_zero_vector = lambda ctx: __import__("pyarrow").array([7] * ctx.num_rows, type=__import__("pyarrow").int32())' handler 'python_bvt_zero_vector' mode vector; +create function python_bvt_vecf32_identity (x vecf32(3)) returns vecf32(3) language python as 'python_bvt_vecf32_identity = lambda ctx, values: values' handler 'python_bvt_vecf32_identity' mode vector; +create function python_bvt_vecf64_identity (x vecf64(3)) returns vecf64(3) language python as 'python_bvt_vecf64_identity = lambda ctx, values: values' handler 'python_bvt_vecf64_identity' mode vector; +create table vector_values (id int, value int); +insert into vector_values values (1, 1), (2, null), (3, 2); +select id, python_bvt_vector(value) as called_result +from vector_values order by id; +➤ id[4,32,0] ¦ called_result[4,32,0] 𝄀 +1 ¦ 11 𝄀 +2 ¦ -99 𝄀 +3 ¦ 12 +select id, python_bvt_vector_strict(value) as strict_result +from vector_values order by id; +➤ id[4,32,0] ¦ strict_result[4,32,0] 𝄀 +1 ¦ 11 𝄀 +2 ¦ null 𝄀 +3 ¦ 12 +select id, python_bvt_zero_vector() as zero_result +from vector_values order by id; +➤ id[4,32,0] ¦ zero_result[4,32,0] 𝄀 +1 ¦ 7 𝄀 +2 ¦ 7 𝄀 +3 ¦ 7 +create table vector_array_values (id int, f32 vecf32(3), f64 vecf64(3)); +insert into vector_array_values values +(1, cast("[1,2,3]" as vecf32(3)), cast("[1.5,2.5,3.5]" as vecf64(3))), +(2, null, null); +select id, +python_bvt_vecf32_identity(f32) as f32_identity, +python_bvt_vecf64_identity(f64) as f64_identity +from vector_array_values order by id; +➤ id[4,32,0] ¦ f32_identity[12,3,0] ¦ f64_identity[12,3,0] 𝄀 +1 ¦ [1, 2, 3] ¦ [1.5, 2.5, 3.5] 𝄀 +2 ¦ null ¦ null +drop function python_bvt_vector(int); +drop function python_bvt_vector_strict(int); +drop function python_bvt_zero_vector(); +drop function python_bvt_vecf32_identity(vecf32(3)); +drop function python_bvt_vecf64_identity(vecf64(3)); +drop table vector_array_values; +drop table vector_values; +drop database udf_python_vector_bvt; diff --git a/test/distributed/cases/udf_python/vector_mode.sql b/test/distributed/cases/udf_python/vector_mode.sql new file mode 100644 index 0000000000000..e3b8d90525587 --- /dev/null +++ b/test/distributed/cases/udf_python/vector_mode.sql @@ -0,0 +1,46 @@ +-- Vector handlers receive one Arrow array per argument and return one Arrow +-- array with the same number of rows. Both NULL policies are exercised here. +drop database if exists udf_python_vector_bvt; +create database udf_python_vector_bvt; +use udf_python_vector_bvt; + +create function python_bvt_vector (x int) returns int language python as 'python_bvt_vector = lambda ctx, values: __import__("pyarrow").array([-99 if value.as_py() is None else value.as_py() + 10 for value in values], type=__import__("pyarrow").int32())' handler 'python_bvt_vector' mode vector; +create function python_bvt_vector_strict (x int) returns int language python as 'python_bvt_vector_strict = lambda ctx, values: __import__("pyarrow").array([value.as_py() + 10 for value in values], type=__import__("pyarrow").int32())' handler 'python_bvt_vector_strict' mode vector returns null on null input; +create function python_bvt_zero_vector () returns int language python as 'python_bvt_zero_vector = lambda ctx: __import__("pyarrow").array([7] * ctx.num_rows, type=__import__("pyarrow").int32())' handler 'python_bvt_zero_vector' mode vector; +create function python_bvt_vecf32_identity (x vecf32(3)) returns vecf32(3) language python as 'python_bvt_vecf32_identity = lambda ctx, values: values' handler 'python_bvt_vecf32_identity' mode vector; +create function python_bvt_vecf64_identity (x vecf64(3)) returns vecf64(3) language python as 'python_bvt_vecf64_identity = lambda ctx, values: values' handler 'python_bvt_vecf64_identity' mode vector; + +create table vector_values (id int, value int); +insert into vector_values values (1, 1), (2, null), (3, 2); + +-- CALLED ON NULL INPUT reaches the vector handler for the NULL row. +select id, python_bvt_vector(value) as called_result +from vector_values order by id; + +-- RETURNS NULL ON NULL INPUT compacts the selected rows and scatters NULL +-- back to the original row positions. +select id, python_bvt_vector_strict(value) as strict_result +from vector_values order by id; + +-- A zero-argument VECTOR routine gets its result shape from ctx.num_rows. +select id, python_bvt_zero_vector() as zero_result +from vector_values order by id; + +create table vector_array_values (id int, f32 vecf32(3), f64 vecf64(3)); +insert into vector_array_values values + (1, cast("[1,2,3]" as vecf32(3)), cast("[1.5,2.5,3.5]" as vecf64(3))), + (2, null, null); + +select id, + python_bvt_vecf32_identity(f32) as f32_identity, + python_bvt_vecf64_identity(f64) as f64_identity +from vector_array_values order by id; + +drop function python_bvt_vector(int); +drop function python_bvt_vector_strict(int); +drop function python_bvt_zero_vector(); +drop function python_bvt_vecf32_identity(vecf32(3)); +drop function python_bvt_vecf64_identity(vecf64(3)); +drop table vector_array_values; +drop table vector_values; +drop database udf_python_vector_bvt; diff --git a/test/distributed/cases/zz_accesscontrol/create_account.result b/test/distributed/cases/zz_accesscontrol/create_account.result index 667d2096b068c..683702a393f7f 100644 --- a/test/distributed/cases/zz_accesscontrol/create_account.result +++ b/test/distributed/cases/zz_accesscontrol/create_account.result @@ -169,6 +169,7 @@ mo_columns mo_configurations mo_database mo_foreign_keys +mo_function_revisions mo_iceberg_catalogs mo_iceberg_maintenance_jobs mo_iceberg_orphan_files