Uh oh!
There was an error while loading. Please reload this page.
Add levenshtein and hamming_distance functions - #60412
Conversation
Thearas
commented
Feb 1, 2026
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
There was a problem hiding this comment.
Pull request overview
This PR adds support for two string distance functions: levenshtein (Hive compatibility) and hamming_distance (Trino/Presto compatibility). These functions compute edit distance and character-difference distance between strings respectively, with proper UTF-8 character handling.
Changes:
- Implemented
levenshteinfunction that calculates the minimum number of single-character edits needed to transform one string into another - Implemented
hamming_distancefunction that counts character differences between equal-length strings - Added comprehensive test coverage for both functions including edge cases, NULL handling, and UTF-8 character support
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| test_string_all.groovy | Added regression tests for levenshtein and hamming_distance functions with various input scenarios |
| test_string_function.groovy | Added nereids query tests covering edge cases and error conditions for both functions |
| test_string_all.out | Expected output for levenshtein and hamming_distance test cases |
| test_string_function.out | Expected output for nereids function tests |
| ScalarFunctionVisitor.java | Added visitor methods for HammingDistance and Levenshtein function nodes |
| Levenshtein.java | Implemented Levenshtein scalar function class with signature definitions |
| HammingDistance.java | Implemented HammingDistance scalar function class with signature definitions |
| StringArithmetic.java | Added executable implementations for levenshtein and hamming_distance with dynamic programming algorithm |
| BuiltinScalarFunctions.java | Registered new functions in the builtin scalar functions registry |
| simple_function_factory.h | Added function registration declarations for backend implementations |
| function_string.cpp | Minor whitespace cleanup |
| function_levenshtein.cpp | Backend C++ implementation of levenshtein with UTF-8 support |
| function_hamming_distance.cpp | Backend C++ implementation of hamming_distance with UTF-8 support and length validation |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
zclllyybb
commented
Feb 2, 2026
and remember to format your code, add more cases which query from table |
Uh oh!
There was an error while loading. Please reload this page.
fb0c27f to
5ccb369Comparezclllyybb
commented
Mar 14, 2026
run buildall |
zclllyybb
commented
Mar 14, 2026
/review |
There was a problem hiding this comment.
Code Review Summary for PR #60412: Add levenshtein and hamming_distance functions
Overall this is a well-structured PR that adds two useful string distance functions. The FE-BE type consistency is correct, the constant folding implementations match the BE implementations, and the test coverage is reasonable. Below are the issues found, organized by the critical checkpoint conclusions.
Critical Checkpoint Conclusions
1. Goal and correctness: The PR adds levenshtein (returns Int32) and hamming_distance (returns Int64) string distance functions with UTF-8 support. The core algorithms are correct. FE constant folding, FE scalar function classes, BE implementations, and registration are all present.
2. Modification scope: The change is focused - 13 files, all related to the two new functions. Minor cosmetic changes in function_string.cpp (blank line changes) are unnecessary but harmless.
3. Concurrency: No concurrency concerns - these are pure stateless scalar functions.
4. Lifecycle management: No special lifecycle concerns.
5. Configuration items: None added. N/A.
6. Incompatible changes: None. New functions only.
7. Parallel code paths:hamming_distance uses a custom FunctionBinaryStringToTypeWithNull wrapper class instead of the standard FunctionBinaryToType used by levenshtein. This is necessary because hamming_distance can return Status::InvalidArgument for unequal-length strings, and the custom class provides proper row-level null handling with explicit nullable return type control. This is an acceptable design choice.
8. Special conditional checks: The string_ref_at helper in both files contains defensive if checks that violate AGENTS.md coding standards. See inline comments.
9. Test coverage: Good regression test coverage for both functions with ASCII, UTF-8, NULL, empty string, and table-based tests. Error case for hamming_distance is tested. However, there is an orphaned .out entry. See inline comments.
10. Observability: N/A for pure scalar functions.
11. Transaction/persistence: N/A.
12. FE-BE variable passing: FE-BE types are consistent (levenshtein: Int32/Int32, hamming_distance: Int64/Int64). PropagateNullable in FE aligns with BE null handling for both functions.
13. Performance: The levenshtein function has O(m*n) time complexity with no input size limit, which is a potential DoS concern for very large strings. See inline comments.
14. Other issues: Alias levenshtein_distance (common Hive name) is not registered - this may be intentional but worth considering for compatibility.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
doris-robot
commented
Mar 14, 2026
TPC-H: Total hot run time: 26861 ms |
doris-robot
commented
Mar 14, 2026
TPC-DS: Total hot run time: 167910 ms |
hello-stephen
commented
Mar 14, 2026
FE UT Coverage ReportIncrement line coverage |
doris-robot
commented
Mar 14, 2026
BE UT Coverage ReportIncrement line coverage Increment coverage report
|
hello-stephen
commented
Mar 14, 2026
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
KazeBox33
commented
Mar 15, 2026
run buildall |
doris-robot
commented
Mar 15, 2026
TPC-H: Total hot run time: 26915 ms |
doris-robot
commented
Mar 15, 2026
TPC-DS: Total hot run time: 168305 ms |
hello-stephen
commented
Mar 15, 2026
FE UT Coverage ReportIncrement line coverage |
doris-robot
commented
Mar 15, 2026
BE UT Coverage ReportIncrement line coverage Increment coverage report
|
### What problem does this PR solve? Issue Number: None Related PR: apache#60412 Problem Summary: Trim the trailing storage zero from const scalar string arguments in the BE levenshtein const-scalar paths so they match vector-vector execution and FE constant folding semantics. ### Release note None ### Check List (For Author) - Test: No need to test (local BE build environment is unavailable in this workspace; existing regression cases already cover the const-scalar paths adjusted here) - Behavior changed: Yes (BE const-scalar levenshtein no longer counts the trailing storage zero as a real character) - Does this need documentation: No
### What problem does this PR solve? Issue Number: None Related PR: apache#60412 Problem Summary: Remove whole-file compile_check_avoid wrappers from the new hamming_distance and levenshtein BE implementations so normal conversion warnings remain enabled for new code. ### Release note None ### Check List (For Author) - Test: No need to test (local thirdparty headers required for BE syntax build are unavailable in this workspace; formatting and diff checks were run) - Behavior changed: No - Does this need documentation: No
936e5cc to
60539aaComparelinrrzqqq
commented
May 27, 2026
run buildall |
linrrzqqq
commented
May 27, 2026
/review |
There was a problem hiding this comment.
Automated review summary for PR 60412 at 60539aa.
I did not add new inline comments because the remaining concerns I found are already covered by existing review threads and should not be duplicated. In particular, please resolve the already-open discussions around vstring_function.h header self-containment, levenshtein FE/BE constant-folding cost guards, debug_skip_fold_constant test session-state restoration, and string trailing-zero handling/access consistency.
Critical checkpoint conclusions:
- Goal/test proof: the PR adds
levenshteinandhamming_distancein FE/BE with regression coverage, including Nereids and negative hamming-distance cases. Existing threads still cover gaps/risks in constant-fold cost and test session state. - Scope: the implementation is focused on the two new string functions and their registrations/tests.
- Concurrency/lifecycle: no new shared mutable state, threads, locks, globals with non-trivial cross-TU initialization, or lifecycle-sensitive ownership were introduced.
- Configuration/compatibility: no new config items, storage formats, persistence, transaction paths, or FE-BE protocol fields were added.
- Parallel paths: both BE execution and FE/Nereids binding/folding paths were added; existing review context already calls out remaining coverage/behavior concerns.
- Error handling:
hamming_distanceunequal-length errors are propagated throughStatusin BE andAnalysisExceptionin FE; no ignoredStatusfound in the reviewed diff. - Memory/performance: the Levenshtein DP remains O(m*n) and existing review threads already flag lack of guard for large constant/runtime inputs.
- Observability: no new distributed or background operational path requiring new metrics/logging.
- User focus: no additional user-provided review focus was present.
No additional distinct issues found beyond the known review context.
hello-stephen
commented
May 27, 2026
TPC-H: Total hot run time: 32172 ms |
hello-stephen
commented
May 27, 2026
TPC-DS: Total hot run time: 172191 ms |
hello-stephen
commented
May 27, 2026
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
hello-stephen
commented
May 27, 2026
FE Regression Coverage ReportIncrement line coverage |
PR approved by at least one committer and no changes requested. |
Uh oh!
There was an error while loading. Please reload this page.
## Versions - [ ] dev - [x] 4.x - [ ] 3.x - [ ] 2.1 or older (not covered by version/language sync gate) ## Languages - [x] Chinese - [x] English - [ ] Japanese candidate translation needed ## Docs Checklist - [x] Checked by AI - [ ] Test Cases Built - [x] Updated required version and language counterparts, or explained why not - [x] If only one language changed, confirmed whether source/translation counterparts need sync Related PR: apache/doris#60412
Related Issue: apache#48203 Related PR: apache#57144 (reference) Problem Summary: support levenshtein (Hive) and hamming_distance (Trino/Presto).
…ing functions Rebuilds the string-similarity functions proposed in apache#60799 on top of current master, addressing prior review feedback: - levenshtein and damerau_levenshtein are dropped: both now exist on master (apache#60412, apache#65278) under levenshtein/damerau_levenshtein_distance, so keeping ours would only collide. - All three functions get full UTF-8 support (ASCII fast path + character- aware path via VStringFunctions::get_utf8_char_offsets/utf8_char_equal), matching the pattern established by levenshtein/damerau_levenshtein_distance instead of operating on raw bytes. - jaro_winkler now shares its Jaro computation with the new jaro function instead of duplicating the matching/transposition logic. - jaccard_similarity is redefined as a character-set Jaccard index (bitset for the ASCII path, hash set of UTF-8 characters otherwise), matching ClickHouse's stringJaccardIndex semantics, rather than an unexplained byte-bigram scheme. - Added FE constant-folding (StringArithmetic.java) for all three functions, and BE unit tests plus expanded regression coverage (column/constant combinations, nullable columns, UTF-8, over-length-input errors). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ing functions Rebuilds the string-similarity functions proposed in apache#60799 on top of current master, addressing prior review feedback: - levenshtein and damerau_levenshtein are dropped: both now exist on master (apache#60412, apache#65278) under levenshtein/damerau_levenshtein_distance, so keeping ours would only collide. - All three functions get full UTF-8 support (ASCII fast path + character- aware path via VStringFunctions::get_utf8_char_offsets/utf8_char_equal), matching the pattern established by levenshtein/damerau_levenshtein_distance instead of operating on raw bytes. - jaro_winkler now shares its Jaro computation with the new jaro function instead of duplicating the matching/transposition logic. - jaccard_similarity is redefined as a character-set Jaccard index (bitset for the ASCII path, hash set of UTF-8 characters otherwise), matching ClickHouse's stringJaccardIndex semantics, rather than an unexplained byte-bigram scheme. - Added FE constant-folding (StringArithmetic.java) for all three functions, and BE unit tests plus expanded regression coverage (column/constant combinations, nullable columns, UTF-8, over-length-input errors). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ing functions Rebuilds the string-similarity functions proposed in apache#60799 on top of current master, addressing prior review feedback: - levenshtein and damerau_levenshtein are dropped: both now exist on master (apache#60412, apache#65278) under levenshtein/damerau_levenshtein_distance, so keeping ours would only collide. - All three functions get full UTF-8 support (ASCII fast path + character- aware path via VStringFunctions::get_utf8_char_offsets/utf8_char_equal), matching the pattern established by levenshtein/damerau_levenshtein_distance instead of operating on raw bytes. - jaro_winkler now shares its Jaro computation with the new jaro function instead of duplicating the matching/transposition logic. - jaccard_similarity is redefined as a character-set Jaccard index (bitset for the ASCII path, hash set of UTF-8 characters otherwise), matching ClickHouse's stringJaccardIndex semantics, rather than an unexplained byte-bigram scheme. - Added FE constant-folding (StringArithmetic.java) for all three functions, and BE unit tests plus expanded regression coverage (column/constant combinations, nullable columns, UTF-8, over-length-input errors).
…ing functions Rebuilds the string-similarity functions proposed in apache#60799 on top of current master, addressing prior review feedback: - levenshtein and damerau_levenshtein are dropped: both now exist on master (apache#60412, apache#65278) under levenshtein/damerau_levenshtein_distance, so keeping ours would only collide. - All three functions get full UTF-8 support (ASCII fast path + character- aware path via VStringFunctions::get_utf8_char_offsets/utf8_char_equal), matching the pattern established by levenshtein/damerau_levenshtein_distance instead of operating on raw bytes. - jaro_winkler now shares its Jaro computation with the new jaro function instead of duplicating the matching/transposition logic. - jaccard_similarity is redefined as a character-set Jaccard index (bitset for the ASCII path, hash set of UTF-8 characters otherwise), matching ClickHouse's stringJaccardIndex semantics, rather than an unexplained byte-bigram scheme. - Added FE constant-folding (StringArithmetic.java) for all three functions, and BE unit tests plus expanded regression coverage (column/constant combinations, nullable columns, UTF-8, over-length-input errors).
…rd with BE Reviewed the merged levenshtein/hamming_distance (apache#60412) and damerau_levenshtein_distance (apache#65278, apache#66236) PRs for consistency with this one. Found and fixed a real FE/BE divergence in the process: - The FE constant-fold length guard checked Java code point count, while the BE guard checks UTF-8 byte length. For multi-byte input the two disagree (e.g. ~30000 3-byte characters is under the FE's 65535 code-point cap but over BE's 65535-byte cap), so a literal expression could fold successfully on FE while the same value would be rejected by BE if read from a column. FE now measures UTF-8 bytes too, matching function_string_similarity.cpp exactly (mirrors the fix pattern in apache#64881, "Align constant folding with BE results"). - Added regression coverage for astral-plane (surrogate-pair/4-byte UTF-8) characters on all three functions, matching the precedent set for RIGHT/INSTR in apache#64881.
What problem does this PR solve?
Related Issue: #48203
Related PR: #57144 (reference)
Problem Summary: support levenshtein (Hive) and hamming_distance (Trino/Presto).
Release note
None
Check List (For Author)
Test
Behavior changed:
Does this need documentation?