fix(#40): remove illegal literal default on TEXT column image_url

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
QiuSW
2026-08-19 14:10:24 +08:00
co-authored by Claude Opus 5
parent 40d2862c1a
commit 45e8c1285d
2 changed files with 30 additions and 1 deletions
@@ -3,6 +3,7 @@ package migrations_test
import (
"fmt"
"reflect"
"regexp"
"strings"
"sync"
"testing"
@@ -333,3 +334,28 @@ func TestShopeeProductSalePriceMustNotBeNegative(t *testing.T) {
t.Fatal("negative sale price was accepted")
}
}
// MySQL rejects a literal DEFAULT clause on TEXT/BLOB/JSON columns
// ("BLOB, TEXT, GEOMETRY or JSON column '...' can't have a default value").
// SQLite does not enforce this, so the SQLite-backed tests in this file never
// catch it; ShopeeProduct.ImageURL hit exactly this error against a live
// MySQL 8.4 database before this test was added. This scans every model field
// via reflection instead of requiring a MySQL connection.
func TestMySQLTextJSONBlobColumnsHaveNoLiteralDefault(t *testing.T) {
modelTypes := []any{
&models.AgentDevice{}, &models.PDDProduct{}, &models.CollectionRule{}, &models.CollectionTask{},
&models.CollectionDimension{}, &models.CollectionDimensionValue{}, &models.CollectionColorPrice{},
&models.CollectionSKU{}, &models.CollectionSKUValue{}, &models.ShopeeProduct{},
}
typePattern := regexp.MustCompile(`type:(text|json|blob)`)
for _, model := range modelTypes {
value := reflect.TypeOf(model).Elem()
for i := 0; i < value.NumField(); i++ {
tag := value.Field(i).Tag.Get("gorm")
if typePattern.MatchString(strings.ToLower(tag)) && strings.Contains(tag, "default:") {
t.Errorf("%s.%s: TEXT/JSON/BLOB column must not carry a literal gorm default tag (MySQL rejects it): %s",
value.Name(), value.Field(i).Name, tag)
}
}
}
}
+4 -1
View File
@@ -252,7 +252,10 @@ type ShopeeProduct struct {
// ImageURL holds the SYB-provided reference image URL. It is written by the
// #41 import and may be overridden manually; the product domain never joins
// syb_products at read time.
ImageURL string `json:"imageUrl" gorm:"type:text;not null;default:''"`
// MySQL rejects a literal DEFAULT on TEXT/BLOB/JSON columns, so this stays
// NOT NULL without a DB-level default; Go's zero value ("") is inserted
// explicitly on every create, which satisfies NOT NULL without needing one.
ImageURL string `json:"imageUrl" gorm:"type:text;not null"`
// SalePriceCent is the reference selling price in integer cents, consistent
// with the priceCent convention from #31. It is the value seen at the latest
// import or manual edit, not an authoritative transaction price.