Skip to content

Commit

Permalink
feat(generate): DIY method accept range in SQL template (go-gorm#248)
Browse files Browse the repository at this point in the history
* feat:add for range and generated code style

* feat:feat style

* feat:feat style do code review

* feat:add for range usage to readme

* conflict

* feat:feat style

* feat:feat style do code review

* feat:Handled the conflict

* feat:Handled the conflict

* feat:rm test dir

* feat:last feat

* feat:last feat

* feat:last feat

* fix: ignore the check of data in single quotes
  • Loading branch information
idersec authored Nov 30, 2021
1 parent d3026df commit 098f259
Show file tree
Hide file tree
Showing 16 changed files with 927 additions and 517 deletions.
42 changes: 41 additions & 1 deletion README.ZH_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -1639,6 +1639,7 @@ type Method interface {
- `if`/`else if`/`else` the condition accept a bool parameter or operation expression which conforms to Golang syntax.
- `where` The `where` clause will be inserted only if the child elements return something. The key word `and` or `or` in front of clause will be removed. And `and` will be added automatically when there is no junction keyword between query condition clause.
- `Set` The `set` clause will be inserted only if the child elements return something. The `,` in front of columns array will be removed.And `,` will be added automatically when there is no junction keyword between query coulmns.
- `for` The `for` clause traverses an array according to golang syntax and inserts its contents into SQL,supports array of struct.
- `...` Coming soon

###### <span id="if-clause">`If` 子句</span>
Expand Down Expand Up @@ -1730,8 +1731,36 @@ update @@table
where id=@id
```

###### `For` clause

```sql
{{for _,name:=range names}}
// do something here
{{end}}
```

Use case in raw SQL:

```go
// select * from users where id>0 {{for _,name:=range names}} and name=@name{{end}}
methond(names []string) (gen.T,error)
```

Use case in raw SQL template:

```sql
select * from @@table where
{{for index,name:=range names}}
{{if index >0}}
OR
{{end}}
name=@name
{{end}}
```

##### <span id="method-interface-example">方法接口示例</span>


```go
type Method interface {
// Where("name=@name and age=@age")
Expand Down Expand Up @@ -1765,6 +1794,17 @@ type Method interface {
// id=@id
// {{end}}
UpdateName(name string, id int) (gen.RowsAffected,error)

// select * from @@table
// {{where}}
// {{for _,user:=range users}}
// {{if user.Age >18}
// OR [email protected]
// {{end}}
// {{end}}
// {{end}}
FindByOrList(cond bool, id int, key, value string) ([]gen.T, error)

}
```

Expand Down Expand Up @@ -1866,7 +1906,7 @@ gentool -dsn "user:pwd@tcp(127.0.0.1:3306)/database?charset=utf8mb4&parseTime=Tr
## <span id="maintainers">维护者</span>
[@riverchu](https://github.com/riverchu) [@idersec](https://github.com/idersec) [@qqxhb](https://github.com/qqxhb) [@dino-ma](https://github.com/dino-ma)
[@riverchu](https://github.com/riverchu) [@iDer](https://github.com/idersec) [@qqxhb](https://github.com/qqxhb) [@dino-ma](https://github.com/dino-ma)
[@jinzhu](https://github.com/jinzhu)
Expand Down
67 changes: 65 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1665,6 +1665,7 @@ Logical operations must be wrapped in `{{}}`,and end must used `{{end}}`, All te
- `if`/`else if`/`else` the condition accept a bool parameter or operation expression which conforms to Golang syntax.
- `where` The `where` clause will be inserted only if the child elements return something. The key word `and` or `or` in front of clause will be removed. And `and` will be added automatically when there is no junction keyword between query condition clause.
- `Set` The `set` clause will be inserted only if the child elements return something. The `,` in front of columns array will be removed.And `,` will be added automatically when there is no junction keyword between query coulmns.
- `for` The `for` clause traverses an array according to golang syntax and inserts its contents into SQL,supports array of struct.
- `...` Coming soon

###### `If` clause
Expand Down Expand Up @@ -1755,6 +1756,58 @@ update @@table
{{end}}
where id=@id
```
###### `For` clause

```sql
{{for _,name:=range names}}
// do something here
{{end}}
```

Use case in raw SQL:

```go
// select * from users where id>0 {{for _,name:=range names}} and name=@name{{end}}
methond(names []string) (gen.T,error)
```

Use case in raw SQL template:

```sql
select * from @@table
{{where}}
{{for _,user:=range users}}
OR name=@user.Name
{{end}}
{{end}}
```

###### `For` clause

```sql
{{for _,name:=range names}}
// do something here
{{end}}
```

Use case in raw SQL:

```go
// select * from users where id>0 {{for _,name:=range names}} and name=@name{{end}}
methond(names []string) (gen.T,error)
```

Use case in raw SQL template:

```sql
select * from @@table where
{{for index,name:=range names}}
{{if index >0}}
OR
{{end}}
name=@name
{{end}}
```

##### Method interface example

Expand Down Expand Up @@ -1791,7 +1844,17 @@ type Method interface {
// id=@id
// {{end}}
UpdateName(name string, id int) (gen.RowsAffected,error)
}

// select * from @@table
// {{where}}
// {{for _,user:=range users}}
// {{if user.Age >18}
// OR [email protected]
// {{end}}
// {{end}}
// {{end}}
FindByOrList(cond bool, id int, key, value string) ([]gen.T, error)
}
```

#### Unit Test
Expand Down Expand Up @@ -1945,7 +2008,7 @@ gentool -dsn "user:pwd@tcp(127.0.0.1:3306)/database?charset=utf8mb4&parseTime=Tr
## Maintainers
[@riverchu](https://github.com/riverchu) [@idersec](https://github.com/idersec) [@qqxhb](https://github.com/qqxhb) [@dino-ma](https://github.com/dino-ma)
[@riverchu](https://github.com/riverchu) [@iDer](https://github.com/idersec) [@qqxhb](https://github.com/qqxhb) [@dino-ma](https://github.com/dino-ma)
[@jinzhu](https://github.com/jinzhu)
Expand Down
11 changes: 6 additions & 5 deletions generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ func (g *Generator) apply(fc interface{}, structs []*check.BaseStruct) {
panic("gen struct fail")
}

functions, err := check.CheckInterface(readInterface, interfaceStruct, data.Interfaces)
functions, err := check.BuildDiyMethod(readInterface, interfaceStruct, data.Interfaces)
if err != nil {
g.db.Logger.Error(context.Background(), "check interface fail: %v", err)
panic("check interface fail")
Expand Down Expand Up @@ -495,12 +495,13 @@ func (g *Generator) generateBaseStruct() (err error) {
func (g *Generator) output(fileName string, content []byte) error {
result, err := imports.Process(fileName, content, nil)
if err != nil {
errLine, _ := strconv.Atoi(strings.Split(err.Error(), ":")[1])
startLine, endLine := 0, errLine+3
fmt.Println("Format fail:")
line := strings.Split(string(content), "\n")
errLine, _ := strconv.Atoi(strings.Split(err.Error(), ":")[1])
startLine, endLine := -0, len(line)-1
fmt.Println("Format fail:", errLine, err)

for i := startLine; i <= endLine; i++ {
fmt.Println(i+errLine, line[i+errLine])
fmt.Println(i, line[i])
}
return fmt.Errorf("cannot format struct file: %w", err)
}
Expand Down
40 changes: 38 additions & 2 deletions helper/clause.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,16 @@ func joinClause(conds []string, keyword string, deal func(string) string, sep st
}

func trimAll(input string) string {
input = strings.Trim(input, " ")
return trimRight(trimLeft(input))
}

func trimLeft(input string) string {
input = strings.TrimSpace(input)
lowercase := strings.ToLower(input)
switch {
case strings.HasPrefix(lowercase, "and "):
return input[4:]
case strings.HasPrefix(lowercase, "or "):
case strings.HasPrefix(lowercase, "or"):
return input[3:]
case strings.HasPrefix(lowercase, "xor "):
return input[4:]
Expand All @@ -59,6 +63,22 @@ func trimAll(input string) string {
return input
}
}
func trimRight(input string) string {
input = strings.TrimSpace(input)
lowercase := strings.ToLower(input)
switch {
case strings.HasSuffix(lowercase, " and"):
return input[:len(input)-3]
case strings.HasSuffix(lowercase, " or"):
return input[:len(input)-2]
case strings.HasSuffix(lowercase, " xor"):
return input[:len(input)-3]
case strings.HasSuffix(lowercase, ","):
return input[:len(input)-1]
default:
return input
}
}

// whereValue append a new condition with prefix "AND"
func whereValue(value string) string {
Expand All @@ -81,3 +101,19 @@ func whereValue(value string) string {
func setValue(value string) string {
return strings.Trim(value, ", ")
}

func JoinWhereBuilder(src *strings.Builder, whereValue strings.Builder) {
value := trimAll(whereValue.String())
if value != "" {
src.WriteString(" WHERE ")
src.WriteString(value)
}
}

func JoinSetBuilder(src *strings.Builder, setValue strings.Builder) {
value := trimAll(setValue.String())
if value != "" {
src.WriteString(" SET ")
src.WriteString(value)
}
}
Loading

0 comments on commit 098f259

Please sign in to comment.