Skip to content

Commit

Permalink
reduce number of type parma on KeyConditionExpr
Browse files Browse the repository at this point in the history
  • Loading branch information
googley42 committed Aug 11, 2023
1 parent 41a4eec commit 7016ca6
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 47 deletions.
24 changes: 10 additions & 14 deletions dynamodb/src/main/scala/zio/dynamodb/DynamoDBQuery.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import zio.prelude.ForEachOps
import zio.schema.Schema
import zio.stream.Stream
import zio.{ Chunk, NonEmptyChunk, Schedule, ZIO, Zippable => _, _ }
import zio.dynamodb.proofs.IsPrimaryKey

sealed trait DynamoDBQuery[-In, +Out] { self =>

Expand Down Expand Up @@ -327,7 +326,7 @@ sealed trait DynamoDBQuery[-In, +Out] { self =>
* val newQuery = query.whereKey($("email").partitionKey === "avi@gmail.com" && $("subject").sortKey === "maths")
* }}}
*/
def whereKey[From, Pk, Sk](keyConditionExpression: KeyConditionExpr[From, Pk, Sk]): DynamoDBQuery[In, Out] =
def whereKey[From](keyConditionExpression: KeyConditionExpr[From]): DynamoDBQuery[In, Out] =
self match {
case Zip(left, right, zippable) =>
Zip(left.whereKey(keyConditionExpression), right.whereKey(keyConditionExpression), zippable)
Expand Down Expand Up @@ -453,15 +452,13 @@ object DynamoDBQuery {
): DynamoDBQuery[Any, Option[Item]] =
GetItem(TableName(tableName), key, projections.toList)

def get[From: Schema, Pk, Sk](
def get[From: Schema](
tableName: String,
projections: ProjectionExpression[_, _]*
)(
partitionKeyExpr: KeyConditionExpr.PrimaryKeyExpr[From, Pk, Sk]
)(implicit ev: IsPrimaryKey[Pk], ev2: IsPrimaryKey[Sk]): DynamoDBQuery[From, Either[DynamoDBError, From]] = {
val (_, _) = (ev, ev2)
partitionKeyExpr: KeyConditionExpr.PrimaryKeyExpr[From]
): DynamoDBQuery[From, Either[DynamoDBError, From]] =
get(tableName, partitionKeyExpr.asAttrMap, projections: _*)
}

private def get[A: Schema](
tableName: String,
Expand Down Expand Up @@ -501,17 +498,16 @@ object DynamoDBQuery {
): DynamoDBQuery[A, Option[A]] =
updateItem(tableName, key)(action).map(_.flatMap(item => fromItem(item).toOption))

def update[From: Schema, Pk, Sk](tableName: String)(primaryKeyExpr: KeyConditionExpr.PrimaryKeyExpr[From, Pk, Sk])(
def update[From: Schema](tableName: String)(primaryKeyExpr: KeyConditionExpr.PrimaryKeyExpr[From])(
action: Action[From]
): DynamoDBQuery[From, Option[From]] =
): DynamoDBQuery[From, Option[From]] =
updateItem(tableName, primaryKeyExpr.asAttrMap)(action).map(_.flatMap(item => fromItem(item).toOption))

def deleteItem(tableName: String, key: PrimaryKey): Write[Any, Option[Item]] = DeleteItem(TableName(tableName), key)

def delete[From: Schema, Pk, Sk](
def delete[From: Schema](
tableName: String
)(
primaryKeyExpr: KeyConditionExpr.PrimaryKeyExpr[From, Pk, Sk]
primaryKeyExpr: KeyConditionExpr.PrimaryKeyExpr[From]
): DynamoDBQuery[Any, Option[From]] =
deleteItem(tableName, primaryKeyExpr.asAttrMap).map(_.flatMap(item => fromItem(item).toOption))

Expand Down Expand Up @@ -838,7 +834,7 @@ object DynamoDBQuery {
exclusiveStartKey: LastEvaluatedKey =
None, // allows client to control start position - eg for client managed paging
filterExpression: Option[FilterExpression[_]] = None,
keyConditionExpr: Option[KeyConditionExpr[_, _, _]] = None,
keyConditionExpr: Option[KeyConditionExpr[_]] = None,
projections: List[ProjectionExpression[_, _]] = List.empty, // if empty all attributes will be returned
capacity: ReturnConsumedCapacity = ReturnConsumedCapacity.None,
select: Option[Select] = None, // if ProjectExpression supplied then only valid value is SpecificAttributes
Expand Down Expand Up @@ -871,7 +867,7 @@ object DynamoDBQuery {
exclusiveStartKey: LastEvaluatedKey =
None, // allows client to control start position - eg for client managed paging
filterExpression: Option[FilterExpression[_]] = None,
keyConditionExpr: Option[KeyConditionExpr[_, _, _]] = None,
keyConditionExpr: Option[KeyConditionExpr[_]] = None,
projections: List[ProjectionExpression[_, _]] = List.empty, // if empty all attributes will be returned
capacity: ReturnConsumedCapacity = ReturnConsumedCapacity.None,
select: Option[Select] = None, // if ProjectExpression supplied then only valid value is SpecificAttributes
Expand Down
34 changes: 17 additions & 17 deletions dynamodb/src/main/scala/zio/dynamodb/KeyConditionExpr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,30 @@ package zio.dynamodb
* Note 1), 2) and 3) are all valid key condition expressions used in Query DynamoDB queries
* BUT only 1) and 2) are valid primary key expressions that can be used in GetItem, UpdateItem and DeleteItem DynamoDB queries
*/
sealed trait KeyConditionExpr[-From, +Pk, +Sk] extends Renderable { self =>
sealed trait KeyConditionExpr[-From] extends Renderable { self =>
def render: AliasMapRender[String]
}

object KeyConditionExpr {
type SortKeyNotUsed

sealed trait PrimaryKeyExpr[-From, +Pk, +Sk] extends KeyConditionExpr[From, Pk, Sk] {
sealed trait PrimaryKeyExpr[-From] extends KeyConditionExpr[From] {
def asAttrMap: AttrMap
}

def getOrInsert[From, To](primaryKeyName: String): AliasMapRender[String] =
// note primary keys must be scalar values, they can't be nested
AliasMapRender.getOrInsert(ProjectionExpression.MapElement[From, To](ProjectionExpression.Root, primaryKeyName))

private[dynamodb] final case class PartitionKeyEquals[-From, +Pk](pk: PartitionKey[From, Pk], value: AttributeValue)
extends PrimaryKeyExpr[From, Pk, SortKeyNotUsed] { self =>
private[dynamodb] final case class PartitionKeyEquals[-From](pk: PartitionKey[From, _], value: AttributeValue)
extends PrimaryKeyExpr[From] { self =>

def &&[From1 <: From, Sk](other: SortKeyEquals[From1, Sk]): CompositePrimaryKeyExpr[From1, Pk, Sk] =
CompositePrimaryKeyExpr[From1, Pk, Sk](self.asInstanceOf[PartitionKeyEquals[From1, Pk]], other)
def &&[From1 <: From](other: SortKeyEquals[From1]): CompositePrimaryKeyExpr[From1] =
CompositePrimaryKeyExpr[From1](self.asInstanceOf[PartitionKeyEquals[From1]], other)
def &&[From1 <: From, Sk](
other: ExtendedSortKeyExpr[From1, Sk]
): ExtendedCompositePrimaryKeyExpr[From1, Pk, Sk] =
ExtendedCompositePrimaryKeyExpr[From1, Pk, Sk](self.asInstanceOf[PartitionKeyEquals[From1, Pk]], other)
): ExtendedCompositePrimaryKeyExpr[From1] =
ExtendedCompositePrimaryKeyExpr[From1](self.asInstanceOf[PartitionKeyEquals[From1]], other)

def asAttrMap: AttrMap = AttrMap(pk.keyName -> value)

Expand All @@ -44,7 +44,7 @@ object KeyConditionExpr {

}

private[dynamodb] final case class SortKeyEquals[-From, +Sk](sortKey: SortKey[From, Sk], value: AttributeValue) {
private[dynamodb] final case class SortKeyEquals[-From](sortKey: SortKey[From, _], value: AttributeValue) {
self =>
def miniRender: AliasMapRender[String] =
for {
Expand All @@ -53,10 +53,10 @@ object KeyConditionExpr {
} yield s"${keyAlias} = $v"
}

private[dynamodb] final case class CompositePrimaryKeyExpr[-From, +Pk, +Sk](
pk: PartitionKeyEquals[From, Pk],
sk: SortKeyEquals[From, Sk]
) extends PrimaryKeyExpr[From, Pk, Sk] {
private[dynamodb] final case class CompositePrimaryKeyExpr[-From](
pk: PartitionKeyEquals[From],
sk: SortKeyEquals[From]
) extends PrimaryKeyExpr[From] {
self =>

def asAttrMap: AttrMap = PrimaryKey(pk.pk.keyName -> pk.value, sk.sortKey.keyName -> sk.value)
Expand All @@ -68,10 +68,10 @@ object KeyConditionExpr {
} yield s"$pkStr AND $skStr"

}
private[dynamodb] final case class ExtendedCompositePrimaryKeyExpr[-From, +Pk, +Sk](
pk: PartitionKeyEquals[From, Pk],
sk: ExtendedSortKeyExpr[From, Sk]
) extends KeyConditionExpr[From, Pk, Sk] {
private[dynamodb] final case class ExtendedCompositePrimaryKeyExpr[-From](
pk: PartitionKeyEquals[From],
sk: ExtendedSortKeyExpr[From, _]
) extends KeyConditionExpr[From] {
self =>

def render: AliasMapRender[String] =
Expand Down
2 changes: 1 addition & 1 deletion dynamodb/src/main/scala/zio/dynamodb/PartitionKey.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import zio.dynamodb.proofs.RefersTo
private[dynamodb] final case class PartitionKey[-From, +To](keyName: String) { self =>
def ===[To1 >: To, To2: ToAttributeValue, IsPrimaryKey](
value: To2
)(implicit ev: RefersTo[To1, To2]): PartitionKeyEquals[From, To] = {
)(implicit ev: RefersTo[To1, To2]): PartitionKeyEquals[From] = {
val _ = ev
PartitionKeyEquals(self, implicitly[ToAttributeValue[To2]].toAttributeValue(value))
}
Expand Down
4 changes: 2 additions & 2 deletions dynamodb/src/main/scala/zio/dynamodb/SortKey.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ private[dynamodb] final case class SortKey[-From, +To](keyName: String) { self =
// all comparison ops apply to: Strings, Numbers, Binary values
def ===[To1 >: To, To2: ToAttributeValue, IsPrimaryKey](
value: To2
)(implicit ev: RefersTo[To1, To2]): SortKeyEquals[From, To2] = {
)(implicit ev: RefersTo[To1, To2]): SortKeyEquals[From] = {
val _ = ev
SortKeyEquals[From, To2](
SortKeyEquals[From](
self.asInstanceOf[SortKey[From, To2]],
implicitly[ToAttributeValue[To2]].toAttributeValue(value)
)
Expand Down
5 changes: 2 additions & 3 deletions dynamodb/src/main/scala/zio/dynamodb/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package zio

import zio.schema.Schema
import zio.stream.{ ZSink, ZStream }
import zio.dynamodb.proofs.IsPrimaryKey

package object dynamodb {
// Filter expression is the same as a ConditionExpression but when used with Query but does not allow key attributes
Expand Down Expand Up @@ -103,12 +102,12 @@ package object dynamodb {
* @tparam B implicit Schema[B] where B is the type of the element in the returned stream
* @return stream of Either[DynamoDBError.DecodingError, (A, Option[B])]
*/
def batchReadFromStream[R, A, From: Schema, Pk: IsPrimaryKey, Sk: IsPrimaryKey](
def batchReadFromStream[R, A, From: Schema](
tableName: String,
stream: ZStream[R, Throwable, A],
mPar: Int = 10
)(
pk: A => KeyConditionExpr.PrimaryKeyExpr[From, Pk, Sk]
pk: A => KeyConditionExpr.PrimaryKeyExpr[From]
): ZStream[R with DynamoDBExecutor, Throwable, Either[DynamoDBError.DecodingError, (A, Option[From])]] =
stream
.aggregateAsync(ZSink.collectAllN[A](100))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ object KeyConditionExprExample extends App {
import zio.dynamodb.KeyConditionExpr.SortKeyEquals
import zio.dynamodb.ProjectionExpression.$

val x6: CompositePrimaryKeyExpr[Any, ProjectionExpression.Unknown, String] =
val x6 =
$("foo.bar").partitionKey === 1 && $("foo.baz").sortKey === "y"
val x7 = $("foo.bar").partitionKey === 1 && $("foo.baz").sortKey > 1
val x8: ExtendedCompositePrimaryKeyExpr[Any, ProjectionExpression.Unknown, Int] =
val x7 = $("foo.bar").partitionKey === 1 && $("foo.baz").sortKey > 1
val x8 =
$("foo.bar").partitionKey === 1 && $("foo.baz").sortKey.between(1, 2)
val x9 =
val x9 =
$("foo.bar").partitionKey === 1 && $("foo.baz").sortKey.beginsWith(1L)

final case class Elephant(email: String, subject: String, age: Int)
Expand All @@ -32,11 +32,11 @@ object KeyConditionExprExample extends App {
val (email, subject, age, binary, binary2) = ProjectionExpression.accessors[Student]
}

val pk: PartitionKeyEquals[Student, String] = Student.email.partitionKey === "x"
val pk: PartitionKeyEquals[Student] = Student.email.partitionKey === "x"
// val pkX: PartitionKeyExpr[Student, String] = Student.age.primaryKey === "x" // as expected does not compile
val sk1: SortKeyEquals[Student, String] = Student.subject.sortKey === "y"
val sk2: ExtendedSortKeyExpr[Student, String] = Student.subject.sortKey > "y"
val pkAndSk: CompositePrimaryKeyExpr[Student, String, String] =
val sk1: SortKeyEquals[Student] = Student.subject.sortKey === "y"
val sk2: ExtendedSortKeyExpr[Student, String] = Student.subject.sortKey > "y"
val pkAndSk: CompositePrimaryKeyExpr[Student] =
Student.email.partitionKey === "x" && Student.subject.sortKey === "y"

//val three = Student.email.primaryKey === "x" && Student.subject.sortKey === "y" && Student.subject.sortKey // 3 terms not allowed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ object TypeSafeRoundTripSerialisationExample extends ZIOAppDefault {

object Repository {
def genericFindById[A <: Invoice](
pkExpr: KeyConditionExpr.PartitionKeyEquals[A, String]
pkExpr: KeyConditionExpr.PartitionKeyEquals[A]
)(implicit ev: Schema[A]): ZIO[DynamoDBExecutor, Throwable, Either[DynamoDBError, Invoice]] =
DynamoDBQuery.get("table1")(pkExpr).execute

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ object Student {
) =
ProjectionExpression.accessors[Student]

def primaryKey(email: String, subject: String): KeyConditionExpr.PrimaryKeyExpr[Student, String, String] =
def primaryKey(email: String, subject: String): KeyConditionExpr.PrimaryKeyExpr[Student] =
Student.email.partitionKey === email && Student.subject.sortKey === subject

val enrolDate = Instant.parse("2021-03-20T01:39:33Z")
Expand Down

0 comments on commit 7016ca6

Please sign in to comment.