/
operator.go
129 lines (121 loc) · 3.79 KB
/
operator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package jorm
import (
"errors"
"go/ast"
)
type RalationalOperator interface {
BuildElementExpression(columnName string, elemType ast.Expr, paramName string, paramType ast.Expr) string
}
type ralationalOperator string
var (
OP_EQ RalationalOperator = ralationalOperator("Eq") // A == B
OP_LT RalationalOperator = ralationalOperator("Lt") // A < B
OP_GT RalationalOperator = ralationalOperator("Gt") // A > B
OP_IN RalationalOperator = ralationalOperator("In") // A in (strings.join([B,C,D],","))
OP_NOTEQ RalationalOperator = ralationalOperator("NotEq") // A <> B
OP_LE RalationalOperator = ralationalOperator("Le") // A <= B
OP_GE RalationalOperator = ralationalOperator("Ge") // A >= B
OP_NOTIN RalationalOperator = ralationalOperator("NotIn") // A not in B
)
func NewRalationalOperator(str string) RalationalOperator {
var op = ralationalOperator(str)
switch op {
case OP_EQ, OP_LT, OP_GT, OP_IN, OP_NOTEQ, OP_LE, OP_GE, OP_NOTIN:
return op
default:
panic("invalid operator: " + str)
}
}
/*
#check1:
- if a slice is here, the pattern is something like: name in (?,?,?,?,?,?,?,?,?,?,?) so the sql is dynamic,
- the count of ? should be the length of the slice (or say can be inferred from names string[])
- so the code would be something like:
func (b *bookRepository) FindByNameIn(names []string) (books []entity.Book, err error){
var q = make([]string, 0, len(names))
for range names {
q = append(q, "?")
}
...
}
rows, err := db.Query("SELECT name,author FROM book where id in ("+strings.Join(q, ",")+")", names)
#check2:
- get the corresponding type in entity of the names[i]
- get the param type or get underlying type if the param is slice
- jorm require that the two types must match
#check3:
- if the method name is like FindByNameIn or FindByNameNotIn, the param type must be Slice
- and vice versa
*/
//TODO
func (op ralationalOperator) BuildElementExpression(columnName string, elemType ast.Expr, paramName string, paramType ast.Expr) string {
if columnName == "" {
panic("columnName is empty")
}
if op == OP_IN || op == OP_NOTIN {
var paramArrayType *ast.ArrayType
var paramIdent *ast.Ident
var elemIdent *ast.Ident
var ok bool
paramArrayType, ok = paramType.(*ast.ArrayType)
if !ok {
panic("wrong param type")
}
paramIdent, ok = paramArrayType.Elt.(*ast.Ident)
if !ok {
panic("wrong param type")
}
elemIdent, ok = elemType.(*ast.Ident)
if !ok {
panic("wrong element type")
}
if paramIdent.Name != elemIdent.Name {
panic("element type doesn't match param type")
}
return op.buildMultipleExp(columnName, paramName)
} else {
var paramIdent *ast.Ident
var elemIdent *ast.Ident
var ok bool
paramIdent, ok = paramType.(*ast.Ident)
if !ok {
panic("wrong param type")
}
elemIdent, ok = elemType.(*ast.Ident)
if !ok {
panic("wrong element type")
}
if paramIdent.Name != elemIdent.Name {
panic("type doesn't match")
}
return op.buildSingleValueExp(columnName)
}
}
func (op ralationalOperator) buildSingleValueExp(column string) string {
switch op {
case OP_EQ:
return `"` + column + " = ?" + `"`
case OP_LT:
return `"` + column + " < ?" + `"`
case OP_GT:
return `"` + column + " > ?" + `"`
case OP_NOTEQ:
return `"` + column + " <> ?" + `"`
case OP_LE:
return `"` + column + " <= ?" + `"`
case OP_GE:
return `"` + column + " >= ?" + `"`
default:
panic(errors.New("invalid operator:" + string(op) + " for " + column))
}
}
func (op ralationalOperator) buildMultipleExp(column string, paramName string) string {
switch op {
case OP_IN:
return `jormgen.AddIn("` + column + `", ` + paramName + `, queryParams)`
case OP_NOTIN:
return `jormgen.AddNotIn("` + column + `", ` + paramName + `, queryParams)`
default:
panic("invalid operator:" + string(op) + " for " + column)
}
}