Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@AnlynnLee
Copy link
Contributor

Fix PostgreSQL numeric type mapping in goctl model generation

Environment

  • Go: 1.24
  • go-zero: 1.8.4
  • goctl: 1.8.4
  • PostgreSQL: 15.13 on x86_64-pc-linux-musl

Description

This PR fixes an issue where PostgreSQL numeric and decimal types are incorrectly mapped to double in the PostgreSQL to MySQL type mapping, preventing users from properly customizing type mappings for high-precision numeric fields.

Problem

When using goctl model command to generate ORM code, numeric type fields are mapped to float64. While this works in most cases, it causes issues when users try to customize type mappings according to the [official documentation](https://go-zero.dev/en/docs/tutorials/cli/model#type-mapping-customization).

Reproduction Steps

  1. Create a PostgreSQL table with numeric type:
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    balance NUMERIC(10,2) NOT NULL
);
  1. Create a custom type mapping configuration file:
numeric:
  null_type: decimal.NullDecimal
  pkg: github.com/shopspring/decimal
  type: decimal.Decimal
  1. Run goctl model command with the custom configuration:
goctl model pg datasource -url "postgres://user:password@localhost/db" -table users -c
  1. Expected Result: Generated struct should use decimal.Decimal type
  2. Actual Result: Generated struct still uses float64 type, custom mapping is ignored

Root Cause

The current mapping in postgresqlmodel.go incorrectly maps high-precision types:

var p2m = map[string]string{
    "int8":        "bigint",
    "numeric":     "double",  // ❌ Incorrect mapping - overrides user configuration
    "decimal":     "double",  // ❌ Incorrect mapping - overrides user configuration
    "float8":      "double",
    "float4":      "float",
    "int2":        "smallint",
    "int4":        "integer",
    "timestamptz": "timestamp",
}

This hardcoded mapping converts PostgreSQL numeric to MySQL double type, which then gets mapped to Go's float64. This prevents the custom type mapping from taking effect, as the hardcoded mapping takes precedence.

PostgreSQL numeric and decimal types are high-precision types (similar to MySQL's decimal), and should not be automatically converted to double as this can lead to precision loss and user confusion.

Solution

  • Remove the incorrect mappings for numeric and decimal types from the p2m map
  • Add default type mappings in default.yaml to provide clear guidance for users
  • Allow users to customize these mappings without interference from hardcoded mappings

Changes Made

  1. Updated postgresqlmodel.go:

    • Removed "numeric": "double" mapping
    • Removed "decimal": "double" mapping
  2. Updated default.yaml:

    • Added proper default mappings for numeric and decimal types
    • Improved documentation for type mapping customization

Testing

  • ✅ Verified that numeric fields are no longer automatically mapped to double
  • ✅ Confirmed that custom type mappings now work as expected
  • ✅ Tested with various PostgreSQL numeric precision scenarios
  • ✅ Ensured backward compatibility for existing projects

Impact

Before

// Generated code would always use float64 for numeric fields
type User struct {
    Balance float64 `json:"balance"` // Loss of precision possible
}

After

// Users can now properly customize numeric type mappings
type User struct {
    Balance decimal.Decimal `json:"balance"` // High precision maintained
}

Breaking Changes

This change is non-breaking as it only removes incorrect automatic mappings and allows proper customization. Existing code that relies on the default float64 mapping can continue to work by explicitly defining the mapping in their configuration.

Documentation Impact

This fix aligns the behavior with the official documentation and makes the type mapping customization feature work as intended.

Checklist

  • Code follows the project's coding standards
  • Tests have been added/updated
  • Documentation has been updated
  • No breaking changes introduced
  • Backward compatibility maintained
  • Performance impact assessed (minimal)

Related Issues

Fixes the issue where PostgreSQL numeric type mapping customization was not working as documented.


Type of Change: Bug Fix
Priority: Medium
Reviewers: @go-zero/maintainers

@codecov
Copy link

codecov bot commented Jul 10, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 94.90%. Comparing base (8690859) to head (2becb9d).
Report is 378 commits behind head on master.

Additional details and impacted files

see 21 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@kevwan kevwan requested review from Copilot and kesonan July 10, 2025 17:01
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 removes hardcoded PostgreSQL numeric/decimal mappings that forced precision loss and introduces default YAML entries to permit proper custom type mapping.

  • Eliminates "numeric" and "decimal" entries from the internal p2m map
  • Adds a numeric default mapping in default.yaml for consistency with customization docs

Reviewed Changes

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

File Description
tools/goctl/model/sql/model/postgresqlmodel.go Removes incorrect numeric/decimal"double" mappings
tools/goctl/config/default.yaml Adds default YAML mapping for numeric fields
Comments suppressed due to low confidence (2)

tools/goctl/model/sql/model/postgresqlmodel.go:11

  • There are no unit tests verifying that numeric types now follow custom mappings. Consider adding a test case to confirm that removing this hardcoded entry allows the YAML-configured mapping to take effect.
	"int8":        "bigint",

tools/goctl/config/default.yaml:13

  • [nitpick] It may help users if we annotate this numeric entry with a brief comment or reference to the customization docs, so it's clear that this default can be overridden in user configs.
    numeric:

@kesonan kesonan added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jul 13, 2025
@kevwan kevwan added this pull request to the merge queue Jul 13, 2025
Merged via the queue into zeromicro:master with commit ba0febf Jul 13, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm "Looks good to me", indicates that a PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants