Skip to content

Commit

Permalink
Merge pull request #75 from fogfish/support-embedded-types
Browse files Browse the repository at this point in the history
support embedded types in I/O
  • Loading branch information
fogfish committed Jan 15, 2023
2 parents a9ddf42 + cf098d1 commit 073df6f
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 50 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ require (
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.1
github.com/fogfish/curie v1.7.1
github.com/fogfish/errors v0.1.0
github.com/fogfish/golem v0.8.5
github.com/fogfish/golem v0.9.1
github.com/fogfish/it v0.9.1
github.com/fogfish/it/v2 v2.0.0-20220827053314-ff49ca642fd4
github.com/fogfish/it/v2 v2.0.1
)

require (
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ github.com/fogfish/curie v1.7.1 h1:A96AcFsJ7kz/Jdf/xvajEqo618sk9pzrycUrdQHB5f0=
github.com/fogfish/curie v1.7.1/go.mod h1:jPv7pg4hHd8Ug/USG29ZA2bAwlRfh/iinY90/30ATGg=
github.com/fogfish/errors v0.1.0 h1:sDHRVWkm+VfHtXeXJylzJ2rMO50Iq/Af3BEgYEj1rfc=
github.com/fogfish/errors v0.1.0/go.mod h1:jyY0y5a6zv0tM8j/webZQNCebcJsG3SyF473vcxofQE=
github.com/fogfish/golem v0.8.5 h1:ILBc28VTz2H2k18xC+1dbhrk4Y9iBCxN1o2iG8lEoBA=
github.com/fogfish/golem v0.8.5/go.mod h1:cQDsAMsur65kwXT/X1FcGRHrQaaQ+5WA87aWjm4Fnuk=
github.com/fogfish/golem v0.9.1 h1:IHBMGrjdOCJOANAVg22BqA7sY8S2Ah/B9M747RjI3Qg=
github.com/fogfish/golem v0.9.1/go.mod h1:lj7cttUvvjAE4KZU4RzHHw0o2pYozkPqat5ff38u71c=
github.com/fogfish/it v0.9.1 h1:Pu+qgqBV2ilZDzZzPIbUIhMIkdpHgbGUsdEwVQvBxNQ=
github.com/fogfish/it v0.9.1/go.mod h1:NQJG4Ygvek85y7zGj0Gny8+6ygAnHjfBORhI7TdQhp4=
github.com/fogfish/it/v2 v2.0.0-20220827053314-ff49ca642fd4 h1:QhBF5rj2dBXg0owbQdut8xdX6ylPrbvY8BuRIgu4/W8=
github.com/fogfish/it/v2 v2.0.0-20220827053314-ff49ca642fd4/go.mod h1:h5FdKaEQT4sUEykiVkB8VV4jX27XabFVeWhoDZaRZtE=
github.com/fogfish/it/v2 v2.0.1 h1:vu3kV2xzYDPHoMHMABxXeu5CoMcTfRc4gkWkzOUkRJY=
github.com/fogfish/it/v2 v2.0.1/go.mod h1:h5FdKaEQT4sUEykiVkB8VV4jX27XabFVeWhoDZaRZtE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
Expand Down
2 changes: 1 addition & 1 deletion service/ddb/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func Codec[T dynamo.Thing, A any](a string) CodecOf[T, A] {
// generic[T] filters hseq.Generic[T] list with defined fields
func genCodec[T any](fs ...string) hseq.Seq[T] {
seq := make(hseq.Seq[T], 0)
for _, t := range hseq.Generic[T]() {
for _, t := range hseq.New[T]() {
for _, f := range fs {
if t.Name == f {
seq = append(seq, t)
Expand Down
20 changes: 14 additions & 6 deletions service/ddb/constraint.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,23 @@ import (
// expressions. Just declare a global variables next to type definition and
// use them across the application.
//
// var name = dynamo.Schema[Person, string]("Name").Condition()
// var (
// name = dynamo.ClauseFor[Person, string]("Name")
// addr = dynamo.ClauseFor[Person, Address]()
// )
//
// name.Eq("Joe Doe")
// name.NotExists()
func ClauseFor[T dynamo.Thing, A any](schema string) ConditionExpression[T, A] {
return hseq.FMap1(
generic[T](string(schema)),
newConditionExpression[T, A],
)
func ClauseFor[T dynamo.Thing, A any](attr ...string) ConditionExpression[T, A] {
var seq hseq.Seq[T]

if len(attr) == 0 {
seq = hseq.New1[T, A]()
} else {
seq = hseq.New[T](attr[0])
}

return hseq.FMap1(seq, newConditionExpression[T, A])
}

type ConditionExpression[T dynamo.Thing, A any] struct{ key string }
Expand Down
5 changes: 4 additions & 1 deletion service/ddb/constraint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ type tConstrain struct {
func (tConstrain) HashKey() curie.IRI { return "" }
func (tConstrain) SortKey() curie.IRI { return "" }

var Name = ClauseFor[tConstrain, string]("Name")
var (
Name = ClauseFor[tConstrain, string]("Name")
Type = ClauseFor[tConstrain, string]()
)

func TestConditionExpression(t *testing.T) {
var (
Expand Down
15 changes: 10 additions & 5 deletions service/ddb/dsl.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,16 @@ import (
//
//

func UpdateFor[T dynamo.Thing, A any](field string) UpdateExpression[T, A] {
return hseq.FMap1(
generic[T](string(field)),
newUpdateExpression[T, A],
)
func UpdateFor[T dynamo.Thing, A any](attr ...string) UpdateExpression[T, A] {
var seq hseq.Seq[T]

if len(attr) == 0 {
seq = hseq.New1[T, A]()
} else {
seq = hseq.New[T](attr[0])
}

return hseq.FMap1(seq, newUpdateExpression[T, A])
}

type UpdateItemExpression[T dynamo.Thing] struct {
Expand Down
33 changes: 22 additions & 11 deletions service/ddb/dsl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,33 @@ func (tUpdatable) HashKey() curie.IRI { return "" }
func (tUpdatable) SortKey() curie.IRI { return "" }

var (
dslName = UpdateFor[tUpdatable, string]("Name")
dslName = UpdateFor[tUpdatable, string]("Name")
dslNameString = UpdateFor[tUpdatable, string]()

dslNone = UpdateFor[tUpdatable, int]("None")
// dslNoneInt = UpdateFor[tUpdatable, int]()

dslList = UpdateFor[tUpdatable, []string]("List")
// dslListSlice = UpdateFor[tUpdatable, []string]()
)

func TestUpdateExpressionModifyingOne(t *testing.T) {
val := tUpdatable{}
dsl := Updater(val, dslName.Set("some"))
n := dsl.request.ExpressionAttributeNames
v := dsl.request.ExpressionAttributeValues
e := *dsl.request.UpdateExpression

it.Then(t).
Should(it.Map(n).Have("#__anothername__", "anothername")).
Should(it.Map(v).Have(":__anothername__", &types.AttributeValueMemberS{Value: "some"})).
Should(it.Equal(e, "SET #__anothername__ = :__anothername__"))
for _, dslExpr := range []interface{ UpdateExpression(tUpdatable) }{
dslName.Set("some"),
dslNameString.Set("some"),
} {
val := tUpdatable{}
dsl := Updater(val, dslExpr)
n := dsl.request.ExpressionAttributeNames
v := dsl.request.ExpressionAttributeValues
e := *dsl.request.UpdateExpression

it.Then(t).Should(
it.Map(n).Have("#__anothername__", "anothername"),
it.Map(v).Have(":__anothername__", &types.AttributeValueMemberS{Value: "some"}),
it.Equal(e, "SET #__anothername__ = :__anothername__"),
)
}
}

func TestUpdateExpressionModifyingOneNotExists(t *testing.T) {
Expand Down
23 changes: 7 additions & 16 deletions service/ddb/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,6 @@ import (
// Internal data structure to manage type schema
//

// generic[T] filters hseq.Generic[T] list with defined fields
func generic[T any](fs ...string) hseq.Seq[T] {
seq := make(hseq.Seq[T], 0)
for _, t := range hseq.Generic[T]() {
for _, f := range fs {
if t.Name == f {
seq = append(seq, t)
}
}
}
return seq
}

// Schema is utility that decodes type into projection expression
type schema[T dynamo.Thing] struct {
ExpectedAttributeNames map[string]string
Expand All @@ -41,10 +28,14 @@ type schema[T dynamo.Thing] struct {

func newSchema[T dynamo.Thing]() *schema[T] {
seq := hseq.FMap(
hseq.Generic[T](),
hseq.New[T](),
func(t hseq.Type[T]) string {
name := t.StructField.Tag.Get("dynamodbav")
return strings.Split(name, ",")[0]
tag := t.StructField.Tag.Get("dynamodbav")
key := strings.Split(tag, ",")
if len(key) == 0 {
return t.Name
}
return key[0]
},
)

Expand Down
8 changes: 4 additions & 4 deletions service/s3/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Schema is utility that merges two struct
type schema[T dynamo.Thing] struct{ hseq.Seq[T] }

func newSchema[T dynamo.Thing]() *schema[T] {
return &schema[T]{hseq.Generic[T]()}
return &schema[T]{hseq.New[T]()}
}

func (schema schema[T]) Merge(a, b T) (c T) {
Expand All @@ -48,9 +48,9 @@ func (schema schema[T]) Merge(a, b T) (c T) {
}

for _, f := range schema.Seq {
fa := va.FieldByIndex(f.Index)
fb := vb.FieldByIndex(f.Index)
fc := vc.FieldByIndex(f.Index)
fa := va.FieldByName(f.Name)
fb := vb.FieldByName(f.Name)
fc := vc.FieldByName(f.Name)

switch {
case !fa.IsZero():
Expand Down

0 comments on commit 073df6f

Please sign in to comment.