Skip to content

feat(contrib/drivers/mssql): convert uniqueidentifier to uuid.UUID#4756

Open
NickWilde18 wants to merge 2 commits into
gogf:masterfrom
NickWilde18:fix/mssql-uniqueidentifier-conversion
Open

feat(contrib/drivers/mssql): convert uniqueidentifier to uuid.UUID#4756
NickWilde18 wants to merge 2 commits into
gogf:masterfrom
NickWilde18:fix/mssql-uniqueidentifier-conversion

Conversation

@NickWilde18

@NickWilde18 NickWilde18 commented Apr 16, 2026

Copy link
Copy Markdown

Summary

SQL Server UNIQUEIDENTIFIER columns arrive on the wire as 16 bytes whose first 8 follow the little-endian COM/Win32 GUID layout while the remaining 8 are big-endian. The MSSQL driver previously had no override for this column type, so gdb's default conversion path treated the raw bytes as a string and returned garbage characters. Any caller doing row[\"id\"].String() on a uniqueidentifier column would get mojibake.

This PR mirrors the existing pgsql uuid handling: add CheckLocalTypeForField and ConvertValueForLocal overrides on the MSSQL driver that detect uniqueidentifier (case-insensitive), delegate the byte-order swap to mssql.UniqueIdentifier.Scan, and return a uuid.UUID. All other column types fall through to Core unchanged.

Reproduction (before this PR)

```sql
CREATE TABLE t_uuid (id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID(), label NVARCHAR(50));
INSERT INTO t_uuid (label) VALUES ('hello');
```

```go
rows, _ := db.Model("t_uuid").Ctx(ctx).Fields("id, label").All()
for _, r := range rows {
fmt.Println(r["id"].String()) // garbage characters like "\ufffdԓ\ufffd?\"\ufffdB\ufffdGx\ufffd..."
}
```

After this PR the same call returns the canonical UUID string (e.g. da93d4f6-223f-42b2-a647-789371ffa693).

Tests

  • Test_CheckLocalTypeForField_UniqueIdentifier — verifies uniqueidentifier (and UNIQUEIDENTIFIER) maps to LocalTypeUUID, and that unknown types still fall through to Core (nvarchar(100) → LocalTypeString).
  • Test_ConvertValueForLocal_UniqueIdentifier — covers the wire-format byte swap, the string form (e.g. after a server-side CAST AS NVARCHAR(36)), a sanity check against mssql.UniqueIdentifier.Scan directly, and the invalid-length error path.

These unit tests do not require a running MSSQL instance — they exercise the driver hooks against fixture inputs. Existing DB-backed tests continue to use the CI's MSSQL container unchanged.

Notes

  • github.com/google/uuid is promoted from indirect to direct dependency in contrib/drivers/mssql/go.mod (already pulled in transitively via microsoft/go-mssqldb).
  • This patch concerns only the read path (DB → Go). Write/where-clause paths (Go → DB) already work because MSSQL accepts the canonical string form server-side.

Copilot AI review requested due to automatic review settings April 16, 2026 15:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds MSSQL-specific handling for SQL Server UNIQUEIDENTIFIER so result decoding returns uuid.UUID (rather than mojibake) by swapping the wire byte order via go-mssqldb’s UniqueIdentifier.Scan, mirroring existing UUID handling in other drivers.

Changes:

  • Add CheckLocalTypeForField override to map uniqueidentifiergdb.LocalTypeUUID (case-insensitive).
  • Add ConvertValueForLocal override to decode UNIQUEIDENTIFIER into uuid.UUID.
  • Add unit tests covering type mapping and conversion, and promote github.com/google/uuid to a direct dependency for the MSSQL contrib module.

Reviewed changes

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

File Description
contrib/drivers/mssql/mssql_convert.go Introduces MSSQL-specific type detection and value conversion for uniqueidentifier to uuid.UUID.
contrib/drivers/mssql/mssql_z_unit_convert_test.go Adds unit tests validating type mapping and correct wire-format UUID decoding behavior.
contrib/drivers/mssql/go.mod Promotes github.com/google/uuid to a direct dependency for this driver module.

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

Comment thread contrib/drivers/mssql/mssql_convert.go
Comment thread contrib/drivers/mssql/mssql_convert.go
SQL Server UNIQUEIDENTIFIER values arrive on the wire as 16 bytes whose
first 8 follow the little-endian COM/Win32 GUID layout while the
remaining 8 are big-endian. The MSSQL driver previously had no override
for this column type, so gdb's default conversion path treated the raw
bytes as a string and returned garbage characters (any caller doing
`row["id"].String()` on a uniqueidentifier column would get mojibake).

This change mirrors the existing pgsql `uuid` handling: add
`CheckLocalTypeForField` and `ConvertValueForLocal` overrides that
detect `uniqueidentifier` (case-insensitive), delegate the byte-order
swap to `mssql.UniqueIdentifier.Scan`, and return a `uuid.UUID`. All
other column types fall through to `Core` unchanged.

Tests cover the wire-format byte swap, the string form (used after a
server-side `CAST AS NVARCHAR(36)`), case-insensitive type matching,
fallthrough behaviour, and an invalid-length error path.
@NickWilde18 NickWilde18 force-pushed the fix/mssql-uniqueidentifier-conversion branch from 98b133b to 8ecf492 Compare April 16, 2026 16:05
@NickWilde18

Copy link
Copy Markdown
Author

Thanks @copilot-pull-request-reviewer for the review. Both points addressed in 8ecf492:

  1. Renamed the mssql import alias to mssqldriver in mssql_convert.go so it no longer collides with the package name and matches what the test file already does.
  2. Replaced the misleading fallback in the Scan error branch with return nil, gerror.Wrapf(err, ...), matching the pgsql driver's pattern. The fallback string was unreachable as you noted.

Removed the now-unused fmt and gconv imports.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 3 out of 3 changed files in this pull request and generated 3 comments.


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

Comment thread contrib/drivers/mssql/mssql_z_unit_convert_test.go Outdated
Comment thread contrib/drivers/mssql/mssql_convert.go Outdated
Comment thread contrib/drivers/mssql/mssql_z_unit_convert_test.go Outdated
@NickWilde18 NickWilde18 force-pushed the fix/mssql-uniqueidentifier-conversion branch 2 times, most recently from 07e62d1 to 245b987 Compare April 20, 2026 02:03
- Refer to go-mssqldb's UniqueIdentifier.Scan explicitly so the docs
  cannot be misread as a symbol on this package.
- Drop the nvarchar(100) fallthrough assertion: it exercised gdb.Core's
  default path with a nil receiver, not the new uniqueidentifier hook,
  and its passing was coincidental to Core's current implementation.
@NickWilde18 NickWilde18 force-pushed the fix/mssql-uniqueidentifier-conversion branch from 245b987 to 69c947d Compare April 20, 2026 02:06
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.

2 participants