Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DynamoDB Expression Package #981

Merged
merged 1 commit into from
Dec 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,577 changes: 1,577 additions & 0 deletions feature/dynamodb/expression/condition.go

Large diffs are not rendered by default.

1,510 changes: 1,510 additions & 0 deletions feature/dynamodb/expression/condition_test.go

Large diffs are not rendered by default.

47 changes: 47 additions & 0 deletions feature/dynamodb/expression/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
Package expression provides types and functions to create Amazon DynamoDB
Expression strings, ExpressionAttributeNames maps, and ExpressionAttributeValues
maps.

Using the Package

The package represents the various DynamoDB Expressions as structs named
accordingly. For example, ConditionBuilder represents a DynamoDB Condition
Expression, an UpdateBuilder represents a DynamoDB Update Expression, and so on.
The following example shows a sample ConditionExpression and how to build an
equivalent ConditionBuilder

// Let :a be an ExpressionAttributeValue representing the string "No One You Know"
condExpr := "Artist = :a"
condBuilder := expression.Name("Artist").Equal(expression.Value("No One You Know"))

In order to retrieve the formatted DynamoDB Expression strings, call the getter
methods on the Expression struct. To create the Expression struct, call the
Build() method on the Builder struct. Because some input structs, such as
QueryInput, can have multiple DynamoDB Expressions, multiple structs
representing various DynamoDB Expressions can be added to the Builder struct.
The following example shows a generic usage of the whole package.

filt := expression.Name("Artist").Equal(expression.Value("No One You Know"))
proj := expression.NamesList(expression.Name("SongTitle"), expression.Name("AlbumTitle"))
expr, err := expression.NewBuilder().WithFilter(filt).WithProjection(proj).Build()
if err != nil {
fmt.Println(err)
}

input := &dynamodb.ScanInput{
ExpressionAttributeNames: expr.Names(),
ExpressionAttributeValues: expr.Values(),
FilterExpression: expr.Filter(),
ProjectionExpression: expr.Projection(),
TableName: aws.String("Music"),
}

The ExpressionAttributeNames and ExpressionAttributeValues member of the input
struct must always be assigned when using the Expression struct because all item
attribute names and values are aliased. That means that if the
ExpressionAttributeNames and ExpressionAttributeValues member is not assigned
with the corresponding Names() and Values() methods, the DynamoDB operation will
run into a logic error.
*/
package expression
59 changes: 59 additions & 0 deletions feature/dynamodb/expression/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package expression

import (
"fmt"
)

// InvalidParameterError is returned if invalid parameters are encountered. This
// error specifically refers to situations where parameters are non-empty but
// have an invalid syntax/format. The error message includes the function
// that returned the error originally and the parameter type that was deemed
// invalid.
//
// Example:
//
// // err is of type InvalidParameterError
// _, err := expression.Name("foo..bar").BuildOperand()
type InvalidParameterError struct {
parameterType string
functionName string
}

func (ipe InvalidParameterError) Error() string {
return fmt.Sprintf("%s error: invalid parameter: %s", ipe.functionName, ipe.parameterType)
}

func newInvalidParameterError(funcName, paramType string) InvalidParameterError {
return InvalidParameterError{
parameterType: paramType,
functionName: funcName,
}
}

// UnsetParameterError is returned if parameters are empty and uninitialized.
// This error is returned if opaque structs (ConditionBuilder, NameBuilder,
// Builder, etc) are initialized outside of functions in the package, since all
// structs in the package are designed to be initialized with functions.
//
// Example:
//
// // err is of type UnsetParameterError
// _, err := expression.Builder{}.Build()
// _, err := expression.NewBuilder().
// WithCondition(expression.ConditionBuilder{}).
// Build()
type UnsetParameterError struct {
parameterType string
functionName string
}

func (upe UnsetParameterError) Error() string {
return fmt.Sprintf("%s error: unset parameter: %s", upe.functionName, upe.parameterType)
}

func newUnsetParameterError(funcName, paramType string) UnsetParameterError {
return UnsetParameterError{
parameterType: paramType,
functionName: funcName,
}
}
51 changes: 51 additions & 0 deletions feature/dynamodb/expression/error_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// +build go1.7

package expression

import (
"testing"
)

func TestInvalidParameterError(t *testing.T) {
cases := []struct {
name string
input InvalidParameterError
expected string
}{
{
name: "invalid error",
input: newInvalidParameterError("func", "param"),
expected: "func error: invalid parameter: param",
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
actual := c.input.Error()
if e, a := c.expected, actual; e != a {
t.Errorf("expect %v, got %v", e, a)
}
})
}
}

func TestUnsetParameterError(t *testing.T) {
cases := []struct {
name string
input UnsetParameterError
expected string
}{
{
name: "unset error",
input: newUnsetParameterError("func", "param"),
expected: "func error: unset parameter: param",
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
actual := c.input.Error()
if e, a := c.expected, actual; e != a {
t.Errorf("expect %v, got %v", e, a)
}
})
}
}
Loading