Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 17, 2025

Pull request type

  • Feature

What is the current behavior?

The SDK already supports scanning YDB Decimal values using types.Decimal as the destination type in both query client and database/sql, but lacked comprehensive test coverage. Additionally, there was a bug in the Decimal.Scan method when handling string values where manual byte copying didn't properly handle the conversion to YDB's 128-bit decimal format.

What is the new behavior?

  • Added comprehensive integration tests in tests/integration/decimal_scan_test.go covering:
    • Query client: Direct row.Scan(&decimal) with various precision/scale combinations, negative values, NULL handling
    • Database/SQL: Both table service and query service modes with same coverage
  • Fixed byte ordering bug in internal/decimal/decimal.go by replacing manual byte copying with BigIntToByte() function which properly handles:
    • Correct conversion from big.Int to YDB's 128-bit decimal format
    • Proper endianness handling
    • Sign handling using two's complement for negative numbers
    • Overflow detection and conversion to inf/neginf

Usage Example

// Query client
row, err := db.Query().QueryRow(ctx,   
    `SELECT Decimal('123456789.987654321', 33, 12)`,  
    query.WithIdempotent(),  
)  
var dst types.Decimal   
err = row.Scan(&dst)
// dst.Precision == 33, dst.Scale == 12

// Database/SQL
row := db.QueryRowContext(ctx, `SELECT Decimal('123456789.987654321', 33, 12)`)
var dst types.Decimal  
err = row.Scan(&dst)

Other information

  • All existing tests pass with no regressions
  • The bug fix ensures correct decimal value conversion when scanning from string sources
  • Test coverage validates the functionality works correctly across both query and database/sql clients
Original prompt

This section details on the original issue you should resolve

<issue_title>feat: support YDB Decimal as destination type in query result and database/sql result</issue_title>
<issue_description>Example using query-client and Scan API

row, err := db.Query().QueryRow(ctx,   
    `SELECT Decimal('123456789.987654321', 33, 12)`,  
    query.WithIdempotent(),  
)  
if err != nil {  
    panic(err)  
}  
var dst types.Decimal   // or other type
err = row.Scan(&dst)  
// check value, precision, scale

Example using database/sql client

var db *sql.DB // init outside
row := db.QueryRowContext(ctx, `SELECT Decimal('123456789.987654321', 33, 12)`)
var dst types.Decimal  // or other type
err = row.Scan(&dst)  
if err != nil {  
    panic(err)  
}  
// check value, precision, scale
```</issue_description>

## Comments on the Issue (you are @copilot in this section)

<comments>
</comments>

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@github-actions
Copy link

github-actions bot commented Nov 17, 2025

github.com/ydb-platform/ydb-go-sdk/v3/decimal

compatible changes

package added

github.com/ydb-platform/ydb-go-sdk/v3/table/types

incompatible changes

Decimal: changed from github.com/ydb-platform/ydb-go-sdk/v3/internal/decimal.Decimal to github.com/ydb-platform/ydb-go-sdk/v3/decimal.Decimal
DecimalTypeFromDecimal: changed from func(*Decimal) Type to func(*Decimal) Type
DecimalValue: changed from func(*Decimal) Value to func(*Decimal) Value
ToDecimal: changed from func(Value) (*Decimal, error) to func(Value) (*Decimal, error)

summary

Inferred base version: v3.121.1
Cannot suggest a release version.
Incompatible changes were detected.

@codecov-commenter
Copy link

codecov-commenter commented Nov 17, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.15%. Comparing base (2bd7589) to head (5c215a8).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1938      +/-   ##
==========================================
+ Coverage   73.96%   74.15%   +0.19%     
==========================================
  Files         395      395              
  Lines       34557    34573      +16     
==========================================
+ Hits        25560    25638      +78     
+ Misses       7875     7812      -63     
- Partials     1122     1123       +1     
Flag Coverage Δ
experiment 73.86% <100.00%> (+0.58%) ⬆️
go-1.21.x 73.00% <100.00%> (+0.22%) ⬆️
go-1.25.x 74.13% <100.00%> (+0.18%) ⬆️
integration 55.08% <46.34%> (-0.29%) ⬇️
macOS 47.76% <96.34%> (+0.39%) ⬆️
ubuntu 74.15% <100.00%> (+0.18%) ⬆️
unit 47.78% <96.34%> (+0.37%) ⬆️
windows 47.77% <96.34%> (+0.39%) ⬆️
ydb-24.4 54.28% <46.34%> (-0.28%) ⬇️
ydb-25.2 54.87% <46.34%> (-0.40%) ⬇️
ydb-latest 54.63% <46.34%> (-0.28%) ⬇️
ydb-nightly 73.86% <100.00%> (+0.58%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Co-authored-by: asmyasnikov <14202262+asmyasnikov@users.noreply.github.com>
Copilot AI changed the title [WIP] Add support for YDB Decimal in query results Add integration tests for Decimal scanning in query and database/sql clients Nov 17, 2025
Copilot AI requested a review from asmyasnikov November 17, 2025 14:51
Copy link
Contributor

Copilot AI left a 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 adds comprehensive integration tests for scanning YDB Decimal values using types.Decimal as the destination type in both query client and database/sql client. The functionality already existed but lacked test coverage.

Key changes:

  • Added extensive integration tests in tests/integration/decimal_test.go covering query client, database/sql, parameters, NULL handling, and negative values
  • Refactored internal/decimal package to introduce an Interface type and implement sql.Scanner interface on Decimal
  • Simplified function signatures by removing redundant scale parameter from BigIntToByte, FromBytes, and FromInt128 functions

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/integration/decimal_test.go New comprehensive integration tests for Decimal scanning in query client, database/sql, and parameter passing
tests/integration/unexpected_decimal_parse_test.go Removed file (test moved and improved in decimal_test.go)
tests/integration/query_execute_test.go Updated BigIntToByte calls to use new 2-parameter signature
internal/decimal/type.go Added Interface type, sql.Scanner implementation, and helper methods (String, Format, BigInt)
internal/decimal/decimal.go Added ParseDecimal function, Decimal.apply method, Format trimTrailingZeros parameter, simplified function signatures
internal/decimal/errors.go Added errOverflow error
internal/decimal/decimal_test.go Updated tests for new function signatures and added ParseDecimal tests
internal/value/value.go Implemented decimal.Interface, updated castTo to use ToDecimal helper, removed scale parameter from function calls
internal/value/any.go Added case for decimalValue to return *decimal.Decimal
internal/value/value_test.go Updated test to use new Decimal() method instead of individual getters
internal/query/scanner/struct_test.go Updated BigIntToByte calls to use new 2-parameter signature
table/types/cast.go Simplified ToDecimal to use decimal.Interface and ToDecimal helper
internal/xcontext/context_with_stoppable_timeout_test.go Reordered imports (minor)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Use BigIntToByte() instead of manual byte copying to ensure proper
128-bit decimal format conversion with correct endianness and sign handling.

Addresses code review feedback from copilot-pull-request-reviewer[bot].

Co-authored-by: asmyasnikov <14202262+asmyasnikov@users.noreply.github.com>
Copilot AI changed the title Add integration tests for Decimal scanning in query and database/sql clients Add integration tests for Decimal scanning and fix byte ordering bug Dec 12, 2025
@github-actions
Copy link

🌋 SLO Test Results

Status: 🟢 6 workloads tested • All passed

Workload Metrics Regressions Improvements Links
🟢 native-table 0 0 0 ReportCheck
🟢 database-sql-table 0 0 0 ReportCheck
🟢 native-bulk-upsert 0 0 0 ReportCheck
🟢 database-sql-query 0 0 0 ReportCheck
🟢 native-query 0 0 0 ReportCheck
🟢 native-table-over-query-service 0 0 0 ReportCheck

Generated by ydb-slo-action

Copy link
Contributor

Copilot AI left a 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 18 out of 21 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (3)

decimal/decimal.go:63

  • The apply method is a private helper method that lacks documentation. While private methods don't always need documentation, this method performs complex logic (string parsing, precision calculation, type assertions) that would benefit from a doc comment explaining its purpose, the types it handles, and any assumptions it makes about the input values.
    decimal/decimal.go:60
  • The ParseDecimal function doesn't validate for edge cases like trailing dots (e.g., "123.") or empty strings. When input is "123.", dotIndex = 3, integerPart = "123", fractionalPart = "", combined = "123", which will parse correctly, but exp will be 0 (length of empty string). While this might work, consider adding explicit handling or validation for such edge cases to make behavior more predictable and add corresponding test cases.
    decimal/decimal.go:84
  • The precision calculation appears to use a magic number formula (bufferSize - exp - 3) where bufferSize is 40. This results in precision = 37 - exp. For very large fractional parts (high exp values), this could result in negative or very small precision values. Consider adding validation to ensure the calculated precision is within valid YDB Decimal bounds (typically 1-35) and documenting why this specific formula is used.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@asmyasnikov asmyasnikov marked this pull request as ready for review December 12, 2025 19:59
@github-actions github-actions bot removed the SLO label Dec 12, 2025
@github-actions github-actions bot removed the SLO label Dec 12, 2025
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.

feat: support YDB Decimal as destination type in query result and database/sql result

3 participants