Skip to content

[feature](datatype) Add UUID data type support - #67627

Open
jacktengg wants to merge 35 commits into
apache:masterfrom
jacktengg:uuid
Open

jacktengg wants to merge 35 commits into
apache:masterfrom
jacktengg:uuid

Conversation

@jacktengg

@jacktengg jacktengg commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: close #xxx

Related PR: #xxx

Problem Summary:
Document:
apache/doris-website#4131
apache/doris-website#4166

Doris does not have a native UUID SQL and storage type, so UUID values must be stored as strings and cannot use a fixed-width representation or UUID-aware generation and version functions. Add a native 128-bit UUID type across FE, BE, IDL, storage, serialization, expressions, runtime filters, external and JNI bridges, and schema metadata. Accept canonical and compact hexadecimal input, normalize output to lowercase canonical form, preserve unsigned canonical ordering, and add native UUID v4 and v7 generation and version inspection while keeping the existing string-returning uuid() behavior compatible.

Release note

None

Check List (For Author)

  • Test

    • Regression test
    • Unit Test
    • Manual test (add detailed scripts or steps below)
    • No need to test or manual test. Explain why:
      • This is a refactor/code format and no logic has been changed.
      • Previous test can cover this change.
      • No code files have been changed.
      • Other reason
  • Behavior changed:

    • No.
    • Yes.
  • Does this need documentation?

    • No.
    • Yes.

Check List (For Reviewer who merge this PR)

  • Confirm the release note
  • Confirm test cases
  • Confirm document
  • Add branch pick label

@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

jacktengg added a commit to jacktengg/incubator-doris that referenced this pull request Sep 8, 2026
### What problem does this PR solve?

Related PR: apache#67627

Problem Summary: UUID dynamic defaults were parsed as literals when partial updates inserted new keys, while ADD COLUMN evaluated one UUID for every existing row. Parquet logical UUID values had no native materialization path, and encoded Variant UUID and nested JSON UUID casts lost valid values. Share batched UUID generation across SQL and all partial-update fill paths, reject volatile UUID defaults for ADD COLUMN, decode Parquet UUID values and dictionaries in canonical byte order, and handle UUID in encoded Variant and JSONB casts.

### Release note

Fix UUID defaults for partial-update inserts, Parquet UUID reading, and UUID casts from encoded Variant and nested JSON. ADD COLUMN now rejects UUID dynamic defaults; UUID literal defaults remain supported.

### Check List (For Author)

- Test: ASAN BE/FE builds; 106 BE unit tests; 4 FE unit tests; 3 UUID regression suites; generated regression outputs; clang-format v16, FE Checkstyle, and build hygiene checks. clang-tidy was attempted but remains blocked by pre-existing unmatched NOLINTEND and toolchain header errors; details are in review-docs/pr-67627-review-fixes.zh.md.
    - Regression test / Unit Test
- Behavior changed: Yes, correct missing UUID values and reject unstable ADD COLUMN defaults as described above.
- Does this need documentation: No, fixes correctness gaps in the UUID feature under review.
jacktengg added a commit to jacktengg/incubator-doris that referenced this pull request Sep 8, 2026
…ite paths

### What problem does this PR solve?

Issue Number: None

Related PR: apache#67627

Problem Summary: Partial updates that omit UUID_V4/UUID_V7 columns previously
created independent random values on each replica. Persist the shared load ID
and derive UUID defaults from the load, primary key and column identity so
flush, publish and recovery produce consistent values despite row reordering.
Keep native UUID identity in Variant typed encoding, storage-cell assembly and
subcolumn materialization, and add the missing FE protobuf mapping for RPC UDF
UUID input and output signatures. Legacy metadata without a load ID explicitly
fails when UUID dynamic defaults are required; literal defaults remain usable.
Variant root scalars retain the existing V1-compatible JSONB storage policy.

### Release note

Fix inconsistent UUID defaults across partial-update replicas, preserve native
UUID identity in Variant adapters and subcolumns, and allow UUID RPC UDF signatures.

### Check List (For Author)

- Test: ASAN BE/FE builds; 58 BE unit tests; 1 FE RPC signature unit test;
  5 UUID regression suites including three replicas across 8 write configurations.
  clang-format v16, FE Checkstyle and build hygiene passed. clang-tidy was run
  but is blocked by the existing unmatched NOLINTEND in be/src/core/types.h:577
  and baseline diagnostics.
    - Regression test / Unit Test
- Behavior changed: Yes, replica-stable UUID defaults and native Variant UUID identity;
  RPC UDF creation accepts UUID signatures.
- Does this need documentation: No
jacktengg added a commit to jacktengg/incubator-doris that referenced this pull request Sep 8, 2026
### What problem does this PR solve?

Issue Number: N/A

Related PR: apache#67627

Problem Summary: UUID support added COLUMN_TYPE_UUID to the deprecated
PColumnType enum, but no producer or consumer uses this value. IN and
MinMax runtime filter serialization writes COLUMN_TYPE_BOOL solely to
populate the deprecated required fields. Remove the unused enum member
without changing existing field numbers or runtime UUID serialization.

### Release note

None

### Check List (For Author)

- Test: Manual test: repository reference search, protoc descriptor generation,
  and git diff --check passed. No runtime tests needed for an unused enum removal.
- Behavior changed: No
- Does this need documentation: No
@jacktengg

Copy link
Copy Markdown
Contributor Author

Local pipeline review — ✅ PASS

schema: doris-repo-review/v1
status: PASS
pr: apache/doris#67627
commit: 864e5448e2236230e662bcddffc10d48acd5fc24
base: 9957987d5bf43fa6a33aa59918435fed65e2912a
reviewed_at: 2026-09-08T18:39+08:00
reviewer: jacktengg
model: gpt-5.6-sol
effort: xhigh
findings: {blocker: 0, major: 0, minor: 0, nit: 0}
rounds: 1
converged: true

Notes for maintainers

None.

Reviewed locally with the doris-repo-review pipeline. Repository policy may accept this receipt for the matching commit; it is not a human Apache approval.

jacktengg added a commit to jacktengg/incubator-doris that referenced this pull request Sep 9, 2026
…ization

### What problem does this PR solve?

Issue Number: N/A

Related PR: apache#67627

Problem Summary: UUID declarations with length or precision parameters were silently accepted. Queries rewritten to multi_distinct_count(UUID) reached an unregistered BE implementation, and UUID MIN/MAX aggregate-storage columns were rejected by FE despite existing BE support. Nested Hive Text UUID values also inherited JSON quoting. Reject unsupported type parameters, register exact UUID distinct aggregation, allow the supported storage aggregates, and separate Hive Text from JSON serialization. Reuse the existing compact-binary writer and preserve its UUID tag and 16-byte payload.

Add FE, BE, JNI and regression coverage for type identity, metadata, NULL/Const columns, serialization, distributed operators, actual spill, storage models, compaction, index formats, schema changes, MySQL/Flight clients, Java UDF/UDAF, file round trips and explicit restrictions. Record all 118 checklist items and distinguish local validation from deployment scenarios still requiring external environments.

### Release note

UUID now rejects length/precision parameters, supports exact multi-distinct aggregation and MIN/MAX aggregate-storage columns, and emits correct unquoted UUID elements in Hive Text.

### Check List (For Author)

- Test: Unit Test / Regression test / Manual test
    - Standard ASAN BE/FE builds; 92 UUID BE tests and 70 FE/JNI tests passed.
    - All 15 UUID regression suites passed with generated expected output, including verified physical spill and index/compaction paths.
    - Independent PyArrow checks for Parquet/ORC OUTFILE and Parquet EXPORT passed; FE plus three BE restart preserved schema and query output.
    - clang-format 16 and header hygiene passed. clang-tidy remains blocked by the existing unmatched NOLINTEND in core/types.h and reports existing JSONB-test cognitive complexity.
    - Cloud, mixed-version deployment and external catalog end-to-end acceptance were not performed; details are recorded in docs/uuid-type-completeness.md.
- Behavior changed: Yes (UUID parameter validation, distinct/storage aggregates, and Hive Text output)
- Does this need documentation: Yes (docs/uuid-type-completeness.md in this commit)
jacktengg added a commit to jacktengg/incubator-doris that referenced this pull request Sep 9, 2026
…imizations

### What problem does this PR solve?

Related PR: apache#67627

Problem Summary: UUID regression suites mixed unrelated features, while result-only
checks could pass without partition pruning, bucket pruning, scanner predicates,
or indexes actually filtering data. Split the existing suites by feature and add
isolated positive/zero profile checks, planner assertions, native UUID Parquet
fixtures, invalid-load atomicity, statistics readback, aggregation phases, and
cross-batch windows. Map all 118 datatype checklist entries to concrete evidence
and record the generic composite-range boundary pruning limitation and remaining
external-environment coverage gaps.

### Release note

None

### Check List (For Author)

- Test: Regression test / Manual test
    - 54 UUID suites passed on one FE and three ASAN BEs with random order and parallelism 3; zero failures or skips
    - Generated golden files with run-regression-test.sh and reran without generation flags
    - Audited preserved golden blocks, independently derived scanner aggregates, and checked Parquet/ORC/EXPORT schema and values with PyArrow 21.0.0
    - Source whitespace checks passed; retained the regression generator's blank-line separators in .out files
- Behavior changed: No (test coverage and documentation only)
- Does this need documentation: Yes (feature coverage index and existing completeness document updated in this commit)
jacktengg added a commit to jacktengg/incubator-doris that referenced this pull request Sep 9, 2026
Issue Number: None

Related PR: apache#67627

Problem Summary: UUID regression cases did not systematically cover special
and ordinary values across constant, mixed and column arguments with FE
folding, BE folding and folding disabled. Add eight functional matrices and
a reusable fixture, including nullable columns, container lambdas, generators,
aggregate states, parameter constraints and checks of nondeterministic results.
Register UUID in the histogram and map_agg_v2 factories. Refresh MERGE's nested
arguments after state rewrites so folding does not leave stale result nullability.
Add focused BE/FE unit tests and document coverage and applicable restrictions.

Support UUID inputs to HISTOGRAM and UUID keys in MAP_AGG/MAP_AGG_V2. Fix
aggregate-state MERGE queries whose argument nullability changes during folding.

- Test: Regression test / Unit Test / Manual test
    - 65 UUID regression suites and 3 existing aggregate-state suites passed.
    - 39 FE unit tests and 5 BE unit tests passed.
    - FE and ASAN BE builds, Checkstyle, C++ formatting and build hygiene passed.
    - Independently audited 93,231 results and folding-mode consistency across 4,397 generated result blocks.
    - clang-tidy attempted; blocked by the existing unmatched NOLINTEND in be/src/core/types.h:577.
- Behavior changed: Yes (UUID aggregate support and correct MERGE result metadata)
- Does this need documentation: Yes (docs/uuid-expression-matrix.md in this commit)
@jacktengg

Copy link
Copy Markdown
Contributor Author

Local pipeline review — ✅ PASS

schema: doris-repo-review/v1
status: PASS
pr: apache/doris#67627
commit: ea16e060372bbdfa1ebbf484523ba8acfd113348
base: 3763638e6c8e3ebbc1b7079266f0d97213f0278d
reviewed_at: 2026-09-09T15:46+08:00
reviewer: jacktengg
model: gpt-6-astra
effort: xhigh
findings: {blocker: 0, major: 0, minor: 0, nit: 0}
rounds: 1
converged: true

Notes for maintainers

  • Read-only review: all 332 changed paths covered; no builds or Doris tests were run.
  • docs/uuid-expression-matrix.md:66 — the pre-existing generic MERGE issue remains outside this UUID change; explicit NULLABLE covers nullable aggregate-state signatures only.

Reviewed locally with the doris-repo-review pipeline. Repository policy may accept this receipt for the matching commit; it is not a human Apache approval.

@jacktengg

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 47.24% (77/163) 🎉
Increment coverage report
Complete coverage report

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 16830 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit ea0affdbc6175e9f7144d2fa8b65cdf412c9dea0, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17638	3019	3007	3007
q2	2069	258	240	240
q3	10317	906	509	509
q4	4680	248	200	200
q5	7684	542	386	386
q6	138	121	97	97
q7	533	513	386	386
q8	9239	945	932	932
q9	3473	2356	2399	2356
q10	6504	884	755	755
q11	411	202	183	183
q12	611	253	200	200
q13	18147	1523	1157	1157
q14	155	146	141	141
q15	q16	438	398	375	375
q17	1348	944	773	773
q18	3063	2249	2250	2249
q19	1140	862	754	754
q20	392	290	201	201
q21	5206	1692	1939	1692
q22	332	274	237	237
Total cold run time: 93518 ms
Total hot run time: 16830 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3350	3290	3279	3279
q2	501	394	370	370
q3	2259	2304	2163	2163
q4	1184	1162	869	869
q5	2189	2137	2089	2089
q6	168	121	88	88
q7	1020	936	836	836
q8	1581	1385	1384	1384
q9	3133	3110	3056	3056
q10	1858	1777	1620	1620
q11	350	268	247	247
q12	456	433	354	354
q13	1469	1555	1166	1166
q14	180	184	170	170
q15	q16	390	391	354	354
q17	3567	3296	3219	3219
q18	4849	4382	4757	4382
q19	841	816	916	816
q20	1034	972	814	814
q21	3852	3116	3364	3116
q22	400	341	326	326
Total cold run time: 34631 ms
Total hot run time: 30718 ms

### What problem does this PR solve?

Issue Number: None

Related PR: apache#67627

Problem Summary: UUID external paths had inconsistent Parquet text and binary carriers, unsafe ClickHouse range pushdown, missing CSV schema support, and missing Iceberg Parquet UUID logical annotations. Preserve Iceberg binary values and statistics, align ordinary Parquet text scans and cache keys, retain ClickHouse UUID ranges locally, and emit interoperable Iceberg UUID schemas. Add source-specific regression matrices and independent Iceberg read-back checks.

### Release note

Fix UUID CSV schema support, Parquet scanner consistency, ClickHouse range filtering, and Iceberg Parquet UUID writes.

### Check List (For Author)

- Test: Unit Test: 37 FE and 226 BE tests passed; Regression test: 11 suites passed with no skips; 320 generated result blocks independently checked. FE and BE ASAN builds, Checkstyle, clang-format 16 and build hygiene passed. clang-tidy omitted as requested.
- Behavior changed: Yes; UUID external values, range filtering and Iceberg file annotations follow the documented carrier semantics.
- Does this need documentation: Yes; external_table-current-status-0910.md saved in the requested local documentation directory.
Issue Number: None

Related PR: apache#67627

Problem Summary: Native UUID lacked the requested parsing fallback, and UUIDv7 time conversion functions.
Add FE signatures and deterministic folding together with BE constant, nullable and column
execution.
Generate UUIDv7 values per row from the supplied session-local datetime, including
counter overflow continuity, and decode timestamps with an optional constant timezone.
Extend UUID regression matrices with nested casts, subqueries, grouping sets, NULL
ordering, pattern predicates and unary expression contexts. Keep the pre-existing
empty-REGEXP STRING discrepancy outside this change and test UUID/text parity for it.

Add dateTimeToUUIDv7, UUIDv7ToDateTime, toUUIDOrZero, toUUIDOrNull,
and toUUIDOrDefault for UUID, with underscore aliases.
Existing UUID_TO_INT/INT_TO_UUID behavior is unchanged.

- Test: Unit Test / Regression test / Manual test
    - FE: 42 tests passed via run-fe-ut.sh.
    - BE: 8 UUID tests passed via run-be-ut.sh, including overflow continuation.
    - Regression: 19 new/existing UUID suites passed; the three new suites
      were verified again after the final BE changes, then the expression and
      conversion suites reverified after the matrix helper change. All 1195 generated
      result blocks were checked against an independent oracle (93 check empty-REGEXP
      text parity after query execution).
    - FE and ASAN BE builds, FE Checkstyle, scoped clang-format and build hygiene passed.
    - clang-tidy was not run as requested.
Issue Number: None

Related PR: apache#67627

Problem Summary: The new native UUID type still formatted values as text at
Arrow and Python boundaries. Represent it as the standard arrow.uuid extension
over canonical big-endian fixed_size_binary(16), including nested containers,
Flight schema exchange, and Python scalar, vector, aggregate and table functions.
Build extension-aware empty and control batches instead of unsupported extension
builders. Write UUID Parquet annotations and ORC binary values with logical type
attributes, including FE-provided OUTFILE schemas and both ORC readers. Preserve
ordinary STRING, public textual interfaces, and legacy external STRING mappings.
This reduces the uncompressed UUID value payload from 36 to 16 bytes without
claiming a measured end-to-end performance improvement.

Native UUID uses binary Arrow/Flight buffers and uuid.UUID Python UDF objects.
Parquet and ORC exports preserve 16-byte UUID payloads and UUID type metadata.
Existing SQL STRING values and MySQL/JSON/CSV text behavior are unchanged.

- Test: ASAN BE+FE build; 135 BE unit tests; 13 FE unit tests; 14 regression suites;
  independent Parquet/ORC schema and byte inspection; clang-format 16 and build
  hygiene checks. clang-tidy remains blocked by pre-existing diagnostics including
  an unmatched NOLINTEND; locally suppress GTest assertion-expansion complexity.
- Behavior changed: Yes, native UUID binary interchange and Python object mapping.
- Does this need documentation: Yes, updated the requested local document
  /mnt/disk2/tengjianping/docs/uuid/uuid-binary-proto.md.
Issue Number: None

Related PR: apache#67627

Problem Summary: UUID SELECT INTO OUTFILE tests fell back to S3 when custom local path settings were absent. Make CSV, Parquet, ORC and nested-map round trips local-only, following the existing OUTFILE test configuration gate. Discover the BE secure file directory, export into unique local temporary directories, read through LOCAL TVF, and clean up files while retaining tables for debugging. Preserve schema inference and legacy ORC reader checks without requiring UUID-specific path settings.

None

- Test: Regression test
    - run-regression-test.sh --run --conf output/uuid-binary-cluster/regression-conf.groovy -d datatype_p0/uuid -s test_uuid_csv_roundtrip,test_uuid_parquet_roundtrip,test_uuid_orc_roundtrip,test_uuid_file_maps: 4 passed, 0 failed, 0 skipped
    - git diff --check: passed
- Behavior changed: No (test-only change)
- Does this need documentation: No
### What problem does this PR solve?

Issue Number: N/A

Related PR: N/A

Problem Summary: Reading an ORC UUID column with enable_mapping_varbinary=true
fails with the V2 scanner: schema inference produces VARBINARY, but the ORC
reader ignores the option and exposes UUID, causing an unsupported UUID to
VARBINARY cast. Pass the existing option through both the data-file and Iceberg
delete-file reader factories and prioritize it over the UUID annotation.
Implement native VARBINARY ORC decoding, including direct and encoded string
batches, so the mapped column can actually be materialized without text
conversion. Preserve original bytes, NULLs, selected rows and nested types.

### Release note

Fix ORC reads with enable_mapping_varbinary=true in the V2 file scanner,
including UUID-annotated fields and Iceberg delete files.

### Check List (For Author)

- Test: Regression test / Unit Test / Manual test
    - Reproduce the unsupported UUID to VARBINARY cast before the fix
    - ASAN BE build via build.sh --be -j16
    - 188 BE unit tests pass for ORC readers, VARBINARY SerDe and Iceberg UUID/binary paths
    - 5 local UUID OUTFILE/LOCAL TVF regression suites pass; no remote storage
    - Generate the new golden output with the regression runner and verify all four scanner/mapping combinations
    - clang-format v16 and build hygiene checks pass
    - clang-tidy attempted; blocked by existing unmatched NOLINTEND and missing stddef.h diagnostics
- Behavior changed: Yes (honor the existing ORC binary mapping option in V2; default mapping is unchanged)
- Does this need documentation: No (restore the existing option's semantics)
### What problem does this PR solve?

Issue Number: N/A

Related PR: N/A

Problem Summary: The UUID array and scalar matrix golden files exceed the
repository's 1 MiB added-file limit at 1,748,503 and 1,564,821 bytes. Move array
element/capture/construction cases and scalar ternary cases into independent
suites with their own tables and golden files. Reuse the existing matrix runner
to preserve every input, constant/column mask, nullability variant and FE/BE/
runtime folding mode. Keep complete row-level oracles instead of hashes or
sampling. All four resulting fixtures are below 1 MiB.

### Release note

None

### Check List (For Author)

- Test: Regression test / Manual test
    - Generate all four golden files with run-regression-test.sh -forceGenOut
    - Re-run all four suites normally: 4 passed, 0 failed, 0 skipped
    - Compare all 2,442 original tagged result blocks and ordered row contents against the split fixtures: identical
    - Check fixture sizes: 839,412 / 909,186 / 893,071 / 671,845 bytes, all below 1,048,576
    - Check patch whitespace; allow the regression generator's final blank lines
- Behavior changed: No (test organization only; query coverage and expected values are unchanged)
- Does this need documentation: No
### What problem does this PR solve?

Issue Number: N/A

Related PR: N/A

Problem Summary: Rebasing UUID support onto the JNI plugin isolation refactor
moves the production data-plane classes into jni-spi, but leaves the new UUID
tests under the removed java-common module. Those tests would no longer run,
and their old package imports and JUnit 4 dependency are incompatible with the
new modules. Move the vector and byte-order tests to jni-spi using JUnit 5,
and keep the Java UDF candidate-type assertion in the java-udf module so the
shared SPI retains its zero-dependency boundary.

The UUID type and accessors also extend the newly frozen JNI plugin surface.
Refresh its baseline from JniPluginSurfaceTest output, bump the shared API
major to 4.0 as required by the new contract, and document the UUID type string
and fixed-width off-heap encoding.

### Release note

UUID-enabled JNI plugins declare API version 4.0 and require a matching shared
JNI SPI. UUID value semantics and byte encoding are unchanged.

### Check List (For Author)

- Test: Unit Test / Manual test
    - run-fe-ut.sh: 58 targeted tests pass across UUID literals/types, vector and byte conversion, SPI surface/version, plugin runtime and Java UDF integration
    - Checkstyle passes for jni-spi and java-udf
    - BE build hygiene passes
    - Verify origin/master is an ancestor, no conflict markers remain, and the original untracked-file inventory is unchanged
    - Full BE build and regression tests not run
- Behavior changed: Yes (JNI plugin API major becomes 4.0; UUID semantics are unchanged)
- Does this need documentation: Yes (fe/be-java-extensions/jni-spi/PROTOCOL.md)
### What problem does this PR solve?

Issue Number: N/A

Problem Summary: Reusing a server-prepared short-circuit query replaces the
cached UUID predicate with a StringLiteral from the MySQL parameter. Tablet
pruning then hashes UTF-8 text instead of the UUID's binary representation,
so existing rows can be missed. Retyping the key during RPC serialization is
too late because the tablet has already been selected. Reuse the existing
key-literal conversion before updating scan conjuncts, keeping pruning and
lookup keys consistent without disabling the short-circuit path.

### Release note

Fix missing rows when reusing prepared point queries on UUID keys.

### Check List (For Author)

- Test: Regression test / Unit Test / Manual test
    - 22 focused FE unit tests passed, including four new rebinding tests.
    - Five regression suites passed; 40 generated UUID prepared results verified.
    - The supplied reproducer passed all four cases on an isolated cluster.
    - FE build and Checkstyle passed; golden results generated by the regression runner.
- Behavior changed: Yes, prepared UUID point queries route to the correct tablet.
- Does this need documentation: No, restores existing query semantics.
### What problem does this PR solve?

Issue Number: N/A

Problem Summary: The newly introduced UUID type transports expression and
partition-boundary literals as text, requiring BE parsing and formatting.
Replace the UUID Thrift string with required high and low i64 fields and
update all FE and BE producers and consumers. Preserve all 128 bits by
joining unsigned halves, including values whose signed Thrift halves are
negative. Keep SQL text conversion and persisted UUID representations
unchanged. Directly replace the branch-local protocol without a legacy
string fallback.

### Release note

UUID literal transport now uses two Thrift integers. FE and BE must be
updated together; the previous UUID string-literal protocol is incompatible.
SQL UUID semantics and stored data formats are unchanged.

### Check List (For Author)

- Test: Regression test / Unit Test / Manual test
    - 11 focused FE unit tests and 23 ASAN BE unit tests passed.
    - Ten regression suites passed, including UUID folding, partitioning,
      runtime filtering and both UUID and existing-type prepared point queries.
    - All four supplied prepared-query reproduction cases passed.
    - New golden results were generated by the regression runner and verified.
    - FE and ASAN BE builds, Checkstyle, clang-format 16, header hygiene and
      git diff whitespace checks passed.
    - Clang-tidy was run; its gate remains blocked by the pre-existing unmatched
      NOLINTEND in be/src/core/types.h. New test complexity and failed-fixture
      initialization diagnostics were fixed; final changed-line diagnostics are zero.
- Behavior changed: Yes, UUID literal wire encoding changes; SQL behavior does not.
- Does this need documentation: No, internal branch-local wire representation only.
### What problem does this PR solve?

Issue Number: N/A

Problem Summary: The BE implementation of is_uuid accepted any 36-character
string whose characters are hex digits, dashes at the separator positions or a
mix of both, because it only rejected non-hex characters that were not located
at the four separator positions. A 36-character value consisting of hex digits
only, such as 36 zeros, therefore returned true even though it is neither the
32-character dash-less form nor the canonical 8-4-4-4-12 form. The FE constant
folding path already rejected that value, so is_uuid('000...0') and is_uuid(v)
for the same text disagreed. Require the four separators to be dashes at the
fixed positions and hex digits everywhere else, which matches the FE
implementation and the documented formats.

### Release note

is_uuid now returns false for 36-character UUID strings that miss the four
fixed dashes, consistent with constant folding and the documented input
formats. Valid 32-character, 36-character and braced 38-character forms are
unchanged.

### Check List (For Author)

- Test: Regression test / Manual test
    - New regression suite test_uuid_is_uuid passed against the worktree cluster;
      it covers the real column path and the literal path with constant folding
      enabled and disabled (debug_skip_fold_constant), and its golden .out file
      was generated by the regression runner.
    - Cases for the affected inputs were added to the existing BE unit test
      function_uuid_test.function_is_uuid_test. They were not executed here
      because building the BE unit test binary was out of scope for this change.
    - Manual SQL verification on the worktree cluster: the reported 36-character
      dash-less value returns false on both the column and literal paths, while
      the 32-character dash-less and canonical 36-character forms still return true.
- Behavior changed: Yes, 36-character UUID strings without the fixed dashes now
  report false instead of true.
- Does this need documentation: No
Issue Number: N/A

Related PR: N/A

Problem Summary: Creating a UUID RANGE table with dynamic partition properties
previously succeeded with no partitions. The scheduler caught the unsupported
column type error, recorded ERROR, and left the table unable to accept writes.
Validate the partition column with the scheduler's existing getPartitionFormat
check at the shared dynamic property analysis entry point, covering CREATE and
ALTER before saving metadata. Limit the check to dynamic properties so ordinary
UUID RANGE tables remain valid, and skip the new check during log replay.
Add utility tests and regression coverage for rejected UUID DDL, unchanged
static UUID tables, replay compatibility, and working DATE dynamic partitions.

Reject dynamic partition CREATE and ALTER statements with unsupported partition
column types synchronously instead of leaving tables in scheduler ERROR state.

- Test: Regression test / Unit Test / Manual test
    - 55 FE unit tests in DynamicPartitionUtilTest and DynamicPartitionTableTest
    - Four UUID and three existing dynamic partition regression suites passed
    - Generated the new golden file with the regression runner and compared it
    - Reproduced the pre-fix ERROR/empty-partition behavior on an isolated cluster
    - Standard FE build with Checkstyle and source whitespace checks passed
- Behavior changed: Yes, unsupported dynamic partition types fail during DDL
- Does this need documentation: No, enforce the existing supported type contract
### What problem does this PR solve?

Issue Number: None

Related PR: None

Problem Summary: Defer UUID partition keys until a concrete use case requires
support. Reject UUID columns in RANGE and LIST partitions, including automatic
LIST partitions, through the existing partition type validation. Remove the
UUID partition successor and BE partition boundary handling. Replace the
positive UUID partition suites with rejection coverage and a date-partitioned
table that stores and distributes UUID values. Preserve UUID hash distribution
and runtime-filter expression result types.

### Release note

UUID columns can no longer be used as RANGE or LIST partition keys. UUID hash
distribution remains supported.

### Check List (For Author)

- Test: Unit Test / Regression test
    - Build: ./build.sh --be --fe -j 16 (ASAN; FE Checkstyle passed)
    - FE unit tests: 55 passed across partition metadata, UUID literals, and point queries
    - BE unit tests: 17 passed across tablet sink partitioning and runtime partition pruning
    - Regression: test_uuid_partition, test_uuid_bucket_pruning,
      test_uuid_runtime_bucket_pruning, test_uuid_comparison, and
      test_uuid_type_contract passed; new output generated by the regression runner
    - clang-format v16 and build hygiene checks passed
    - clang-tidy attempted with the toolchain resource path; blocked by the
      pre-existing unmatched NOLINTEND in be/src/core/types.h:577. No diagnostics
      were reported on added or modified lines.
- Behavior changed: Yes, reject UUID partition keys
- Does this need documentation: No
Issue Number: None

Related PR: None

Problem Summary: UUID casts and text serializers previously allocated a temporary
36-character string for each value and copied it into the destination column.
Formatting also walked every output position, tested for separators, and shifted
a 128-bit integer for each hexadecimal digit. Add a caller-buffer formatter that
uses the existing hexadecimal byte-pair lookup and fixed 64-bit groups, and let
CastToString write directly into BufferWritable. The string-returning API shares
the same formatter. Numeric and network-byte conversions are already independent
of host endianness; document that contract and cover it with fixed vectors,
unaligned buffers, boundary values, and 4096 comparisons against Boost.

Add SQL coverage for stored nullable UUIDs, nested serializers and 4096 rows of
byte-pair formatting. Canonical text and serialized representations are unchanged.
No throughput claim is made: the benchmark target requires RELEASE, while this
change was built and tested with ASAN.

Reduce temporary allocations and per-digit work when formatting UUID values.

- Test: ASAN BE build via build.sh --be -j 16; 35 BE unit tests via run-be-ut.sh;
  five regression suites via run-regression-test.sh (test_uuid_format,
  test_uuid_cast, test_uuid_json, test_uuid_nested_types, test_uuid_type_semantics).
  New expected output was generated and verified by the regression runner.
  clang-format 16 and build hygiene checks passed. clang-tidy was run and has no
  diagnostics on changed lines, but its full check remains blocked by the existing
  unmatched NOLINTEND in core/types.h:577; it also reports an existing UUID
  generation comparison outside the changed lines.
- Behavior changed: No
- Does this need documentation: No
### What problem does this PR solve?

Issue Number: N/A

Related PR: N/A

Problem Summary: When projection pruning leaves no required scan slots,
PhysicalPlanTranslator retains the smallest available slot. UUID was missing
from the fixed-width priority group, so string and complex slots were preferred
over a 16-byte UUID slot. Include Type.isUuid() in that group and preserve the
existing size comparison within it. Add comparator coverage against string and
complex types, fixed-width size ordering, and a COUNT(*) scan-slot plan case.

### Release note

Prefer UUID over string and complex columns when choosing a fallback scan slot
for COUNT(*) and other queries with no required scan columns.

### Check List (For Author)

- Test: Unit Test
    - run-fe-ut.sh --run org.apache.doris.nereids.glue.translator.CountStarSmallestSlotTest: all 19 tests passed; the two new UUID tests failed before the fix.
    - build.sh --fe -j8 with FE_MAVEN_THREADS=8 and DISABLE_BE_JAVA_EXTENSIONS=ON: passed, including FE Checkstyle.
    - git diff --check: passed.
- Behavior changed: Yes (fallback scan-slot selection now classifies UUID with fixed-width types; query results are unchanged).
- Does this need documentation: No
Issue Number: N/A

Related PR: apache#68246, apache#67805

Problem Summary: The UUID aggregate matrix still expected an empty array from
TOPN_ARRAY(uuid, 100, 0), reflecting the old behavior that discarded every
candidate while serializing a zero-capacity partial state. Current BE code
treats non-positive expansion rates as unlimited candidate retention, so the
test fails on a current BE while passing against an older local binary.

Regenerate the expected output using the regression runner, name the third
argument as an expansion rate, sort the returned arrays, and cover a negative
rate in the existing phase/folding/input matrix. Replace the obsolete
COLLECT_SET column-limit matrix with an expected-error case, matching the FE
requirement that the limit argument is constant.

None

- Test: Regression test and Manual test
    - Reproduced unary_p1_fe_c_1 against the unchanged expected output after rebuilding the current BE; the old local BE passed the old test.
    - run-regression-test.sh --run -d datatype_p0/uuid -s test_uuid_aggregate_matrix -forceGenOut: passed.
    - run-regression-test.sh --run -d datatype_p0/uuid,nereids_function_p0/agg_function/topn -s test_uuid_aggregate_matrix,topn_unlimited: 2 suites passed.
    - Verified 66 unary matrix queries against default TOPN results and confirmed all 584 other retained output blocks are unchanged.
    - build.sh --be -j48 (ASAN) and git diff --check: passed.
- Behavior changed: No (test-only alignment with existing aggregate parameter semantics).
- Does this need documentation: No
@hello-stephen

Copy link
Copy Markdown
Contributor

run buildall

@jacktengg

Copy link
Copy Markdown
Contributor Author

/review

@hello-stephen

Copy link
Copy Markdown
Contributor

Cloud UT Coverage Report

Increment line coverage 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 77.54% (2064/2662)
Line Coverage 65.78% (37948/57686)
Region Coverage 53.20% (35545/66816)
Branch Coverage 56.56% (11420/20190)

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static review of UUID support on head 3044575863e038595742b9f736868bb9ee07f3e2: requesting changes for one correctness issue in the Arrow Flight schema path.

Checkpoint conclusions:

  • Goal, focusedness, and tests: the PR broadly implements native UUID across FE, BE, storage, formats, functions, and UDF/JNI paths, with substantial unit/regression coverage. However, the new Flight schema assertion exposes an omitted central mapper case, so the Flight portion does not yet accomplish its goal and its own test cannot pass.
  • Parallel paths and conditions: V1/V2 Parquet and ORC, Arrow/Iceberg carriers, runtime filters/indexes, point queries, aggregates, casts, JNI/JDBC/Python, and fixed/flexible partial updates were traced. No additional distinct correctness issue was substantiated; existing review threads remain duplicate fences.
  • Concurrency, lifecycle, and performance: UUIDv7 atomic/counter state, the scoped datetime-to-v7 mutex, Arrow extension lifecycle, and partial-update load identity/replay were reviewed. No additional concurrency, lifetime, or material performance defect was found.
  • Configuration and compatibility: no new dynamic configuration contract is introduced. ORC varbinary precedence and the mixed-version BE fence are already covered by existing threads; JNI correctly advances its plugin API major version.
  • Persistence, transactions, and atomicity: the partial-update load seed is persisted and restored, and deterministic defaults use logical keys across replica, retry, row-remap, and rollup paths. No additional transaction, EditLog, replay, or crash-consistency issue was found.
  • Observability and FE/BE variables: no new metric, logging, or FE-to-BE variable gap was identified for the added paths.
  • User focus: no additional focus was supplied.

Validation was static only, as required by the review prompt; no build or test command was run. Live CI state is not treated as independent execution evidence.

desc("key", TPrimitiveType.UUID), desc("value", TPrimitiveType.UUID))),
buildField(desc("record", TPrimitiveType.STRUCT, desc("u", TPrimitiveType.UUID))),
buildField(desc("text", TPrimitiveType.STRING))));
Schema schema = MessageSerializer.deserializeSchema(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Add UUID to the central Flight Arrow type mapping. buildField(...) reaches DorisArrowTypeMapping.toArrowType, whose switch currently has no PrimitiveType.UUID case and therefore returns ArrowType.Null. That means GetTables and nested serialized schemas advertise Null while BE emits arrow.uuid, and this assertion (plus the existing exhaustive everyPrimitiveTypeHasARow test) cannot pass. Please return UuidType.INSTANCE from the mapper and add UUID to its mapping table/tests.

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 51.29% (139/271) 🎉
Increment coverage report
Complete coverage report

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 27709 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 3044575863e038595742b9f736868bb9ee07f3e2, data reload: false

------ Round 1 ----------------------------------
============================================
q1	16473	3870	3871	3870
q2	2210	387	303	303
q3	9455	1470	811	811
q4	4483	478	351	351
q5	7217	824	547	547
q6	187	169	138	138
q7	747	791	601	601
q8	9306	1598	1536	1536
q9	5450	4295	4205	4205
q10	6803	1322	1014	1014
q11	425	268	251	251
q12	640	409	299	299
q13	17675	2610	2002	2002
q14	280	249	235	235
q15	q16	728	721	658	658
q17	1700	1158	922	922
q18	6540	5648	5536	5536
q19	1188	1256	902	902
q20	465	374	258	258
q21	5210	2954	3151	2954
q22	467	389	316	316
Total cold run time: 97649 ms
Total hot run time: 27709 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4679	4540	4674	4540
q2	735	592	552	552
q3	4779	5220	4554	4554
q4	2228	2321	1490	1490
q5	4669	4450	4359	4359
q6	231	168	126	126
q7	1843	1912	1470	1470
q8	2371	2050	1953	1953
q9	7465	7308	7318	7308
q10	3692	3592	3152	3152
q11	539	387	356	356
q12	713	714	513	513
q13	2425	2620	1965	1965
q14	281	265	247	247
q15	q16	668	673	607	607
q17	7313	6779	6646	6646
q18	11897	11108	11861	11108
q19	1106	980	1018	980
q20	2210	2213	1900	1900
q21	4997	4113	4249	4113
q22	515	444	398	398
Total cold run time: 65356 ms
Total hot run time: 58337 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 152308 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 3044575863e038595742b9f736868bb9ee07f3e2, data reload: false

query5	4309	593	461	461
query6	438	202	195	195
query7	4841	545	305	305
query8	341	170	172	170
query9	8806	3950	3929	3929
query10	443	306	263	263
query11	5819	3519	3228	3228
query12	144	104	90	90
query13	1261	587	404	404
query14	6511	4489	4199	4199
query14_1	3985	3907	3947	3907
query15	203	200	179	179
query16	997	510	377	377
query17	917	686	543	543
query18	2430	461	341	341
query19	206	184	149	149
query20	82	92	84	84
query21	225	135	118	118
query22	12946	13020	12762	12762
query23	14027	13050	12453	12453
query23_1	12532	12558	12614	12558
query24	7029	1077	660	660
query24_1	647	683	724	683
query25	562	426	380	380
query26	1300	333	165	165
query27	2626	543	330	330
query28	4412	1995	1992	1992
query29	1622	725	515	515
query30	298	227	192	192
query31	894	763	640	640
query32	144	98	93	93
query33	507	315	262	262
query34	1202	1123	622	622
query35	726	748	636	636
query36	811	804	720	720
query37	157	106	92	92
query38	1846	1778	1711	1711
query39	701	702	663	663
query39_1	660	625	641	625
query40	225	128	110	110
query41	74	72	68	68
query42	100	98	95	95
query43	330	344	299	299
query44	1360	700	712	700
query45	184	178	165	165
query46	1067	1226	697	697
query47	1473	1531	1381	1381
query48	403	394	289	289
query49	585	408	296	296
query50	932	338	255	255
query51	10147	10416	10480	10416
query52	95	87	74	74
query53	248	245	178	178
query54	245	219	184	184
query55	86	73	71	71
query56	231	210	216	210
query57	1504	1361	1315	1315
query58	283	261	254	254
query59	1979	2037	1855	1855
query60	282	241	224	224
query61	150	152	150	150
query62	395	319	267	267
query63	211	167	179	167
query64	2698	1015	827	827
query65	3483	3394	3428	3394
query66	1764	446	306	306
query67	20251	20041	19924	19924
query68	3271	1505	954	954
query69	419	294	254	254
query70	882	805	817	805
query71	302	231	210	210
query72	2651	2534	2209	2209
query73	838	791	427	427
query74	4615	4496	4279	4279
query75	2302	2295	1932	1932
query76	2074	1150	727	727
query77	367	388	300	300
query78	9224	9041	8511	8511
query79	1365	1180	766	766
query80	1237	473	370	370
query81	601	325	277	277
query82	706	165	123	123
query83	305	222	194	194
query84	314	146	109	109
query85	902	461	373	373
query86	408	244	213	213
query87	1980	1958	1857	1857
query88	3621	2734	2724	2724
query89	363	283	244	244
query90	1960	181	183	181
query91	173	155	132	132
query92	123	83	90	83
query93	1524	1428	820	820
query94	695	355	294	294
query95	672	375	348	348
query96	1017	750	335	335
query97	2442	2438	2364	2364
query98	188	151	144	144
query99	715	725	606	606
Total cold run time: 236198 ms
Total hot run time: 152308 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 23.97 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 3044575863e038595742b9f736868bb9ee07f3e2, data reload: false

query1	0.01	0.01	0.01
query2	0.09	0.05	0.05
query3	0.25	0.13	0.13
query4	1.61	0.14	0.14
query5	0.27	0.22	0.22
query6	1.16	0.93	0.94
query7	0.04	0.01	0.00
query8	0.05	0.04	0.03
query9	0.38	0.33	0.33
query10	0.55	0.52	0.56
query11	0.20	0.15	0.16
query12	0.19	0.15	0.15
query13	0.46	0.47	0.46
query14	0.96	0.95	0.95
query15	0.61	0.60	0.59
query16	0.31	0.33	0.30
query17	1.08	1.14	1.10
query18	0.22	0.20	0.20
query19	1.96	1.93	1.87
query20	0.02	0.02	0.01
query21	15.46	0.22	0.13
query22	4.90	0.05	0.05
query23	16.16	0.30	0.12
query24	2.94	0.42	0.33
query25	0.11	0.06	0.04
query26	0.74	0.20	0.15
query27	0.04	0.05	0.03
query28	3.56	0.76	0.35
query29	12.47	3.97	3.20
query30	0.28	0.15	0.14
query31	2.77	0.57	0.31
query32	3.22	0.59	0.50
query33	3.09	3.23	3.32
query34	15.48	3.91	3.26
query35	3.21	3.20	3.21
query36	0.56	0.43	0.42
query37	0.09	0.06	0.07
query38	0.06	0.04	0.04
query39	0.03	0.03	0.03
query40	0.17	0.15	0.15
query41	0.08	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.03	0.04
Total cold run time: 95.92 s
Total hot run time: 23.97 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 92.01% (587/638) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 76.40% (34540/45207)
Line Coverage 61.43% (388388/632276)
Region Coverage 57.84% (327114/565531)
Branch Coverage 58.68% (149274/254382)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants