-
Notifications
You must be signed in to change notification settings - Fork 82
Fix float formatting to match ODBC sqlcmd with hybrid approach (decimal notation with scientific fallback) #686
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Co-authored-by: dlevy-msft-sql <194277063+dlevy-msft-sql@users.noreply.github.com>
Co-authored-by: dlevy-msft-sql <194277063+dlevy-msft-sql@users.noreply.github.com>
Co-authored-by: dlevy-msft-sql <194277063+dlevy-msft-sql@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR updates go-sqlcmd’s result formatting so SQL Server FLOAT/REAL values are rendered in decimal notation (rather than scientific notation) to better match the legacy ODBC sqlcmd output and improve script compatibility.
Changes:
- Add explicit
float64/float32handling inscanRow()usingstrconv.FormatFloat(..., 'f', -1, ...)to avoid scientific notation. - Add a formatter test that asserts float output does not include scientific notation and includes expected decimal substrings.
- Ignore the root-level
modernbuild artifact in.gitignore.
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
pkg/sqlcmd/format.go |
Forces decimal float formatting during row scanning to align with ODBC sqlcmd output style. |
pkg/sqlcmd/format_test.go |
Adds an integration-style test covering float output formatting expectations. |
.gitignore |
Ignores a root-level modern binary/artifact. |
…extreme values Co-authored-by: dlevy-msft-sql <194277063+dlevy-msft-sql@users.noreply.github.com>
Co-authored-by: dlevy-msft-sql <194277063+dlevy-msft-sql@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 2 out of 3 changed files in this pull request and generated 2 comments.
|
@copilot fix the issues identified in the last review |
- Set SQLCMDMAXVARTYPEWIDTH in TestFormatterFloatFormattingExtremeValues to enable fallback behavior testing - Add TestFormatterRealFormatting to test float32 (REAL) column formatting with both typical and extreme values Co-authored-by: dlevy-msft-sql <194277063+dlevy-msft-sql@users.noreply.github.com>
- Add more precise assertions to verify typical values don't use scientific notation - Split output by lines to examine data separately from headers - Verify the typical value column doesn't contain 'e' notation Co-authored-by: dlevy-msft-sql <194277063+dlevy-msft-sql@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 4 out of 10 changed files in this pull request and generated no new comments.
|
@copilot Fix the failing GitHub Actions job golangci-lint (run: https://github.com/microsoft/go-sqlcmd/actions/runs/21575514192/job/62162530634?pr=686) in microsoft/go-sqlcmd at ref 5194b35. The job fails due to errcheck violations in pkg/sqlcmd/commands.go: At listVarCommand around line ~411, the return value of fmt.Fprintf is not checked. |
- Check fmt.Fprintf return value in listVarCommand - Wrap deferred os.Remove in anonymous function with error handling - Check file.Close return value in editCommand - All 3 errcheck violations resolved Co-authored-by: dlevy-msft-sql <194277063+dlevy-msft-sql@users.noreply.github.com>
Fixed in commit 85c8c8b. All 3 golangci-lint errcheck violations resolved:
golangci-lint now passes with 0 issues. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 4 out of 10 changed files in this pull request and generated 2 comments.
|
@copilot fix the code review issues |
- Add deferred file.Close in editCommand to ensure file is closed on all error paths - Add TestFormatterFloatFormattingExtremeValuesUnlimitedWidth to test fallback with SQLCMDMAXVARTYPEWIDTH=0 - Ensures extreme values use scientific notation even with unlimited width Co-authored-by: dlevy-msft-sql <194277063+dlevy-msft-sql@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 4 out of 10 changed files in this pull request and generated 1 comment.
|
@copilot fix the review comment |
Co-authored-by: dlevy-msft-sql <194277063+dlevy-msft-sql@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 4 out of 10 changed files in this pull request and generated no new comments.
Float Formatting Fix - Complete ✅
This PR fixes the inconsistent float formatting between go-sqlcmd and ODBC SQLCMD versions.
Problem
Previously, go-sqlcmd would output floats using scientific notation (e.g.,
4.713347310380896e+06) while ODBC SQLCMD uses decimal notation (e.g.,4713347.3103808956), causing compatibility issues.Solution
Implemented a hybrid approach that:
Changes
pkg/sqlcmd/format.goto use hybrid float formatting for both FLOAT (float64) and REAL (float32).gitignoreto exclude build artifactsBehavior
4713347.310380896instead of4.713347310380896e+061e+308instead of truncated1000000000000000000000001e-308instead of truncated0.0000000000000000000000Testing
Original prompt
This section details on the original issue you should resolve
<issue_title>Inconsistent Float Formatting Between go-sqlcmd and ODBC SQLCMD Versions</issue_title>
<issue_description>Description
In Windows OS the go-sqlcmd application produces a different output format for FLOAT data types compared to the ODBC-based SQLCMD.EXE when executing the same SQL query. This discrepancy can cause issues for applications and scripts that rely on consistent float formatting.
Steps to Reproduce
1.8.1):15.0.4410):Observed Behavior
go-sqlcmd Output:
ODBC SQLCMD Output:
Expected Behavior
The float formatting in the output of go-sqlcmd should align with the behavior of the ODBC SQLCMD to maintain compatibility and consistency across different SQLCMD implementations.
Environment
Additional Information
This issue primarily affects the formatting of float numbers. For example:
4.713347310380896e+064713347.3103808956The scientific notation output from go-sqlcmd is less intuitive and might require additional parsing in downstream applications.
Request
Please investigate this behavior and consider aligning the float formatting of go-sqlcmd with the output of the ODBC-based SQLCMD.EXE.
</issue_description>
Comments on the Issue (you are @copilot in this section)
@shueybubbles How were the values inserted? Is go-sqlcmd reading from the same table instance as ODBC sqlcmd? @shueybubbles The ODBC logic for formatting floats is pretty exotic. I'll see how close various standard options available in `strconv.FormatFloat` get me to the desired behavior. @shueybubbles FWIW I think the "best" way to query floats to get a consistent format is to use the `STR` function in TSQL to make sure your query result renders in a driver-independent and app-independent way. Does SSMS format floats the same way ODBC does? @shueybubbles Go and SQL floats may have some precision mismatch issues (I am far from a floating point expert).I wrote this experiment:
The output drops the last digit:
Also, there are situations where ODBC converts to exponent, but I don't quite understand the logic enough to write test cases to verify any change I make will align with ODBC.
In short, I don't have straightforward way to make our rendering of SQL floats match the ODBC rendering in every instance. I don't know if your example is a frequent problem to justify spending a lot of time on it.</comment_new>
<comment_new>@shueybubbles
thx I'll look at
big.Floatsince we already usemath/bigelsewhere.Using
fisn't quite right, though, because ODBC uses some other special sauce to decide when to use exponents instead of just a decimal. We could flip it so there are cases where ODBC is using exponents and go-sqlcmd does not.As I mentioned above - any query that needs to return float-as-string ...
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.