-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathexpression_builder.go
92 lines (84 loc) · 2.07 KB
/
expression_builder.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
package dynmgrm
import (
"fmt"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"reflect"
"slices"
)
// expressionBuilder is a function that builds a clause.Expression
type expressionBuilder[T clause.Expression] func(expression T, statement *gorm.Statement)
// toClauseBuilder converts expressionBuilder to clause.ClauseBuilder
func toClauseBuilder[T clause.Expression](xpBuilder expressionBuilder[T]) clause.ClauseBuilder {
return func(c clause.Clause, builder clause.Builder) {
xp, ok := c.Expression.(T)
if !ok {
return
}
statement, ok := builder.(*gorm.Statement)
if !ok {
return
}
xpBuilder(xp, statement)
}
}
// buildValuesClause builds VALUES clause
func buildValuesClause(values clause.Values, stmt *gorm.Statement) {
columns := values.Columns
if len(columns) <= 0 {
return
}
// PartiQL for DynamoDB does not support multiple rows in VALUES clause
items := values.Values[0]
stmt.WriteString("VALUE ")
stmt.WriteByte('{')
prfl := stmt.Schema.PrimaryFieldDBNames
for i, column := range columns {
v := items[i]
if isZeroValue(v) && !slices.Contains[[]string](prfl, column.Name) {
continue
}
if i > 0 {
stmt.WriteString(", ")
}
stmt.WriteString(fmt.Sprintf(`'%s'`, column.Name))
stmt.WriteString(" : ")
stmt.AddVar(stmt, v)
}
stmt.WriteByte('}')
}
// buildSetClause builds SET clause
func buildSetClause(set clause.Set, stmt *gorm.Statement) {
if len(set) <= 0 {
return
}
prfl := stmt.Schema.PrimaryFieldDBNames
for idx, assignment := range set {
asgcol := assignment.Column.Name
if slices.Contains[[]string](prfl, asgcol) {
continue
}
if idx > 0 {
stmt.WriteByte(' ')
}
stmt.WriteString("SET ")
stmt.WriteQuoted(asgcol)
stmt.WriteByte('=')
asgv := assignment.Value
switch asgv := asgv.(type) {
case functionForPartiQLUpdates:
valuer := asgv.bindVariable()
stmt.WriteString(asgv.expression(stmt.DB, asgcol))
stmt.AddVar(stmt, valuer)
stmt.WriteByte(')')
continue
}
stmt.AddVar(stmt, asgv)
}
}
func isZeroValue(v interface{}) bool {
if v == nil {
return true
}
return reflect.ValueOf(v).IsZero()
}