implement:implements full support for DECIMAL(M, D) with M up to 65 #23916
implement:implements full support for DECIMAL(M, D) with M up to 65 #23916robll-v1 wants to merge 6 commits intomatrixorigin:mainfrom
Conversation
Extend the DECIMAL(65,30)/decimal256 type to cover all core numeric operators and functions: - Arithmetic: +, -, *, /, %, div with scale-aware Decimal256.Add/Sub/Mul/Div/Mod methods - Aggregation: SUM, AVG, MIN, MAX with dedicated decimal256 exec paths - Math functions: ABS, SIGN, CEIL, FLOOR, ROUND, TRUNCATE - Predicates: =, !=, <, >, <=, >=, <=>, BETWEEN, IN, NOT IN - Conditional: CASE WHEN, COALESCE, IFF - Sorting: ORDER BY via pkg/sort - Implicit type coercion rules updated in type_check.go - Return type inference for all arithmetic operators updated in list_operator.go All affected unit tests pass. BVT cases updated and verified with mo-tester (10/10). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
|
There was a problem hiding this comment.
Pull request overview
This PR upgrades DECIMAL support to fully handle DECIMAL(M,D) up to M=65 by introducing/activating decimal256 across parsing, planning, execution, vector ops, functions/operators, aggregation, sorting, and frontend formatting/export paths (issue #23910).
Changes:
- Extend MySQL parser + planner/binder type selection to route
DECIMAL(39..65, D)toT_decimal256. - Add
decimal256support across casts, comparisons, arithmetic/operators, math functions, SUM/AVG/MIN/MAX, sorting, and vector encode/decode/minmax. - Add/update unit tests and distributed test expectations for the new type and behaviors.
Reviewed changes
Copilot reviewed 52 out of 52 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| test/distributed/cases/operator/is_operator.result | Updates expected output (including new result formatting) and removes the previous parser error for DECIMAL(65,30). |
| test/distributed/cases/function/func_datetime_unixtime.result | Adjusts expected behavior of FROM_UNIXTIME(huge_literal) to return null instead of an error. |
| test/distributed/cases/dtype/numeric.sql | Updates “out of range” numeric tests to exceed new max precision (66/67). |
| test/distributed/cases/dtype/numeric.result | Updates expected parser error messages to reflect new 0..65 range. |
| test/distributed/cases/dtype/decimal_256.test | Adds distributed BVT coverage for decimal(65,30) DDL/DML/functions/aggregations. |
| test/distributed/cases/dtype/decimal_256.result | Expected results for the new distributed decimal256 test. |
| test/distributed/cases/dtype/decimal.test | Updates “out of range” decimal tests to exceed new max precision (66/67). |
| test/distributed/cases/dtype/decimal.result | Updates expected parser error messages to reflect new 0..65 range. |
| pkg/vm/engine/tae/index/zm.go | Skips zonemap maintenance for decimal256 to avoid layout/flush issues. |
| pkg/sql/plan/make.go | Enables constant decimal expression typing to fall back to decimal256; adds default rewrite for empty decimal256 type. |
| pkg/sql/plan/function/type_check.go | Extends type coercion / fixed cast rules to include decimal256 and scale propagation rules. |
| pkg/sql/plan/function/operator_in.go | Adds decimal256 to generic IN/NOT IN operator type set. |
| pkg/sql/plan/function/operator_between.go | Adds BETWEEN / in-range support using CompareDecimal256. |
| pkg/sql/plan/function/operatorSet.go | Wires decimal256 into CASE/IFF/COALESCE and supported type sets; adds unary minus impl. |
| pkg/sql/plan/function/list_operator.go | Registers operator overloads/return-type rules for decimal256 (IN/NOT IN, arithmetic, unary, coalesce). |
| pkg/sql/plan/function/list_builtIn.go | Registers math built-ins and FROM_UNIXTIME overloads for decimal256. |
| pkg/sql/plan/function/list_agg.go | Enables decimal256 for SUM and MIN/MAX supported types. |
| pkg/sql/plan/function/func_unary.go | Implements ABS and SIGN for decimal256. |
| pkg/sql/plan/function/func_testcase.go | Extends function test harness to compare/build vectors for decimal256. |
| pkg/sql/plan/function/func_compare.go | Adds compare operator support and valueDec256Compare to handle scale alignment. |
| pkg/sql/plan/function/func_cast_test.go | Adds unit tests for casting to decimal256 from string and int64. |
| pkg/sql/plan/function/func_cast.go | Adds decimal256 casting support (to/from numeric/string/binary-ish types) and routing in NewCast. |
| pkg/sql/plan/function/func_binary_test.go | Adds FROM_UNIXTIME(decimal256) unit test. |
| pkg/sql/plan/function/func_binary.go | Adds decimal256 math funcs (ceil/floor/round/truncate) and FROM_UNIXTIME(decimal256) implementations. |
| pkg/sql/plan/function/decimal256_support_test.go | Adds broad unit coverage for decimal256 operators, coercion, arithmetic, conditional ops, math, etc. |
| pkg/sql/plan/function/baseTemplate.go | Extends decimal arithmetic template to include decimal256 and zero-checks. |
| pkg/sql/plan/function/arithmetic.go | Adds decimal256 operator support (plus/minus/mul/div/mod/div) and result-type driven handling. |
| pkg/sql/plan/build_util.go | Maps AST decimal types with precision > 38 to T_decimal256. |
| pkg/sql/plan/base_binder.go | Updates numeric literal binding to fall back to decimal256 parsing when decimal128 parsing fails; generalizes decimal check for floats. |
| pkg/sql/parsers/dialect/mysql/mysql_sql_test.go | Adds parser test for decimal(65,30). |
| pkg/sql/parsers/dialect/mysql/mysql_sql.y | Extends grammar to accept decimal precision up to 65 and to build appropriate internal type. |
| pkg/sql/parsers/dialect/mysql/mysql_sql.go | Regenerated parser output matching mysql_sql.y changes. |
| pkg/sql/colexec/aggexec/sumavg2_test.go | Extends SUM/AVG tests to include decimal256 vectors and validation. |
| pkg/sql/colexec/aggexec/sumavg2.go | Adds SUM/AVG execution support for decimal256 (including return type rules). |
| pkg/sql/colexec/aggexec/minmax2_test.go | Adds unit tests for MIN/MAX over decimal256. |
| pkg/sql/colexec/aggexec/minmax2.go | Adds MIN/MAX exec path for decimal256. |
| pkg/sort/sort_test.go | Adds unit test for sorting decimal256. |
| pkg/sort/sort.go | Adds decimal256 sort support. |
| pkg/frontend/util.go | Enables scalar expr value extraction for decimal256. |
| pkg/frontend/output.go | Adds decimal256 formatting for result output and column slice conversion. |
| pkg/frontend/mysql_cmd_executor.go | Maps engine decimal256 to MySQL DECIMAL type for column metadata. |
| pkg/frontend/export_parquet.go | Adds decimal256 conversion for Parquet export values. |
| pkg/frontend/export.go | Adds decimal256 formatting for export and JSON conversion. |
| pkg/container/vector/vector.go | Adds core vector operations for decimal256 (GetAny/Shrink/Shuffle/UnionAll/const set/String/minmax/sort/compact). |
| pkg/container/vector/tools.go | Adds append-bytes function support for decimal256. |
| pkg/container/vector/functionTools.go | Adds function result wrapper support for decimal256. |
| pkg/container/types/types.go | Extends DecimalWithFormat to include Decimal256. |
| pkg/container/types/encoding.go | Adds encode/decode and size constants for decimal256 values. |
| pkg/container/types/decimal_test.go | Adds parse/format test for decimal256 and negative-scale float conversion test. |
| pkg/container/types/decimal.go | Implements substantial decimal256 parsing/formatting, arithmetic helpers, trunc-scaling, float conversions, etc. |
| pkg/container/types/compare.go | Adds decimal256 asc/desc compare helpers. |
| pkg/compare/compare.go | Adds comparator construction + copy function for decimal256. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
I fixed the clear issue-level gaps in this round:
I also added focused tests for both changes. ZoneMap bypass for decimal256 is a real performance limitation, but I did not address it in this patch. The The cast-gap report is only partially applicable now. I fixed the missing decimal256 integral cast paths Decimal256 Format() using big.Int is a valid performance concern. I agree it is worth optimizing, but I I do not see evidence that Decimal128.Mod128 behavior changed in this branch. The branch adds decimal256- FROM_UNIXTIME behavior did change for very large numeric literals after decimal256 widened the literal There is still duplicated decimal256 code across the decimal64/128/256 paths. That is real technical debt, Some result-file churn in this branch is broader than the core decimal256 behavior change. I agree that is |
What type of PR is this?
Which issue(s) this PR fixes:
issue #23910
What this PR does / why we need it:
This PR implements full support for DECIMAL(M, D) with M up to 65 (backed by the decimal256 type), bringing it from a skeletal type stub to a production-usable numeric type.
What was added across two commits
Commit 1 — d9a6e16: Basic query path
Commit 2 — fa7995f: Complete operator and function support
Testing
Known Risks and Limitations
In pkg/vm/engine/tae/index/zm.go, the UpdateZM and BatchUpdateZM paths skip T_decimal256 entirely. The raw Decimal256 value is 32 bytes, which does not fit the current fixed-layout zonemap encoding. This means:
RANK, ROW_NUMBER, LAG, LEAD, FIRST_VALUE, LAST_VALUE etc. have not been extended for T_decimal256. Using decimal256 columns in window functions will return an unsupported-type error.
These are edge-case operations on decimal types in general and are not implemented for decimal256.
These convenience functions are not wired for T_decimal256 and will return unsupported errors if called with decimal256 arguments.
AVG return type for decimal256 is capped at scale = min(input_scale + 6, 30) consistent with the existing decimal128 policy. This is a known approximation, not a regression.