Passed
Pull Request — master (#10)
by eval
01:42
created

dynamodb.XUpdateCondition.NewCondition   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nop 0
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
package dynamodb
2
3
import (
4
	"errors"
5
	"fmt"
6
7
	"github.com/aws/aws-sdk-go-v2/service/dynamodb/expression"
8
)
9
10
// XConditions is to build Expression Condition for Query/Scan/Update operation.
11
type XConditions struct {
12
	KeyConditions []XCondition
13
	Conditions    []XCondition
14
	Filters       []XCondition
15
	Updates       []XUpdateCondition
16
	Projections   []string
17
}
18
19
func (x XConditions) hasValue() bool {
20
	switch {
21
	case len(x.KeyConditions) != 0,
22
		len(x.Conditions) != 0,
23
		len(x.Filters) != 0,
24
		len(x.Projections) != 0:
25
		return true
26
	}
27
	return false
28
}
29
30
func (x XConditions) Build() (expression.Expression, error) {
0 ignored issues
show
introduced by
exported method XConditions.Build should have comment or be unexported
Loading history...
31
	b := expression.NewBuilder()
32
33
	if len(x.KeyConditions) != 0 {
34
		kc, err := x.KeyConditions[0].KeyCondition()
35
		if err != nil {
36
			return expression.Expression{}, err
37
		}
38
		// for multiple key conditions
39
		if len(x.KeyConditions) > 1 {
40
			for _, v := range x.KeyConditions[1:] {
41
				kc2, err := v.KeyCondition()
42
				if err != nil {
43
					return expression.Expression{}, err
44
				}
45
				kc = kc.And(kc2)
46
			}
47
		}
48
		b = b.WithKeyCondition(kc)
49
	}
50
51
	if len(x.Conditions) != 0 {
52
		cond, err := x.Conditions[0].Condition()
53
		if err != nil {
54
			return expression.Expression{}, err
55
		}
56
57
		// for multiple conditions
58
		if len(x.Conditions) > 1 {
59
			for _, v := range x.Conditions[1:] {
60
				cond2, err := v.Condition()
61
				if err != nil {
62
					return expression.Expression{}, err
63
				}
64
				if v.IsNOT {
65
					cond2 = cond2.Not()
66
				}
67
68
				switch {
69
				case v.IsOR:
70
					cond = cond.Or(cond2)
71
				default:
72
					cond = cond.And(cond2)
73
				}
74
			}
75
		}
76
		b = b.WithCondition(cond)
77
	}
78
79
	if len(x.Filters) != 0 {
80
		filt, err := x.Filters[0].Condition()
81
		if err != nil {
82
			return expression.Expression{}, err
83
		}
84
85
		// for multiple conditions
86
		if len(x.Filters) > 1 {
87
			for _, v := range x.Filters[1:] {
88
				filt2, err := v.Condition()
89
				if err != nil {
90
					return expression.Expression{}, err
91
				}
92
				if v.IsNOT {
93
					filt2 = filt2.Not()
94
				}
95
96
				switch {
97
				case v.IsOR:
98
					filt = filt.Or(filt2)
99
				default:
100
					filt = filt.And(filt2)
101
				}
102
			}
103
		}
104
		b = b.WithFilter(filt)
105
	}
106
107
	if len(x.Updates) != 0 {
108
		cond := x.Updates[0].NewCondition()
109
110
		// for multiple conditions
111
		if len(x.Updates) > 1 {
112
			for _, v := range x.Updates[1:] {
113
				cond = v.updateCondition(cond)
114
			}
115
		}
116
		b = b.WithUpdate(cond)
117
	}
118
119
	if len(x.Projections) != 0 {
120
		list := make([]expression.NameBuilder, len(x.Projections))
121
		for i, v := range x.Projections {
122
			list[i] = expression.Name(v)
123
		}
124
		b = b.WithProjection(expression.ProjectionBuilder{}.AddNames(list...))
125
	}
126
127
	return b.Build()
128
}
129
130
// XCondition contains single condition parameters.
131
type XCondition struct {
132
	Name     string
133
	Value    interface{}
134
	Operator ComparisonOperator
135
136
	// optional
137
	IsOR  bool
138
	IsNOT bool
139
	// - 'BETWEEN': higher value.
140
	// - 'IN': all of values afre used besides XCondition.Value.
141
	OtherValues []string
142
}
143
144
func (x XCondition) KeyCondition() (expression.KeyConditionBuilder, error) {
0 ignored issues
show
introduced by
exported method XCondition.KeyCondition should have comment or be unexported
Loading history...
145
	e := expression.Key(x.Name)
146
	switch x.Operator {
147
	case ComparisonOperatorEq:
148
		return e.Equal(expression.Value(x.Value)), nil
149
	case ComparisonOperatorLe:
150
		return e.LessThanEqual(expression.Value(x.Value)), nil
151
	case ComparisonOperatorLt:
152
		return e.LessThan(expression.Value(x.Value)), nil
153
	case ComparisonOperatorGe:
154
		return e.GreaterThanEqual(expression.Value(x.Value)), nil
155
	case ComparisonOperatorGt:
156
		return e.GreaterThan(expression.Value(x.Value)), nil
157
	case ComparisonOperatorBeginsWith:
158
		return e.BeginsWith(fmt.Sprint(x.Value)), nil
159
	case ComparisonOperatorBetween:
160
		if len(x.OtherValues) == 0 {
161
			return expression.KeyConditionBuilder{}, errors.New("Condition 'BETWEEN' must set 'OtherValues[0]'")
162
		}
163
		return e.Between(expression.Value(x.Value), expression.Value(x.OtherValues[0])), nil
164
	default:
165
		return e.Equal(expression.Value(x.Value)), nil
166
	}
167
}
168
169
func (x XCondition) Condition() (expression.ConditionBuilder, error) {
0 ignored issues
show
introduced by
exported method XCondition.Condition should have comment or be unexported
Loading history...
170
	e := expression.Name(x.Name)
171
	switch x.Operator {
172
	case ComparisonOperatorEq:
173
		return e.Equal(expression.Value(x.Value)), nil
174
	case ComparisonOperatorLe:
175
		return e.LessThanEqual(expression.Value(x.Value)), nil
176
	case ComparisonOperatorLt:
177
		return e.LessThan(expression.Value(x.Value)), nil
178
	case ComparisonOperatorGe:
179
		return e.GreaterThanEqual(expression.Value(x.Value)), nil
180
	case ComparisonOperatorGt:
181
		return e.GreaterThan(expression.Value(x.Value)), nil
182
	case ComparisonOperatorBeginsWith:
183
		return e.BeginsWith(fmt.Sprint(x.Value)), nil
184
	case ComparisonOperatorBetween:
185
		if len(x.OtherValues) == 0 {
186
			return expression.ConditionBuilder{}, errors.New("Condition 'BETWEEN' must set 'OtherValues[0]'")
187
		}
188
		return e.Between(expression.Value(x.Value), expression.Value(x.OtherValues[0])), nil
189
	case ComparisonOperatorIn:
190
		list := make([]expression.OperandBuilder, len(x.OtherValues))
191
		for i, v := range x.OtherValues {
192
			list[i] = expression.Value(v)
193
		}
194
		return e.In(expression.Value(x.Value), list...), nil
195
	case ComparisonOperatorNe:
196
		return e.NotEqual(expression.Value(x.Value)), nil
197
	case ComparisonOperatorContains:
198
		return e.Contains(fmt.Sprint(x.Value)), nil
199
	case ComparisonOperatorAttrExists:
200
		return e.AttributeExists(), nil
201
	case ComparisonOperatorAttrNotExists:
202
		return e.AttributeNotExists(), nil
203
	case ComparisonOperatorAttrType:
204
		return e.AttributeType(expression.DynamoDBAttributeType(fmt.Sprint(x.Value))), nil
205
	default:
206
		return e.Equal(expression.Value(x.Value)), nil
207
	}
208
}
209
210
type XUpdateCondition struct {
0 ignored issues
show
introduced by
exported type XUpdateCondition should have comment or be unexported
Loading history...
211
	Name      string
212
	Value     interface{}
213
	Operation OperationMode
214
215
	SetType       SetType
216
	SetTypeKey    string
217
	SetTypeValue2 interface{}
218
}
219
220
func (x XUpdateCondition) NewCondition() expression.UpdateBuilder {
0 ignored issues
show
introduced by
exported method XUpdateCondition.NewCondition should have comment or be unexported
Loading history...
221
	return x.updateCondition(expression.UpdateBuilder{})
222
}
223
224
func (x XUpdateCondition) updateCondition(b expression.UpdateBuilder) expression.UpdateBuilder {
225
	switch x.Operation {
226
	case OperationModeSET:
227
		return x.updateConditionSet(b)
228
	case OperationModeREMOVE:
229
		return b.Remove(expression.Name(x.Name))
230
	case OperationModeADD:
231
		return b.Add(expression.Name(x.Name), expression.Value(x.Value))
232
	default:
233
		return x.updateConditionSet(b)
234
	}
235
}
236
237
func (x XUpdateCondition) updateConditionSet(b expression.UpdateBuilder) expression.UpdateBuilder {
238
	name := expression.Name(x.Name)
239
	value := expression.Value(x.Value)
240
	switch x.SetType {
241
	case SetTypePlus:
242
		return b.Set(name, expression.Plus(value, expression.Value(x.SetTypeValue2)))
243
	case SetTypeMinus:
244
		return b.Set(name, expression.Minus(value, expression.Value(x.SetTypeValue2)))
245
	case SetTypeListAppend:
246
		return b.Set(name, expression.ListAppend(value, expression.Value(x.SetTypeValue2)))
247
	case SetTypeIfNotExists:
248
		return b.Set(name, expression.IfNotExists(expression.Name(x.SetTypeKey), expression.Value(x.SetTypeValue2)))
249
	default:
250
		return b.Set(name, value)
251
	}
252
}
253
254
type OperationMode string
0 ignored issues
show
introduced by
exported type OperationMode should have comment or be unexported
Loading history...
255
256
const (
257
	OperationModeSET    OperationMode = "SET"
0 ignored issues
show
introduced by
exported const OperationModeSET should have comment (or a comment on this block) or be unexported
Loading history...
258
	OperationModeREMOVE OperationMode = "REMOVE"
259
	OperationModeADD    OperationMode = "ADD"
260
	OperationModeDELETE OperationMode = "DELETE"
261
)
262
263
type SetType string
0 ignored issues
show
introduced by
exported type SetType should have comment or be unexported
Loading history...
264
265
const (
266
	SetTypePlus        SetType = "PLUS"
0 ignored issues
show
introduced by
exported const SetTypePlus should have comment (or a comment on this block) or be unexported
Loading history...
267
	SetTypeMinus       SetType = "MINUS"
268
	SetTypeListAppend  SetType = "LIST_APPEND"
269
	SetTypeIfNotExists SetType = "IF_NOT_EXISTS"
270
)
271