1package expression 2 3import ( 4 "fmt" 5 "strings" 6 7 "github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue" 8 "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" 9) 10 11// ValueBuilder represents an item attribute value operand and implements the 12// OperandBuilder interface. Methods and functions in the package take 13// ValueBuilder as an argument and establishes relationships between operands. 14// ValueBuilder should only be initialized using the function Value(). 15// 16// Example: 17// 18// // Create a ValueBuilder representing the string "aValue" 19// valueBuilder := expression.Value("aValue") 20type ValueBuilder struct { 21 value interface{} 22} 23 24// NameBuilder represents a name of a top level item attribute or a nested 25// attribute. Since NameBuilder represents a DynamoDB Operand, it implements the 26// OperandBuilder interface. Methods and functions in the package take 27// NameBuilder as an argument and establishes relationships between operands. 28// NameBuilder should only be initialized using the function Name(). 29// 30// Example: 31// 32// // Create a NameBuilder representing the item attribute "aName" 33// nameBuilder := expression.Name("aName") 34type NameBuilder struct { 35 name string 36} 37 38// SizeBuilder represents the output of the function size ("someName"), which 39// evaluates to the size of the item attribute defined by "someName". Since 40// SizeBuilder represents an operand, SizeBuilder implements the OperandBuilder 41// interface. Methods and functions in the package take SizeBuilder as an 42// argument and establishes relationships between operands. SizeBuilder should 43// only be initialized using the function Size(). 44// 45// Example: 46// 47// // Create a SizeBuilder representing the size of the item attribute 48// // "aName" 49// sizeBuilder := expression.Name("aName").Size() 50type SizeBuilder struct { 51 nameBuilder NameBuilder 52} 53 54// KeyBuilder represents either the partition key or the sort key, both of which 55// are top level attributes to some item in DynamoDB. Since KeyBuilder 56// represents an operand, KeyBuilder implements the OperandBuilder interface. 57// Methods and functions in the package take KeyBuilder as an argument and 58// establishes relationships between operands. However, KeyBuilder should only 59// be used to describe Key Condition Expressions. KeyBuilder should only be 60// initialized using the function Key(). 61// 62// Example: 63// 64// // Create a KeyBuilder representing the item key "aKey" 65// keyBuilder := expression.Key("aKey") 66type KeyBuilder struct { 67 key string 68} 69 70// setValueMode specifies the type of SetValueBuilder. The default value is 71// unsetValue so that an UnsetParameterError when BuildOperand() is called on an 72// empty SetValueBuilder. 73type setValueMode int 74 75const ( 76 unsetValue setValueMode = iota 77 plusValueMode 78 minusValueMode 79 listAppendValueMode 80 ifNotExistsValueMode 81) 82 83// SetValueBuilder represents the outcome of operator functions supported by the 84// DynamoDB Set operation. The operator functions are the following: 85// Plus() // Represents the "+" operator 86// Minus() // Represents the "-" operator 87// ListAppend() 88// IfNotExists() 89// For documentation on the above functions, 90// see: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.SET 91// Since SetValueBuilder represents an operand, it implements the OperandBuilder 92// interface. SetValueBuilder structs are used as arguments to the Set() 93// function. SetValueBuilders should only initialize a SetValueBuilder using the 94// functions listed above. 95type SetValueBuilder struct { 96 leftOperand OperandBuilder 97 rightOperand OperandBuilder 98 mode setValueMode 99} 100 101// Operand represents an item attribute name or value in DynamoDB. The 102// relationship between Operands specified by various builders such as 103// ConditionBuilders and UpdateBuilders for example is processed internally to 104// write Condition Expressions and Update Expressions respectively. 105type Operand struct { 106 exprNode exprNode 107} 108 109// OperandBuilder represents the idea of Operand which are building blocks to 110// DynamoDB Expressions. Package methods and functions can establish 111// relationships between operands, representing DynamoDB Expressions. The method 112// BuildOperand() is called recursively when the Build() method on the type 113// Builder is called. BuildOperand() should never be called externally. 114// OperandBuilder and BuildOperand() are exported to allow package functions to 115// take an interface as an argument. 116type OperandBuilder interface { 117 BuildOperand() (Operand, error) 118} 119 120// Name creates a NameBuilder. The argument should represent the desired item 121// attribute. It is possible to reference nested item attributes by using 122// square brackets for lists and dots for maps. For documentation on specifying 123// item attributes, 124// see: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.Attributes.html 125// 126// Example: 127// 128// // Specify a top-level attribute 129// name := expression.Name("TopLevel") 130// // Specify a nested attribute 131// nested := expression.Name("Record[6].SongList") 132// // Use Name() to create a condition expression 133// condition := expression.Name("foo").Equal(expression.Name("bar")) 134func Name(name string) NameBuilder { 135 return NameBuilder{ 136 name: name, 137 } 138} 139 140// Value creates a ValueBuilder and sets its value to the argument. The value 141// will be marshalled using the attributevalue package, unless it is of 142// type types.AttributeValue, where it will be used directly. 143// 144// Empty slices and maps will be encoded as their respective empty types.AttributeValue 145// types. If a NULL value is required, pass a dynamodb.AttributeValue, e.g.: 146// emptyList := &types.AttributeValueMemberNULL{Value: true} 147// 148// Example: 149// 150// // Use Value() to create a condition expression 151// condition := expression.Name("foo").Equal(expression.Value(10)) 152// // Use Value() to set the value of a set expression. 153// update := Set(expression.Name("greets"), expression.Value(&types.AttributeValueMemberS{Value: "hello"})) 154func Value(value interface{}) ValueBuilder { 155 return ValueBuilder{ 156 value: value, 157 } 158} 159 160// Size creates a SizeBuilder representing the size of the item attribute 161// specified by the argument NameBuilder. Size() is only valid for certain types 162// of item attributes. For documentation, 163// see: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html 164// SizeBuilder is only a valid operand in Condition Expressions and Filter 165// Expressions. 166// 167// Example: 168// 169// // Use Size() to create a condition expression 170// condition := expression.Name("foo").Size().Equal(expression.Value(10)) 171// 172// Expression Equivalent: 173// 174// expression.Name("aName").Size() 175// "size (aName)" 176func (nb NameBuilder) Size() SizeBuilder { 177 return SizeBuilder{ 178 nameBuilder: nb, 179 } 180} 181 182// Size creates a SizeBuilder representing the size of the item attribute 183// specified by the argument NameBuilder. Size() is only valid for certain types 184// of item attributes. For documentation, 185// see: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html 186// SizeBuilder is only a valid operand in Condition Expressions and Filter 187// Expressions. 188// 189// Example: 190// 191// // Use Size() to create a condition expression 192// condition := expression.Size(expression.Name("foo")).Equal(expression.Value(10)) 193// 194// Expression Equivalent: 195// 196// expression.Size(expression.Name("aName")) 197// "size (aName)" 198func Size(nameBuilder NameBuilder) SizeBuilder { 199 return nameBuilder.Size() 200} 201 202// Key creates a KeyBuilder. The argument should represent the desired partition 203// key or sort key value. KeyBuilders should only be used to specify 204// relationships for Key Condition Expressions. When referring to the partition 205// key or sort key in any other Expression, use Name(). 206// 207// Example: 208// 209// // Use Key() to create a key condition expression 210// keyCondition := expression.Key("foo").Equal(expression.Value("bar")) 211func Key(key string) KeyBuilder { 212 return KeyBuilder{ 213 key: key, 214 } 215} 216 217// Plus creates a SetValueBuilder to be used in as an argument to Set(). The 218// arguments can either be NameBuilders or ValueBuilders. Plus() only supports 219// DynamoDB Number types, so the ValueBuilder must be a Number and the 220// NameBuilder must specify an item attribute of type Number. 221// More information: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.SET.IncrementAndDecrement 222// 223// Example: 224// 225// // Use Plus() to set the value of the item attribute "someName" to 5 + 10 226// update, err := expression.Set(expression.Name("someName"), expression.Plus(expression.Value(5), expression.Value(10))) 227// 228// Expression Equivalent: 229// 230// expression.Plus(expression.Value(5), expression.Value(10)) 231// // let :five and :ten be ExpressionAttributeValues for the values 5 and 232// // 10 respectively. 233// ":five + :ten" 234func Plus(leftOperand, rightOperand OperandBuilder) SetValueBuilder { 235 return SetValueBuilder{ 236 leftOperand: leftOperand, 237 rightOperand: rightOperand, 238 mode: plusValueMode, 239 } 240} 241 242// Plus creates a SetValueBuilder to be used in as an argument to Set(). The 243// arguments can either be NameBuilders or ValueBuilders. Plus() only supports 244// DynamoDB Number types, so the ValueBuilder must be a Number and the 245// NameBuilder must specify an item attribute of type Number. 246// More information: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.SET.IncrementAndDecrement 247// 248// Example: 249// 250// // Use Plus() to set the value of the item attribute "someName" to the 251// // numeric value of item attribute "aName" incremented by 10 252// update, err := expression.Set(expression.Name("someName"), expression.Name("aName").Plus(expression.Value(10))) 253// 254// Expression Equivalent: 255// 256// expression.Name("aName").Plus(expression.Value(10)) 257// // let :ten be ExpressionAttributeValues representing the value 10 258// "aName + :ten" 259func (nb NameBuilder) Plus(rightOperand OperandBuilder) SetValueBuilder { 260 return Plus(nb, rightOperand) 261} 262 263// Plus creates a SetValueBuilder to be used in as an argument to Set(). The 264// arguments can either be NameBuilders or ValueBuilders. Plus() only supports 265// DynamoDB Number types, so the ValueBuilder must be a Number and the 266// NameBuilder must specify an item attribute of type Number. 267// More information: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.SET.IncrementAndDecrement 268// 269// Example: 270// 271// // Use Plus() to set the value of the item attribute "someName" to 5 + 10 272// update, err := expression.Set(expression.Name("someName"), expression.Value(5).Plus(expression.Value(10))) 273// 274// Expression Equivalent: 275// 276// expression.Value(5).Plus(expression.Value(10)) 277// // let :five and :ten be ExpressionAttributeValues representing the value 278// // 5 and 10 respectively 279// ":five + :ten" 280func (vb ValueBuilder) Plus(rightOperand OperandBuilder) SetValueBuilder { 281 return Plus(vb, rightOperand) 282} 283 284// Minus creates a SetValueBuilder to be used in as an argument to Set(). The 285// arguments can either be NameBuilders or ValueBuilders. Minus() only supports 286// DynamoDB Number types, so the ValueBuilder must be a Number and the 287// NameBuilder must specify an item attribute of type Number. 288// More information: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.SET.IncrementAndDecrement 289// 290// Example: 291// 292// // Use Minus() to set the value of item attribute "someName" to 5 - 10 293// update, err := expression.Set(expression.Name("someName"), expression.Minus(expression.Value(5), expression.Value(10))) 294// 295// Expression Equivalent: 296// 297// expression.Minus(expression.Value(5), expression.Value(10)) 298// // let :five and :ten be ExpressionAttributeValues for the values 5 and 299// // 10 respectively. 300// ":five - :ten" 301func Minus(leftOperand, rightOperand OperandBuilder) SetValueBuilder { 302 return SetValueBuilder{ 303 leftOperand: leftOperand, 304 rightOperand: rightOperand, 305 mode: minusValueMode, 306 } 307} 308 309// Minus creates a SetValueBuilder to be used in as an argument to Set(). The 310// arguments can either be NameBuilders or ValueBuilders. Minus() only supports 311// DynamoDB Number types, so the ValueBuilder must be a Number and the 312// NameBuilder must specify an item attribute of type Number. 313// More information: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.SET.IncrementAndDecrement 314// 315// Example: 316// 317// // Use Minus() to set the value of item attribute "someName" to the 318// // numeric value of "aName" decremented by 10 319// update, err := expression.Set(expression.Name("someName"), expression.Name("aName").Minus(expression.Value(10))) 320// 321// Expression Equivalent: 322// 323// expression.Name("aName").Minus(expression.Value(10))) 324// // let :ten be ExpressionAttributeValues represent the value 10 325// "aName - :ten" 326func (nb NameBuilder) Minus(rightOperand OperandBuilder) SetValueBuilder { 327 return Minus(nb, rightOperand) 328} 329 330// Minus creates a SetValueBuilder to be used in as an argument to Set(). The 331// arguments can either be NameBuilders or ValueBuilders. Minus() only supports 332// DynamoDB Number types, so the ValueBuilder must be a Number and the 333// NameBuilder must specify an item attribute of type Number. 334// More information: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.SET.IncrementAndDecrement 335// 336// Example: 337// 338// // Use Minus() to set the value of item attribute "someName" to 5 - 10 339// update, err := expression.Set(expression.Name("someName"), expression.Value(5).Minus(expression.Value(10))) 340// 341// Expression Equivalent: 342// 343// expression.Value(5).Minus(expression.Value(10)) 344// // let :five and :ten be ExpressionAttributeValues for the values 5 and 345// // 10 respectively. 346// ":five - :ten" 347func (vb ValueBuilder) Minus(rightOperand OperandBuilder) SetValueBuilder { 348 return Minus(vb, rightOperand) 349} 350 351// ListAppend creates a SetValueBuilder to be used in as an argument to Set(). 352// The arguments can either be NameBuilders or ValueBuilders. ListAppend() only 353// supports DynamoDB List types, so the ValueBuilder must be a List and the 354// NameBuilder must specify an item attribute of type List. 355// More information: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.SET.UpdatingListElements 356// 357// Example: 358// 359// // Use ListAppend() to set item attribute "someName" to the item 360// // attribute "nameOfList" with "some" and "list" appended to it 361// update, err := expression.Set(expression.Name("someName"), expression.ListAppend(expression.Name("nameOfList"), expression.Value([]string{"some", "list"}))) 362// 363// Expression Equivalent: 364// 365// expression.ListAppend(expression.Name("nameOfList"), expression.Value([]string{"some", "list"}) 366// // let :list be a ExpressionAttributeValue representing the list 367// // containing "some" and "list". 368// "list_append (nameOfList, :list)" 369func ListAppend(leftOperand, rightOperand OperandBuilder) SetValueBuilder { 370 return SetValueBuilder{ 371 leftOperand: leftOperand, 372 rightOperand: rightOperand, 373 mode: listAppendValueMode, 374 } 375} 376 377// ListAppend creates a SetValueBuilder to be used in as an argument to Set(). 378// The arguments can either be NameBuilders or ValueBuilders. ListAppend() only 379// supports DynamoDB List types, so the ValueBuilder must be a List and the 380// NameBuilder must specify an item attribute of type List. 381// More information: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.SET.UpdatingListElements 382// 383// Example: 384// 385// // Use ListAppend() to set item attribute "someName" to the item 386// // attribute "nameOfList" with "some" and "list" appended to it 387// update, err := expression.Set(expression.Name("someName"), expression.Name("nameOfList").ListAppend(expression.Value([]string{"some", "list"}))) 388// 389// Expression Equivalent: 390// 391// expression.Name("nameOfList").ListAppend(expression.Value([]string{"some", "list"}) 392// // let :list be a ExpressionAttributeValue representing the list 393// // containing "some" and "list". 394// "list_append (nameOfList, :list)" 395func (nb NameBuilder) ListAppend(rightOperand OperandBuilder) SetValueBuilder { 396 return ListAppend(nb, rightOperand) 397} 398 399// ListAppend creates a SetValueBuilder to be used in as an argument to Set(). 400// The arguments can either be NameBuilders or ValueBuilders. ListAppend() only 401// supports DynamoDB List types, so the ValueBuilder must be a List and the 402// NameBuilder must specify an item attribute of type List. 403// More information: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.SET.UpdatingListElements 404// 405// Example: 406// 407// // Use ListAppend() to set item attribute "someName" to a string list 408// // equal to {"a", "list", "some", "list"} 409// update, err := expression.Set(expression.Name("someName"), expression.Value([]string{"a", "list"}).ListAppend(expression.Value([]string{"some", "list"}))) 410// 411// Expression Equivalent: 412// 413// expression.Name([]string{"a", "list"}).ListAppend(expression.Value([]string{"some", "list"}) 414// // let :list1 and :list2 be a ExpressionAttributeValue representing the 415// // list {"a", "list"} and {"some", "list"} respectively 416// "list_append (:list1, :list2)" 417func (vb ValueBuilder) ListAppend(rightOperand OperandBuilder) SetValueBuilder { 418 return ListAppend(vb, rightOperand) 419} 420 421// IfNotExists creates a SetValueBuilder to be used in as an argument to Set(). 422// The first argument must be a NameBuilder representing the name where the new 423// item attribute is created. The second argument can either be a NameBuilder or 424// a ValueBuilder. In the case that it is a NameBuilder, the value of the item 425// attribute at the name specified becomes the value of the new item attribute. 426// More information: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.SET.PreventingAttributeOverwrites 427// 428// Example: 429// 430// // Use IfNotExists() to set item attribute "someName" to value 5 if 431// // "someName" does not exist yet. (Prevents overwrite) 432// update, err := expression.Set(expression.Name("someName"), expression.IfNotExists(expression.Name("someName"), expression.Value(5))) 433// 434// Expression Equivalent: 435// 436// expression.IfNotExists(expression.Name("someName"), expression.Value(5)) 437// // let :five be a ExpressionAttributeValue representing the value 5 438// "if_not_exists (someName, :five)" 439func IfNotExists(name NameBuilder, setValue OperandBuilder) SetValueBuilder { 440 return SetValueBuilder{ 441 leftOperand: name, 442 rightOperand: setValue, 443 mode: ifNotExistsValueMode, 444 } 445} 446 447// IfNotExists creates a SetValueBuilder to be used in as an argument to Set(). 448// The first argument must be a NameBuilder representing the name where the new 449// item attribute is created. The second argument can either be a NameBuilder or 450// a ValueBuilder. In the case that it is a NameBuilder, the value of the item 451// attribute at the name specified becomes the value of the new item attribute. 452// More information: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.SET.PreventingAttributeOverwrites 453// 454// Example: 455// 456// // Use IfNotExists() to set item attribute "someName" to value 5 if 457// // "someName" does not exist yet. (Prevents overwrite) 458// update, err := expression.Set(expression.Name("someName"), expression.Name("someName").IfNotExists(expression.Value(5))) 459// 460// Expression Equivalent: 461// 462// expression.Name("someName").IfNotExists(expression.Value(5)) 463// // let :five be a ExpressionAttributeValue representing the value 5 464// "if_not_exists (someName, :five)" 465func (nb NameBuilder) IfNotExists(rightOperand OperandBuilder) SetValueBuilder { 466 return IfNotExists(nb, rightOperand) 467} 468 469// BuildOperand creates an Operand struct which are building blocks to DynamoDB 470// Expressions. Package methods and functions can establish relationships 471// between operands, representing DynamoDB Expressions. The method 472// BuildOperand() is called recursively when the Build() method on the type 473// Builder is called. BuildOperand() should never be called externally. 474// BuildOperand() aliases all strings to avoid stepping over DynamoDB's reserved 475// words. 476// More information on reserved words at http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html 477func (nb NameBuilder) BuildOperand() (Operand, error) { 478 if nb.name == "" { 479 return Operand{}, newUnsetParameterError("BuildOperand", "NameBuilder") 480 } 481 482 node := exprNode{ 483 names: []string{}, 484 } 485 486 nameSplit := strings.Split(nb.name, ".") 487 fmtNames := make([]string, 0, len(nameSplit)) 488 489 for _, word := range nameSplit { 490 var substr string 491 if word == "" { 492 return Operand{}, newInvalidParameterError("BuildOperand", "NameBuilder") 493 } 494 495 if word[len(word)-1] == ']' { 496 for j, char := range word { 497 if char == '[' { 498 substr = word[j:] 499 word = word[:j] 500 break 501 } 502 } 503 } 504 505 if word == "" { 506 return Operand{}, newInvalidParameterError("BuildOperand", "NameBuilder") 507 } 508 509 // Create a string with special characters that can be substituted later: $p 510 node.names = append(node.names, word) 511 fmtNames = append(fmtNames, "$n"+substr) 512 } 513 node.fmtExpr = strings.Join(fmtNames, ".") 514 return Operand{ 515 exprNode: node, 516 }, nil 517} 518 519// BuildOperand creates an Operand struct which are building blocks to DynamoDB 520// Expressions. Package methods and functions can establish relationships 521// between operands, representing DynamoDB Expressions. The method 522// BuildOperand() is called recursively when the Build() method on the type 523// Builder is called. BuildOperand() should never be called externally. 524// BuildOperand() aliases all strings to avoid stepping over DynamoDB's reserved 525// words. 526// More information on reserved words at http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html 527func (vb ValueBuilder) BuildOperand() (Operand, error) { 528 var ( 529 expr types.AttributeValue 530 err error 531 ) 532 533 switch v := vb.value.(type) { 534 case types.AttributeValueMemberS: 535 expr = &v 536 case types.AttributeValueMemberN: 537 expr = &v 538 case types.AttributeValueMemberB: 539 expr = &v 540 case types.AttributeValueMemberSS: 541 expr = &v 542 case types.AttributeValueMemberNS: 543 expr = &v 544 case types.AttributeValueMemberBS: 545 expr = &v 546 case types.AttributeValueMemberM: 547 expr = &v 548 case types.AttributeValueMemberL: 549 expr = &v 550 case types.AttributeValueMemberNULL: 551 expr = &v 552 case types.AttributeValueMemberBOOL: 553 expr = &v 554 case types.AttributeValue: 555 expr = v 556 default: 557 expr, err = attributevalue.Marshal(vb.value) 558 if err != nil { 559 return Operand{}, newInvalidParameterError("BuildOperand", "ValueBuilder") 560 } 561 } 562 563 // Create a string with special characters that can be substituted later: $v 564 operand := Operand{ 565 exprNode: exprNode{ 566 values: []types.AttributeValue{expr}, 567 fmtExpr: "$v", 568 }, 569 } 570 return operand, nil 571} 572 573// BuildOperand creates an Operand struct which are building blocks to DynamoDB 574// Expressions. Package methods and functions can establish relationships 575// between operands, representing DynamoDB Expressions. The method 576// BuildOperand() is called recursively when the Build() method on the type 577// Builder is called. BuildOperand() should never be called externally. 578// BuildOperand() aliases all strings to avoid stepping over DynamoDB's reserved 579// words. 580// More information on reserved words at http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html 581func (sb SizeBuilder) BuildOperand() (Operand, error) { 582 operand, err := sb.nameBuilder.BuildOperand() 583 operand.exprNode.fmtExpr = "size (" + operand.exprNode.fmtExpr + ")" 584 585 return operand, err 586} 587 588// BuildOperand creates an Operand struct which are building blocks to DynamoDB 589// Expressions. Package methods and functions can establish relationships 590// between operands, representing DynamoDB Expressions. The method 591// BuildOperand() is called recursively when the Build() method on the type 592// Builder is called. BuildOperand() should never be called externally. 593// BuildOperand() aliases all strings to avoid stepping over DynamoDB's reserved 594// words. 595// More information on reserved words at http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html 596func (kb KeyBuilder) BuildOperand() (Operand, error) { 597 if kb.key == "" { 598 return Operand{}, newUnsetParameterError("BuildOperand", "KeyBuilder") 599 } 600 601 ret := Operand{ 602 exprNode: exprNode{ 603 names: []string{kb.key}, 604 fmtExpr: "$n", 605 }, 606 } 607 608 return ret, nil 609} 610 611// BuildOperand creates an Operand struct which are building blocks to DynamoDB 612// Expressions. Package methods and functions can establish relationships 613// between operands, representing DynamoDB Expressions. The method 614// BuildOperand() is called recursively when the Build() method on the type 615// Builder is called. BuildOperand() should never be called externally. 616// BuildOperand() aliases all strings to avoid stepping over DynamoDB's reserved 617// words. 618// More information on reserved words at http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html 619func (svb SetValueBuilder) BuildOperand() (Operand, error) { 620 if svb.mode == unsetValue { 621 return Operand{}, newUnsetParameterError("BuildOperand", "SetValueBuilder") 622 } 623 624 left, err := svb.leftOperand.BuildOperand() 625 if err != nil { 626 return Operand{}, err 627 } 628 leftNode := left.exprNode 629 630 right, err := svb.rightOperand.BuildOperand() 631 if err != nil { 632 return Operand{}, err 633 } 634 rightNode := right.exprNode 635 636 node := exprNode{ 637 children: []exprNode{leftNode, rightNode}, 638 } 639 640 switch svb.mode { 641 case plusValueMode: 642 node.fmtExpr = "$c + $c" 643 case minusValueMode: 644 node.fmtExpr = "$c - $c" 645 case listAppendValueMode: 646 node.fmtExpr = "list_append($c, $c)" 647 case ifNotExistsValueMode: 648 node.fmtExpr = "if_not_exists($c, $c)" 649 default: 650 return Operand{}, fmt.Errorf("build operand error: unsupported mode: %v", svb.mode) 651 } 652 653 return Operand{ 654 exprNode: node, 655 }, nil 656} 657