-
-
Notifications
You must be signed in to change notification settings - Fork 349
Description
Index order in generated models is non-deterministic
Problem
When generating GORM models using gorm.io/gen, the order of indexes in the generated gorm tags is non-deterministic. This causes the generated code to differ between CI and local environments, even when the database schema is identical.
Example
The same database schema can generate different code:
Run 1:
TenantID string `gorm:"column:tenant_id;type:uuid;not null;index:idx_payout_tenant_id,priority:1;index:idx_payout_tenant_payment_at,priority:2;comment:tenant ID" json:"tenant_id"`Run 2:
TenantID string `gorm:"column:tenant_id;type:uuid;not null;index:idx_payout_tenant_payment_at,priority:2;index:idx_payout_tenant_id,priority:1;comment:tenant ID" json:"tenant_id"`The indexes are functionally equivalent, but the order differs, causing unnecessary diffs in version control and CI failures.
Root Cause
The issue occurs in internal/model/tbl_column.go in the buildGormTag() method. When iterating over c.Indexes, the order depends on how PostgreSQL returns index information, which is based on OID (Object ID) order. This order can vary between database instances or even between queries on the same database.
The relevant code:
for _, idx := range c.Indexes {
// ...
tag.Append(field.TagKeyGormIndex, fmt.Sprintf("%s,priority:%d", idx.Name(), idx.Priority))
}Since c.Indexes is populated from PostgreSQL's system catalogs without explicit ordering, the iteration order is non-deterministic.
Environment
- GORM gen version: v0.3.27
- PostgreSQL version: 17.7
- Go version: 1.25.0
- Database: PostgreSQL
Expected Behavior
The index order in generated models should be deterministic and consistent across all environments. Ideally, indexes should be sorted alphabetically by name to ensure consistent output.
Proposed Solution
Sort the indexes by name before iterating over them in the buildGormTag() method. This ensures that the generated code is always consistent, regardless of the order returned by PostgreSQL.
Impact
This issue affects:
- CI/CD pipelines that check if generated code is up-to-date
- Teams working on the same codebase where generated files are committed
- Any workflow that relies on deterministic code generation
Workaround
Currently, we work around this by:
- Using a post-processing script to normalize index order after generation
- Commenting out the generation check in CI until the issue is resolved
However, this is not ideal and adds maintenance overhead.
Additional Context
This issue is particularly noticeable when:
- Multiple indexes exist on the same column
- Working with composite indexes
- Running migrations in different environments (CI vs local)
The problem becomes more apparent when using CI to verify that generated code matches the current database schema, as the check fails due to non-functional differences in index order.