diff --git a/orm/models_utils.go b/orm/models_utils.go index ec11d516..1dc17f81 100644 --- a/orm/models_utils.go +++ b/orm/models_utils.go @@ -192,10 +192,10 @@ func parseStructTag(data string, attrs *map[string]bool, tags *map[string]string tag := make(map[string]string) for _, v := range strings.Split(data, defaultStructTagDelim) { v = strings.TrimSpace(v) - if supportTag[v] == 1 { - attr[v] = true + if t := strings.ToLower(v); supportTag[t] == 1 { + attr[t] = true } else if i := strings.Index(v, "("); i > 0 && strings.Index(v, ")") == len(v)-1 { - name := v[:i] + name := t[:i] if supportTag[name] == 2 { v = v[i+1 : len(v)-1] tag[name] = v diff --git a/orm/orm_test.go b/orm/orm_test.go index 11f6bd56..c029999f 100644 --- a/orm/orm_test.go +++ b/orm/orm_test.go @@ -2117,3 +2117,47 @@ func TestUintPk(t *testing.T) { dORM.Delete(u) } + +func TestSnake(t *testing.T) { + cases := map[string]string{ + "i": "i", + "I": "i", + "iD": "i_d", //01 + "ID": "id", //11 pre+curent=2 + "NO": "no", //11 + "NOO": "noo", //111 10 + "NOOooOOoo": "noo_oo_oo_oo", //111_00_11_00 + "OrderNO": "order_no", //10000_11 + "tagName": "tag_name", //000_1000 + "tag_Name": "tag_name", + "tag_name": "tag_name", + "_tag_name": "_tag_name", + "tag_666name": "tag_666name", + "tag_666Name": "tag_666_name", + } + for name, want := range cases { + got := snakeString(name) + throwFail(t, AssertIs(got, want)) + } +} + +func TestIgnoreCaseTag(t *testing.T) { + type testTagModel struct { + ID int `orm:"pk"` + NOO string `orm:"column(n)"` + Name01 string `orm:"NULL"` + Name02 string `orm:"COLUMN(Name)"` + Name03 string `orm:"Column(name)"` + } + RegisterModel(&testTagModel{}) + info, ok := modelCache.get("test_tag_model") + throwFail(t, AssertIs(ok, true)) + throwFail(t, AssertNot(info, nil)) + if t == nil { + return + } + throwFail(t, AssertIs(info.fields.GetByName("NOO").column, "n")) + throwFail(t, AssertIs(info.fields.GetByName("Name01").null, true)) + throwFail(t, AssertIs(info.fields.GetByName("Name02").column, "Name")) + throwFail(t, AssertIs(info.fields.GetByName("Name03").column, "name")) +} diff --git a/orm/utils.go b/orm/utils.go index 99437c7b..e3cd8ad6 100644 --- a/orm/utils.go +++ b/orm/utils.go @@ -181,18 +181,36 @@ func ToInt64(value interface{}) (d int64) { return } -// snake string, XxYy to xx_yy +// snake string, XxYy to xx_yy , XxYY to xx_yy func snakeString(s string) string { data := make([]byte, 0, len(s)*2) - j := false num := len(s) for i := 0; i < num; i++ { d := s[i] - if i > 0 && d >= 'A' && d <= 'Z' && j { - data = append(data, '_') - } - if d != '_' { - j = true + if i > 0 && d != '_' && s[i-1] != '_' { + need := false + // upper as 1, lower as 0 + // XX -> 11 -> 11 + // Xx -> 10 -> 10 + // XxYyZZ -> 101011 -> 10_10_11 + isUpper := d >= 'A' && d <= 'Z' + preIsUpper := s[i-1] >= 'A' && s[i-1] <= 'Z' + if isUpper { + // like : xxYy + if !preIsUpper { + need = true + } + } else { + if preIsUpper { + // ignore "Xy" in "xxXyy" + if i-2 >= 0 && s[i-2] >= 'A' && s[i-2] <= 'Z' { + need = true + } + } + } + if need { + data = append(data, '_') + } } data = append(data, d) }