Skip to content

Commit 0972442

Browse files
committed
增加slice参数类型支持,更好的支持多条记录插入
1 parent 7b327e7 commit 0972442

File tree

8 files changed

+187
-49
lines changed

8 files changed

+187
-49
lines changed

parsing/xml/dynamics.go

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"fmt"
1414
"github.com/xfali/gobatis/logging"
1515
"github.com/xfali/gobatis/parsing"
16-
"github.com/xfali/gobatis/reflection"
1716
"strconv"
1817
"strings"
1918
"unicode"
@@ -138,6 +137,20 @@ func Compare(src string, getFunc func(key string) string) bool {
138137
return false
139138
}
140139

140+
func getKey(src string) string {
141+
if src == "" {
142+
return ""
143+
}
144+
if src[:1] == "{" {
145+
index := strings.Index(src, "}")
146+
if index == -1 {
147+
return src
148+
}
149+
return src[1:index]
150+
}
151+
return src
152+
}
153+
141154
func getValueFromFunc(src string, getFunc func(key string) string) string {
142155
if src == "" {
143156
return ""
@@ -256,26 +269,30 @@ func (de *Foreach) Format(getFunc func(key string) string) string {
256269
return ""
257270
}
258271

259-
listStr := getValueFromFunc(de.Collection, getFunc)
260-
if listStr == "" || listStr == "nil" {
261-
return ""
262-
}
263-
264-
elems := reflection.ParseSliceParamString(listStr)
272+
collectionKey := getKey(de.Collection)
273+
value := getValueFromFunc(de.Collection, getFunc)
274+
//if value == "" || value == "nil" {
275+
// return ""
276+
//}
277+
//
278+
//elems := reflection.ParseSliceParamString(value)
279+
//length := len(elems)
280+
length, _ := strconv.Atoi(value)
265281
ret := strings.Builder{}
266282
ret.WriteString(de.Open)
267-
itemStr := fmt.Sprintf("#{%s}", de.Item)
268283
indexStr := fmt.Sprintf("#{%s}", de.Index)
269-
length := len(elems)
284+
270285
originData := strings.TrimSpace(de.Data)
271286
realStr := ""
272-
for i, v := range elems {
273-
realStr = strings.Replace(originData, itemStr, v, -1)
287+
i := 0
288+
for i < length {
289+
realStr = strings.Replace(originData, de.Item, fmt.Sprintf("%s[%d]", collectionKey, i), -1)
274290
realStr = strings.Replace(realStr, indexStr, strconv.Itoa(i), -1)
275291
ret.WriteString(realStr)
276292
if i < length-1 {
277293
ret.WriteString(de.Separator)
278294
}
295+
i++
279296
}
280297
ret.WriteString(de.Close)
281298

reflection/parseparam.go

Lines changed: 56 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
package reflection
1010

1111
import (
12+
"fmt"
1213
"reflect"
1314
"strconv"
1415
"strings"
@@ -34,11 +35,11 @@ func ParseParams(params ...interface{}) map[string]interface{} {
3435

3536
func (parser *paramParser) innerParse(params ...interface{}) {
3637
for i := range params {
37-
parser.parseOne(params[i])
38+
parser.parseOne("", params[i])
3839
}
3940
}
4041

41-
func (parser *paramParser) parseOne(v interface{}) {
42+
func (parser *paramParser) parseOne(parentKey string, v interface{}) {
4243
rt := reflect.TypeOf(v)
4344
rv := reflect.ValueOf(v)
4445

@@ -48,47 +49,53 @@ func (parser *paramParser) parseOne(v interface{}) {
4849
}
4950

5051
if IsSimpleType(rt) {
51-
parser.ret[strconv.Itoa(parser.index)] = v
52-
parser.index++
52+
if parentKey == "" {
53+
parser.ret[parentKey+strconv.Itoa(parser.index)] = v
54+
parser.index++
55+
} else {
56+
parser.ret[parentKey[:len(parentKey)-1]] = v
57+
}
5358
} else if rt.Kind() == reflect.Struct {
5459
oi, _ := GetStructInfo(v)
5560
structMap := oi.MapValue()
5661
for key, value := range structMap {
57-
parser.ret[structKey(oi, key)] = value
62+
parser.ret[parentKey+structKey(oi, key)] = value
5863
}
5964
} else if rt.Kind() == reflect.Slice {
60-
//l := rv.Len()
61-
//for i := 0; i < l; i++ {
62-
// elemV := rv.Index(i)
63-
// if !elemV.CanInterface() {
64-
// elemV = reflect.Indirect(elemV)
65-
// }
66-
// parser.parseOne(elemV.Interface())
67-
//}
6865
l := rv.Len()
69-
builder := strings.Builder{}
7066
for i := 0; i < l; i++ {
7167
elemV := rv.Index(i)
7268
if !elemV.CanInterface() {
7369
elemV = reflect.Indirect(elemV)
7470
}
75-
if elemV.Kind() == reflect.String {
76-
builder.WriteString(elemV.String())
77-
} else {
78-
var str string
79-
if SafeSetValue(reflect.ValueOf(&str), elemV.Interface()) {
80-
builder.WriteString(str)
81-
} else {
82-
//log
83-
}
84-
}
85-
86-
if i < l-1 {
87-
builder.WriteString(slice_param_separator)
88-
}
71+
parser.parseOne(fmt.Sprintf("%s%d[%d].", parentKey, parser.index, i), elemV.Interface())
8972
}
90-
parser.ret[strconv.Itoa(parser.index)] = builder.String()
73+
parser.ret[strconv.Itoa(parser.index)] = l
9174
parser.index++
75+
//l := rv.Len()
76+
//builder := strings.Builder{}
77+
//for i := 0; i < l; i++ {
78+
// elemV := rv.Index(i)
79+
// if !elemV.CanInterface() {
80+
// elemV = reflect.Indirect(elemV)
81+
// }
82+
// if elemV.Kind() == reflect.String {
83+
// builder.WriteString(elemV.String())
84+
// } else {
85+
// var str string
86+
// if SafeSetValue(reflect.ValueOf(&str), elemV.Interface()) {
87+
// builder.WriteString(str)
88+
// } else {
89+
// //log
90+
// }
91+
// }
92+
//
93+
// if i < l-1 {
94+
// builder.WriteString(slice_param_separator)
95+
// }
96+
//}
97+
//parser.ret[strconv.Itoa(parser.index)] = builder.String()
98+
//parser.index++
9299
} else if rt.Kind() == reflect.Map {
93100
keys := rv.MapKeys()
94101
for _, key := range keys {
@@ -99,7 +106,7 @@ func (parser *paramParser) parseOne(v interface{}) {
99106
if !value.CanInterface() {
100107
value = reflect.Indirect(value)
101108
}
102-
parser.ret[key.String()] = value
109+
parser.ret[parentKey+key.String()] = value
103110
}
104111
}
105112
}
@@ -110,6 +117,25 @@ func ParseSliceParamString(src string) []string {
110117
return strings.Split(src, slice_param_separator)
111118
}
112119

120+
func (parser *paramParser) setSliceValue(parentKey string) string {
121+
key := fmt.Sprintf("%s%d[", parentKey, parser.index)
122+
builder := strings.Builder{}
123+
parser.ret[strconv.Itoa(parser.index)] = builder.String()
124+
for k := range parser.ret {
125+
if strings.Index(k, key) == 0 {
126+
builder.WriteString(k)
127+
builder.WriteString(slice_param_separator)
128+
}
129+
}
130+
131+
s := builder.String()
132+
if len(s) > 7 {
133+
return s[:len(s)-7]
134+
} else {
135+
return s
136+
}
137+
}
138+
113139
func structKey(oi *StructInfo, field string) string {
114140
return oi.Name + "." + field
115141
}

test/cmd/template/test_table_mapper.tmpl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
{{/*This file was generated by xfali/gobatis-cmd at*/}}
2+
{{/*2020-02-07 11:43:44.4379882 +0800 CST m=+0.092005301*/}}
3+
14
{{define "selectTestTable"}}
25
SELECT "id","username","password","createtime" FROM "test_table"
36
{{where (ne .Id 0) "AND" "id" .Id "" | where (ne .Username "") "AND" "username" .Username | where (ne .Password "") "AND" "password" .Password | where (ne .Createtime ) "AND" "createtime" .Createtime}}
@@ -7,7 +10,6 @@ SELECT "id","username","password","createtime" FROM "test_table"
710
INSERT INTO "test_table"("id","username","password","createtime")
811
VALUES(
912
{{.Id}}, '{{.Username}}', '{{.Password}}', {{.Createtime}})
10-
RETURNING ID
1113
{{end}}
1214

1315
{{define "updateTestTable"}}

test/cmd/test_table.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//This file was generated by xfali/gobatis-cmd at
2+
//2020-02-07 11:43:44.4189871 +0800 CST m=+0.073004201
3+
14
package test_package
25

36
import "time"

test/cmd/test_table_proxy.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//This file was generated by xfali/gobatis-cmd at
2+
//2020-02-07 11:43:44.4459887 +0800 CST m=+0.100005801
3+
14
package test_package
25

36
import (
@@ -7,7 +10,7 @@ import (
710
func init() {
811
modelV := TestTable{}
912
gobatis.RegisterModel(&modelV)
10-
//gobatis.RegisterMapperFile("./xml/test_table_mapper.xml")
13+
gobatis.RegisterTemplateFile("./template/test_table_mapper.tmpl")
1114
}
1215

1316
func SelectTestTable(sess *gobatis.Session, model TestTable) ([]TestTable, error) {

test/cmd/xml/test_table_mapper.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
<!--This file was generated by xfali/gobatis-cmd at -->
2+
<!--2020-02-07 11:45:05.5246261 +0800 CST m=+0.099005701-->
3+
14
<mapper namespace="test_package.TestTable">
25
<sql id="columns_id">"id","username","password","createtime"</sql>
36

@@ -29,7 +32,6 @@
2932
#{TestTable.password},
3033
#{TestTable.createtime}
3134
)
32-
RETURNING ID
3335
</insert>
3436

3537
<update id="updateTestTable">

test/reflection_test.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,33 @@ func TestReflectionParseSlice(t *testing.T) {
169169
}
170170
for k, v := range ret {
171171
t.Logf("complex key : %s value : %v", k, v)
172-
elems := reflection.ParseSliceParamString(v.(string))
173-
for _, e := range elems {
174-
t.Logf("slice elem %v\n", e)
175-
}
172+
//elems := reflection.ParseSliceParamString(v.(string))
173+
//for _, e := range elems {
174+
// t.Logf("slice elem %v\n", e)
175+
//}
176+
}
177+
}
178+
179+
func TestReflectionParseStructSlice(t *testing.T) {
180+
ret := reflection.ParseParams([]testParseStruct{
181+
{
182+
Username: "user1",
183+
Password: "pw1",
184+
},
185+
{
186+
Username: "user2",
187+
Password: "pw2",
188+
},
189+
})
190+
if len(ret) == 0 {
191+
t.Fail()
192+
}
193+
for k, v := range ret {
194+
t.Logf("complex key : %s value : %v", k, v)
195+
//elems := reflection.ParseSliceParamString(v.(string))
196+
//for _, e := range elems {
197+
// t.Logf("slice elem %v\n", e)
198+
//}
176199
}
177200
}
178201

test/xmlparse_test.go

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,69 @@ func TestXmlDynamicForeach(t *testing.T) {
386386
params := []string{
387387
"first", "second",
388388
}
389-
ret := m.Replace(params)
389+
ret, err := m.ParseMetadata("mysql", params)
390+
if err != nil {
391+
t.Fatal(err)
392+
}
393+
t.Logf("arg first : %s\n", ret)
394+
395+
})
396+
}
397+
398+
func TestXmlDynamicForeach2(t *testing.T) {
399+
src := `INSERT INTO TEST_TABLE(id, username, password) VALUES(
400+
<foreach item="item" index="index" collection="{0}"
401+
open="(" separator="," close=")">
402+
#{item}
403+
</foreach>
404+
)
405+
`
406+
logging.SetLevel(logging.DEBUG)
407+
m, err := xml.ParseDynamic(src, nil)
408+
if err != nil {
409+
t.Fatal(err)
410+
}
411+
t.Run("foreach first", func(t *testing.T) {
412+
params := []string{
413+
"first", "second",
414+
}
415+
ret, err := m.ParseMetadata("mysql", params)
416+
if err != nil {
417+
t.Fatal(err)
418+
}
419+
t.Logf("arg first : %s\n", ret)
420+
421+
})
422+
}
423+
424+
func TestXmlDynamicForeach3(t *testing.T) {
425+
src := `INSERT INTO TEST_TABLE(id, username, password) VALUES(
426+
<foreach item="item" index="index" collection="{0}"
427+
open="" separator="," close="">
428+
(#{item.testParseStruct.Username}, #{item.testParseStruct.Password})
429+
</foreach>
430+
)
431+
`
432+
logging.SetLevel(logging.DEBUG)
433+
m, err := xml.ParseDynamic(src, nil)
434+
if err != nil {
435+
t.Fatal(err)
436+
}
437+
t.Run("foreach first", func(t *testing.T) {
438+
params := []testParseStruct{
439+
{
440+
Username: "user1",
441+
Password: "pw1",
442+
},
443+
{
444+
Username: "user2",
445+
Password: "pw2",
446+
},
447+
}
448+
ret, err := m.ParseMetadata("mysql", params)
449+
if err != nil {
450+
t.Fatal(err)
451+
}
390452
t.Logf("arg first : %s\n", ret)
391453

392454
})

0 commit comments

Comments
 (0)