kosiew opened a new issue, #24058:
URL: https://github.com/apache/datafusion/issues/24058

   ## Related PR
   #23718
   
   ## Problem
   `datafusion/spark/src/function/string/format_string.rs` has separate sign 
and width-padding logic in `format_float`, `format_decimal`, and integer 
decimal formatting. These paths all need to preserve the same Java/Spark 
formatting contract for flags such as `(`, `+`, space, `0`, `-`, and width, but 
they duplicate the final assembly of `prefix + number + suffix`.
   
   A recent decimal bug was caused by this drift: `format_decimal` missed 
`negative_in_parentheses` suffix handling that already existed in 
`format_float`. The bug is now fixed, but the underlying refactor opportunity 
remains: the shared final-assembly invariant is still encoded separately in 
multiple paths.
   
   ## Why it matters
   Duplicated tail-formatting logic makes future fixes easy to apply to one 
numeric type but miss another. This is a correctness risk for SQL-visible 
`format_string` behavior across Float16/32/64, Decimal128/256, and integer 
inputs.
   
   ## Invariant / desired behavior
   After a numeric value has been converted into its unsigned/absolute textual 
`number`, all numeric formatting paths should apply sign, parentheses suffix, 
zero padding, left adjustment, and width using one canonical helper.
   
   Type-specific number generation must remain separate:
   - float finite / NaN / Infinity behavior
   - decimal exact BigDecimal formatting
   - integer base formatting
   - `%g` / scientific precision decisions
   
   ## Proposed direction
   Add a narrow helper for final numeric assembly and padding, not a broad 
helper that tries to merge float and decimal formatting.
   
   Suggested helper responsibility:
   - accept `prefix`, `number`, `suffix`
   - account for `width`, `left_adj`, and `zero_pad`
   - write the final string
   - allow callers to disable zero padding when required, e.g. non-finite floats
   
   Keep `format_float` and `format_decimal` responsible for producing `number`. 
Use the helper only after type-specific formatting is complete.
   
   ## Scope
   ### In
   - Add one small helper in `ConversionSpecifier` for `prefix + number + 
suffix` width/padding assembly.
   - Use it from `format_float` and `format_decimal`.
   - Consider using it from signed integer decimal formatting if it reduces 
duplication without changing behavior.
   - Preserve all existing outputs.
   - Keep or add focused regression coverage where helper behavior could drift, 
especially negative parentheses with width and zero padding.
   
   ### Out
   - Do not merge decimal and float number-generation logic.
   - Do not change Spark/Java compatibility semantics.
   - Do not rewrite parsing or validation of format specifiers.
   - Do not alter scientific / compact `%g` precision behavior.
   - Do not introduce a broad abstraction with many primitive flags beyond 
final assembly/padding.
   
   ## Acceptance criteria
   - [ ] `format_float` and `format_decimal` use the same final 
sign/suffix/width-padding helper.
   - [ ] Existing float, decimal, and integer `format_string` tests pass 
unchanged unless expected strings are proven wrong against Spark/Java.
   - [ ] Negative-parentheses decimal formatting remains covered for no-width 
and width cases, confirming the existing bug fix stays protected.
   - [ ] Helper has a narrow contract documented by its name/signature or a 
short comment.
   - [ ] Refactor is behavior-preserving except for any separately justified 
bug fixes.
   
   ## Tests / verification
   - Run targeted Rust tests for Spark format string:
     - `cargo test -p datafusion-spark format_string --lib`
   - At minimum, include/keep regression coverage for:
     - Decimal128 negative `%(,.2f`
     - Decimal128 negative `%(,15.2f`
     - Float negative `%(,15.2f`
     - zero padding with sign/parentheses where supported
   - If integer formatting is touched, run existing integer `format_string` 
tests and add a focused case only if current coverage does not protect sign + 
width placement.
   
   ## Notes / open questions
   - Decimal256 uses the same `format_decimal` path as Decimal128. A small 
Decimal256 regression case may be useful if the refactor touches decimal 
dispatch or tests are otherwise too Decimal128-specific.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to