fix(jinja): support negative exponents in ** operator#1433
fix(jinja): support negative exponents in ** operator#1433
Conversation
|
Thanks for your pull request, and welcome to our community! We require contributors to sign our Contributor License Agreement and we don't seem to have your signature on file. Check out this article for more information on why we have a CLA. In order for us to review and merge your code, please submit the Individual Contributor License Agreement form attached above above. If you have questions about the CLA, or if you believe you've received this message in error, please reach out through a comment on this PR. CLA has not been signed by users: @mani-dbt |
|
This repository enforces signed commits. Please sign your commits by following the docs here. |
Negative integer exponents (e.g. 10 ** -9) were failing with "unable to calculate 10 ** -9" because the I128 branch tried to convert the exponent to u32 for checked_pow, which fails for negative values. Fix by promoting to f64 arithmetic when the exponent is negative, matching Python/Jinja2 behavior. Adds unit tests covering the exact conversion_factor values used in dbt adapter macros. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
0e8ec95 to
46f37c0
Compare
| if b < 0 { | ||
| // Negative exponents produce fractional results; promote to float | ||
| // to match Python/Jinja2 behavior (e.g. 10 ** -9 == 1e-9). | ||
| Ok((a as f64).powf(b as f64).into()) |
There was a problem hiding this comment.
Use TryFrom to convert from a and b (128-bit integers) to f64 (64-bit floats) and Err(..) gracefully like in the else branch. Otherwise, the whole system crashes with a panic when a huge integer is passed.
There was a problem hiding this comment.
@felipecrv - after some back and forth with Claude code, used the existing as_f64 to gracefully handle this scenario, and followed the same pattern as else branch. Please review. Revalidated end-to-end with dbt-sa-cli parse against my dbt project using the affected macro.
…ve exponent path Replace bare `as f64` casts with `as_f64(lossy=false)` which round-trips the conversion to catch precision loss on huge integers, returning Err gracefully instead of silently producing incorrect results. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…xponent i128::MAX - 1 rounds to the same f64 as i128::MAX (2^127), but the round-trip check (n as f64 as i128 != n) catches the precision loss and returns Err instead of panicking or silently corrupting the result. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fixes #1432
Summary
**(power) operator with negative integer exponents (e.g.10 ** -9) was failing withdbt1501: Failed to render SQL invalid operation: unable to calculate 10 ** -9value/ops.rs, thepowfunction'sI128branch attempted to convert the exponent tou32forchecked_pow, which fails for negative valuesf64arithmetic instead, matching Python/Jinja2 behavior (e.g.10 ** -9 == 1e-9)conversion_factorsdicts like{'nanosecond': 10**-9, 'microsecond': 10**-6, ...}Test plan
test_pow_negative_exponentinvalue/ops.rscovering10**-9,10**-6,10**-3dbt-sa-cli parseagainst a real dbt project using the affected macro🤖 Generated with Claude Code