From 1dd4c86a4b8a086895c504261c657c789c76d63d Mon Sep 17 00:00:00 2001 From: Ian Botsford <83236726+ianbotsf@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:16:43 +0000 Subject: [PATCH 1/4] runtime component of DDB Mapper filter expressions --- gradle/libs.versions.toml | 3 +- .../operations/model/MemberCodegenBehavior.kt | 10 + .../dynamodb-mapper/api/dynamodb-mapper.api | 424 ++++++++ .../dynamodb-mapper/build.gradle.kts | 3 +- .../expressions/AttributeType.kt | 62 ++ .../dynamodbmapper/expressions/BooleanFunc.kt | 38 + .../dynamodbmapper/expressions/Comparator.kt | 41 + .../expressions/ExpressionVisitor.kt | 71 ++ .../dynamodbmapper/expressions/Expressions.kt | 486 +++++++++ .../hll/dynamodbmapper/expressions/Filter.kt | 920 ++++++++++++++++++ .../dynamodbmapper/expressions/ScalarFunc.kt | 18 + .../expressions/internal/ExpressionImpls.kt | 139 +++ .../expressions/internal/FilterImpl.kt | 44 + .../ParameterizingExpressionVisitor.kt | 711 ++++++++++++++ .../dynamodbmapper/items/DocumentConverter.kt | 3 +- .../kotlin/hll/dynamodbmapper/model/Item.kt | 17 +- .../dynamodbmapper/util/AttributeValues.kt | 79 ++ .../values/NullableConverter.kt | 3 +- .../dynamodbmapper/expressions/FilterTest.kt | 799 +++++++++++++++ .../operations/DeleteItemTest.kt | 3 +- .../dynamodbmapper/operations/GetItemTest.kt | 5 +- .../dynamodbmapper/operations/QueryTest.kt | 43 +- .../testutils/AttributeValues.kt | 78 -- .../testutils/DdbClientExtensions.kt | 12 +- .../dynamodbmapper/testutils/DdbLocalTest.kt | 5 +- .../values/ValueConvertersTest.kt | 4 +- .../values/collections/ListConverterTest.kt | 2 +- .../values/collections/MapConverterTest.kt | 2 +- settings.gradle.kts | 2 +- 29 files changed, 3907 insertions(+), 120 deletions(-) create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Expressions.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ExpressionImpls.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/FilterImpl.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ParameterizingExpressionVisitor.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/util/AttributeValues.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/expressions/FilterTest.kt delete mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/testutils/AttributeValues.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2ccab54362d..f9f87de789b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] kotlin-version = "2.0.10" -ksp-version = "2.0.0-1.0.24" # Keep in sync with kotlin-version +ksp-version = "2.0.10-1.0.24" # Keep in sync with kotlin-version dokka-version = "1.9.10" @@ -29,7 +29,6 @@ slf4j-version = "2.0.9" [libraries] aws-kotlin-repo-tools-build-support = { module="aws.sdk.kotlin.gradle:build-support", version.ref = "aws-kotlin-repo-tools-version" } -kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin-version" } kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin-version" } kotlin-stdlib-jdk8 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin-version" } kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin-version" } diff --git a/hll/dynamodb-mapper/dynamodb-mapper-codegen/src/main/kotlin/aws/sdk/kotlin/hll/dynamodbmapper/codegen/operations/model/MemberCodegenBehavior.kt b/hll/dynamodb-mapper/dynamodb-mapper-codegen/src/main/kotlin/aws/sdk/kotlin/hll/dynamodbmapper/codegen/operations/model/MemberCodegenBehavior.kt index 079c475f249..2c7d79b9255 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper-codegen/src/main/kotlin/aws/sdk/kotlin/hll/dynamodbmapper/codegen/operations/model/MemberCodegenBehavior.kt +++ b/hll/dynamodb-mapper/dynamodb-mapper-codegen/src/main/kotlin/aws/sdk/kotlin/hll/dynamodbmapper/codegen/operations/model/MemberCodegenBehavior.kt @@ -28,6 +28,7 @@ internal sealed interface MemberCodegenBehavior { member in unsupportedMembers -> Drop member.type in attrMapTypes -> if (member.name == "key") MapKeys else MapAll member.isTableName -> Hoist + member.isFilterExpression -> FilterExpression else -> PassThrough } } @@ -65,6 +66,12 @@ internal sealed interface MemberCodegenBehavior { * structure). */ data object Hoist : MemberCodegenBehavior + + /** + * Indicates that a member from a low-level structure represents a filter expression and should be replaced with a + * filter DSL + */ + data object FilterExpression : MemberCodegenBehavior } /** @@ -78,6 +85,9 @@ internal val Member.codegenBehavior: MemberCodegenBehavior else -> MemberCodegenBehavior.PassThrough } +private val Member.isFilterExpression: Boolean + get() = name == "filterExpression" && type == Types.Kotlin.StringNullable + private val Member.isTableName: Boolean get() = name == "tableName" && type == Types.Kotlin.StringNullable diff --git a/hll/dynamodb-mapper/dynamodb-mapper/api/dynamodb-mapper.api b/hll/dynamodb-mapper/dynamodb-mapper/api/dynamodb-mapper.api index c344b8910f1..d777c1226c1 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/api/dynamodb-mapper.api +++ b/hll/dynamodb-mapper/dynamodb-mapper/api/dynamodb-mapper.api @@ -32,6 +32,430 @@ public final class aws/sdk/kotlin/hll/dynamodbmapper/DynamoDbMapperKt { public static synthetic fun DynamoDbMapper$default (Laws/sdk/kotlin/services/dynamodb/DynamoDbClient;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Laws/sdk/kotlin/hll/dynamodbmapper/DynamoDbMapper; } +public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/AndExpr : aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr { + public abstract fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; + public abstract fun getOperands ()Ljava/util/List; +} + +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/AndExpr$DefaultImpls { + public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AndExpr;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; +} + +public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttrPathElement { +} + +public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttrPathElement$Index : aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttrPathElement { + public abstract fun getIndex ()I +} + +public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttrPathElement$Name : aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttrPathElement { + public abstract fun getName ()Ljava/lang/String; +} + +public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath : aws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression { + public abstract fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; + public abstract fun getElement ()Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttrPathElement; + public abstract fun getParent ()Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath; +} + +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath$DefaultImpls { + public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; +} + +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType : java/lang/Enum { + public static final field Binary Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType; + public static final field BinarySet Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType; + public static final field Boolean Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType; + public static final field List Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType; + public static final field Map Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType; + public static final field Null Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType; + public static final field Number Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType; + public static final field NumberSet Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType; + public static final field String Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType; + public static final field StringSet Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType; + public final fun getAbbreviation ()Ljava/lang/String; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType; + public static fun values ()[Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType; +} + +public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/BetweenExpr : aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr { + public abstract fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; + public abstract fun getMax ()Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression; + public abstract fun getMin ()Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression; + public abstract fun getValue ()Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression; +} + +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/BetweenExpr$DefaultImpls { + public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BetweenExpr;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; +} + +public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr : aws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression { +} + +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc : java/lang/Enum { + public static final field ATTRIBUTE_EXISTS Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc; + public static final field ATTRIBUTE_NOT_EXISTS Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc; + public static final field ATTRIBUTE_TYPE Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc; + public static final field BEGINS_WITH Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc; + public static final field CONTAINS Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public final fun getExprString ()Ljava/lang/String; + public static fun valueOf (Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc; + public static fun values ()[Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc; +} + +public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr : aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr { + public abstract fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; + public abstract fun getAdditionalOperands ()Ljava/util/List; + public abstract fun getFunc ()Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc; + public abstract fun getPath ()Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath; +} + +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr$DefaultImpls { + public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; +} + +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator : java/lang/Enum { + public static final field EQUALS Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator; + public static final field GREATER_THAN Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator; + public static final field GREATER_THAN_OR_EQUAL Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator; + public static final field LESS_THAN Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator; + public static final field LESS_THAN_OR_EQUAL Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator; + public static final field NOT_EQUALS Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public final fun getExprString ()Ljava/lang/String; + public static fun valueOf (Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator; + public static fun values ()[Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator; +} + +public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/ComparisonExpr : aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr { + public abstract fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; + public abstract fun getComparator ()Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator; + public abstract fun getLeft ()Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression; + public abstract fun getRight ()Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression; +} + +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/ComparisonExpr$DefaultImpls { + public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ComparisonExpr;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; +} + +public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression { + public abstract fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; +} + +public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor { + public abstract fun visit (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AndExpr;)Ljava/lang/Object; + public abstract fun visit (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;)Ljava/lang/Object; + public abstract fun visit (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BetweenExpr;)Ljava/lang/Object; + public abstract fun visit (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr;)Ljava/lang/Object; + public abstract fun visit (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ComparisonExpr;)Ljava/lang/Object; + public abstract fun visit (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/InExpr;)Ljava/lang/Object; + public abstract fun visit (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr;)Ljava/lang/Object; + public abstract fun visit (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/NotExpr;)Ljava/lang/Object; + public abstract fun visit (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/OrExpr;)Ljava/lang/Object; + public abstract fun visit (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr;)Ljava/lang/Object; +} + +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionsKt { + public static final fun AndExpr (Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AndExpr; + public static final fun AttributePath (ILaws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath; + public static final fun AttributePath (Ljava/lang/String;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath; + public static synthetic fun AttributePath$default (Ljava/lang/String;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;ILjava/lang/Object;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath; + public static final fun BetweenExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BetweenExpr; + public static final fun BooleanFuncExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr; + public static final fun BooleanFuncExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;[Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr; + public static synthetic fun BooleanFuncExpr$default (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/List;ILjava/lang/Object;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr; + public static final fun ComparisonExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ComparisonExpr; + public static final fun InExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/InExpr; + public static final fun LiteralExpr (Laws/sdk/kotlin/services/dynamodb/model/AttributeValue;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr (Ljava/lang/Boolean;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr (Ljava/lang/Number;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr (Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr (Ljava/lang/Void;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr (Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr (Ljava/util/Map;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr ([B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr-3swpYEE (Lkotlin/UByte;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr-ADd3fzo (Lkotlin/ULong;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr-ExVfyTY (Lkotlin/UInt;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr-ffyZV3s (Lkotlin/UShort;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExprSetByteArray (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExprSetNumber (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExprSetString (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExprSetUByte (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExprSetUInt (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExprSetULong (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExprSetUShort (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun NotExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/NotExpr; + public static final fun OrExpr (Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/OrExpr; + public static final fun ScalarFuncExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr; + public static final fun ScalarFuncExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;[Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr; + public static synthetic fun ScalarFuncExpr$default (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/List;ILjava/lang/Object;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr; +} + +public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter { + public abstract fun and (Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun and ([Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun attr (Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath; + public abstract fun contains (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun contains (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/lang/Object;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Boolean;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Number;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Void;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Map;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;[B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eq-FrkygD8 (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Lkotlin/UInt;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eq-X7ZSXPM (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Lkotlin/UShort;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eq-Zf_Lc9A (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Lkotlin/ULong;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eq-tA8902A (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Lkotlin/UByte;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eqSetByteArray (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eqSetNumber (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eqSetString (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eqSetUByte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eqSetUInt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eqSetULong (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun eqSetUShort (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun exists (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun get (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;I)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath; + public abstract fun get (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath; + public abstract fun getSize (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression; + public abstract fun gt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun gt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Number;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun gt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun gt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;[B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun gt-2TYgG_w (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;J)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun gt-EK-6454 (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun gt-Qn1smSk (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;I)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun gt-i8woANY (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;S)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun gte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun gte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Number;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun gte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun gte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;[B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun gte-2TYgG_w (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;J)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun gte-EK-6454 (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun gte-Qn1smSk (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;I)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun gte-i8woANY (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;S)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isBetween (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInCollectionByteArray (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInCollectionExpression (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInCollectionList (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInCollectionMap (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInCollectionNumber (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInCollectionSetByteArray (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInCollectionSetNumber (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInCollectionSetString (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInCollectionSetUByte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInCollectionSetUInt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInCollectionSetULong (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInCollectionSetUShort (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInCollectionString (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInCollectionUByte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInCollectionUInt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInCollectionULong (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInCollectionUShort (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInRangeNumber (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Lkotlin/ranges/ClosedRange;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInRangeString (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Lkotlin/ranges/ClosedRange;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInRangeUByte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Lkotlin/ranges/ClosedRange;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInRangeUInt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Lkotlin/ranges/ClosedRange;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInRangeULong (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Lkotlin/ranges/ClosedRange;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isInRangeUShort (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Lkotlin/ranges/ClosedRange;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun isOfType (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun lt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun lt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Number;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun lt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun lt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;[B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun lt-2TYgG_w (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;J)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun lt-EK-6454 (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun lt-Qn1smSk (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;I)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun lt-i8woANY (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;S)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun lte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun lte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Number;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun lte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun lte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;[B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun lte-2TYgG_w (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;J)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun lte-EK-6454 (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun lte-Qn1smSk (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;I)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun lte-i8woANY (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;S)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Boolean;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Number;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Void;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Map;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;[B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neq-FrkygD8 (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Lkotlin/UInt;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neq-X7ZSXPM (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Lkotlin/UShort;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neq-Zf_Lc9A (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Lkotlin/ULong;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neq-tA8902A (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Lkotlin/UByte;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neqSetByteArray (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neqSetNumber (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neqSetString (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neqSetUByte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neqSetUInt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neqSetULong (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun neqSetUShort (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun not (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun notExists (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun or (Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun or ([Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun startsWith (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public abstract fun startsWith (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; +} + +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter$DefaultImpls { + public static fun and (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;[Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun contains (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/lang/Object;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun eq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Boolean;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun eq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Number;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun eq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun eq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Void;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun eq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun eq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Map;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun eq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;[B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun eq-FrkygD8 (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Lkotlin/UInt;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun eq-X7ZSXPM (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Lkotlin/UShort;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun eq-Zf_Lc9A (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Lkotlin/ULong;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun eq-tA8902A (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Lkotlin/UByte;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun eqSetByteArray (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun eqSetNumber (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun eqSetString (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun eqSetUByte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun eqSetUInt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun eqSetULong (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun eqSetUShort (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun gt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Number;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun gt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun gt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;[B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun gt-2TYgG_w (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;J)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun gt-EK-6454 (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun gt-Qn1smSk (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;I)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun gt-i8woANY (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;S)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun gte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Number;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun gte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun gte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;[B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun gte-2TYgG_w (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;J)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun gte-EK-6454 (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun gte-Qn1smSk (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;I)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun gte-i8woANY (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;S)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInCollectionByteArray (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInCollectionList (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInCollectionMap (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInCollectionNumber (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInCollectionSetByteArray (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInCollectionSetNumber (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInCollectionSetString (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInCollectionSetUByte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInCollectionSetUInt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInCollectionSetULong (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInCollectionSetUShort (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInCollectionString (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInCollectionUByte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInCollectionUInt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInCollectionULong (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInCollectionUShort (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInRangeNumber (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Lkotlin/ranges/ClosedRange;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInRangeString (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Lkotlin/ranges/ClosedRange;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInRangeUByte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Lkotlin/ranges/ClosedRange;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInRangeUInt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Lkotlin/ranges/ClosedRange;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInRangeULong (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Lkotlin/ranges/ClosedRange;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun isInRangeUShort (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Lkotlin/ranges/ClosedRange;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun lt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Number;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun lt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun lt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;[B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun lt-2TYgG_w (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;J)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun lt-EK-6454 (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun lt-Qn1smSk (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;I)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun lt-i8woANY (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;S)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun lte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Number;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun lte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun lte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;[B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun lte-2TYgG_w (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;J)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun lte-EK-6454 (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun lte-Qn1smSk (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;I)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun lte-i8woANY (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;S)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun neq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Boolean;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun neq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Number;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun neq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun neq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/lang/Void;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun neq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun neq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Map;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun neq (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;[B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun neq-FrkygD8 (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Lkotlin/UInt;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun neq-X7ZSXPM (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Lkotlin/UShort;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun neq-Zf_Lc9A (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Lkotlin/ULong;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun neq-tA8902A (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Lkotlin/UByte;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun neqSetByteArray (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun neqSetNumber (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun neqSetString (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun neqSetUByte (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun neqSetUInt (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun neqSetULong (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun neqSetUShort (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun or (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;[Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; + public static fun startsWith (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; +} + +public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/InExpr : aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr { + public abstract fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; + public abstract fun getSet ()Ljava/util/Collection; + public abstract fun getValue ()Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression; +} + +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/InExpr$DefaultImpls { + public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/InExpr;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; +} + +public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr : aws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression { + public abstract fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; + public abstract fun getValue ()Laws/sdk/kotlin/services/dynamodb/model/AttributeValue; +} + +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr$DefaultImpls { + public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; +} + +public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/NotExpr : aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr { + public abstract fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; + public abstract fun getOperand ()Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; +} + +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/NotExpr$DefaultImpls { + public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/NotExpr;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; +} + +public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/OrExpr : aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr { + public abstract fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; + public abstract fun getOperands ()Ljava/util/List; +} + +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/OrExpr$DefaultImpls { + public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/OrExpr;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; +} + +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc : java/lang/Enum { + public static final field SIZE Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public final fun getExprString ()Ljava/lang/String; + public static fun valueOf (Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc; + public static fun values ()[Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc; +} + +public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr : aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr { + public abstract fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; + public abstract fun getAdditionalOperands ()Ljava/util/List; + public abstract fun getFunc ()Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc; + public abstract fun getPath ()Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath; +} + +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr$DefaultImpls { + public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; +} + public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/items/AttributeDescriptor { public abstract fun getConverter ()Laws/sdk/kotlin/hll/mapping/core/converters/Converter; public abstract fun getGetter ()Lkotlin/jvm/functions/Function1; diff --git a/hll/dynamodb-mapper/dynamodb-mapper/build.gradle.kts b/hll/dynamodb-mapper/dynamodb-mapper/build.gradle.kts index 1491c0ae34a..05fc9e97132 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/build.gradle.kts +++ b/hll/dynamodb-mapper/dynamodb-mapper/build.gradle.kts @@ -20,6 +20,8 @@ buildscript { plugins { alias(libs.plugins.ksp) + + id("org.jetbrains.kotlinx.kover") version "0.9.0-RC" // REMOVE ME } kotlin { @@ -34,7 +36,6 @@ kotlin { commonTest { dependencies { - implementation(libs.kotlin.reflect) implementation(libs.kotlinx.coroutines.test) implementation(libs.kotest.assertions.core) implementation(libs.kotest.runner.junit5) diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType.kt new file mode 100644 index 00000000000..ed361ee56aa --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType.kt @@ -0,0 +1,62 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions + +/** + * Represents a + * [DynamoDB attribute data type](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes) + * @param abbreviation The DynamoDB type name + */ +public enum class AttributeType(public val abbreviation: kotlin.String) { + /** + * Binary data type, denoted in DynamoDB as `B` + */ + Binary("B"), + + /** + * Binary set data type, denoted in DynamoDB as `BS` + */ + BinarySet("BS"), + + /** + * Boolean data type, denoted in DynamoDB as `BOOL` + */ + Boolean("BOOL"), + + /** + * List data type, denoted in DynamoDB as `L` + */ + List("L"), + + /** + * Map data type, denoted in DynamoDB as `M` + */ + Map("M"), + + /** + * Null data type, denoted in DynamoDB as `NULL` + */ + Null("NULL"), + + /** + * Number data type, denoted in DynamoDB as `N` + */ + Number("N"), + + /** + * Number set data type, denoted in DynamoDB as `NS` + */ + NumberSet("NS"), + + /** + * String data type, denoted in DynamoDB as `S` + */ + String("S"), + + /** + * String set data type, denoted in DynamoDB as `S` + */ + StringSet("SS"), +} diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc.kt new file mode 100644 index 00000000000..1b6e222fd6a --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc.kt @@ -0,0 +1,38 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions + +/** + * Identifies a + * [DynamoDB expression function](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) + * which returns a boolean value + * @param exprString The literal name of the function to use in expression strings + */ +public enum class BooleanFunc(public val exprString: String) { + /** + * The `attribute_exist` function + */ + ATTRIBUTE_EXISTS("attribute_exists"), + + /** + * The `attribute_not_exists` function + */ + ATTRIBUTE_NOT_EXISTS("attribute_not_exists"), + + /** + * The `attribute_type` function + */ + ATTRIBUTE_TYPE("attribute_type"), + + /** + * The `begins_with` function + */ + BEGINS_WITH("begins_with"), + + /** + * The `contains` function + */ + CONTAINS("contains"), +} diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator.kt new file mode 100644 index 00000000000..4565973db1b --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator.kt @@ -0,0 +1,41 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions + +/** + * Identifies a comparison operator to use in an expression + * @param exprString The literal value of the operator to use in an expression string + */ +public enum class Comparator(public val exprString: String) { + /** + * An equality comparison, equivalent to `==` in Kotlin and to `=` in DynamoDB + */ + EQUALS("="), + + /** + * An inequality comparison, equivalent to `!=` in Kotlin and to `<>` in DynamoDB + */ + NOT_EQUALS("<>"), + + /** + * A less-than comparison, equivalent to `<` in Kotlin and DynamoDB + */ + LESS_THAN("<"), + + /** + * A less-than-or-equal-to comparison, equivalent to `<=` in Kotlin and DynamoDB + */ + LESS_THAN_OR_EQUAL("<="), + + /** + * A greater-than comparison, equivalent to `>` in Kotlin and DynamoDB + */ + GREATER_THAN(">"), + + /** + * A greater-than-or-equal-to comparison, equivalent to `>=` in Kotlin + */ + GREATER_THAN_OR_EQUAL(">="), +} diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor.kt new file mode 100644 index 00000000000..2ed03f5b845 --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor.kt @@ -0,0 +1,71 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions + +/** + * A [visitor](https://en.wikipedia.org/wiki/Visitor_pattern) that can traverse an [Expression] + * @param T The type of value used for state tracking by this visitor + */ +public interface ExpressionVisitor { + /** + * Visit an [AndExpr] + * @param expr The expression to visit + */ + public fun visit(expr: AndExpr): T + + /** + * Visit an [AttributePath] + * @param expr The expression to visit + */ + public fun visit(expr: AttributePath): T + + /** + * Visit a [BetweenExpr] + * @param expr The expression to visit + */ + public fun visit(expr: BetweenExpr): T + + /** + * Visit a [BooleanFuncExpr] + * @param expr The expression to visit + */ + public fun visit(expr: BooleanFuncExpr): T + + /** + * Visit a [ComparisonExpr] + * @param expr The expression to visit + */ + public fun visit(expr: ComparisonExpr): T + + /** + * Visit a [LiteralExpr] + * @param expr The expression to visit + */ + public fun visit(expr: LiteralExpr): T + + /** + * Visit an [InExpr] + * @param expr The expression to visit + */ + public fun visit(expr: InExpr): T + + /** + * Visit a [NotExpr] + * @param expr The expression to visit + */ + public fun visit(expr: NotExpr): T + + /** + * Visit an [OrExpr] + * @param expr The expression to visit + */ + public fun visit(expr: OrExpr): T + + /** + * Visit a [ScalarFuncExpr] + * @param expr The expression to visit + */ + public fun visit(expr: ScalarFuncExpr): T +} diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Expressions.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Expressions.kt new file mode 100644 index 00000000000..6d53cedba62 --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Expressions.kt @@ -0,0 +1,486 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.* +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.AndExprImpl +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.AttrPathIndexImpl +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.AttrPathNameImpl +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.AttributePathImpl +import aws.sdk.kotlin.hll.dynamodbmapper.util.attr +import aws.sdk.kotlin.services.dynamodb.model.AttributeValue + +/** + * Represents any kind of expression. This is an abstract top-level interface and describes no details about an + * expression on its own. Expressions may be of various specific types (e.g., [AttributePath], [ComparisonExpr], + * [AndExpr], etc.) each of which have specific data detailing the expression. + * + * [Expression] and its derivatives support the [visitor design pattern](https://en.wikipedia.org/wiki/Visitor_pattern) + * by way of an [accept] method. + */ +public sealed interface Expression { + /** + * Accepts a visitor that is traversing an expression tree by dispatching to a subtype implementation. Subtype + * implementations MUST call the [ExpressionVisitor.visit] overload for their concrete type (effectively forming a + * [double dispatch](https://en.wikipedia.org/wiki/Double_dispatch)) and MUST return the resulting value. + * @param visitor The [ExpressionVisitor] that is traversing an expression + */ + public fun accept(visitor: ExpressionVisitor): T +} + +/** + * A subtype of [Expression] that represents a condition with a boolean value, such as would be used for filtering + * items. This is a [marker interface](https://en.wikipedia.org/wiki/Marker_interface_pattern) which adds no additional + * declarations. + */ +public interface BooleanExpr : Expression + +/** + * Represents an element in an [AttributePath] + */ +public sealed interface AttrPathElement { + /** + * Represents the name of a top-level attribute or a key in a map + */ + public interface Name : AttrPathElement { + /** + * The name or key of this element + */ + public val name: String + } + + /** + * Represents an index into a list/set + */ + public interface Index : AttrPathElement { + /** + * The index (starting at `0`) + */ + public val index: Int + } +} + +/** + * Represents an expression that consists of an attribute. Attributes are referenced by attribute paths, analogous to + * [document paths in DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.Attributes.html#Expressions.Attributes.NestedElements.DocumentPathExamples). + * Attribute paths consist of one or more elements, which are either names (e.g., of a top-level attribute or a nested + * key in a map attribute) or indices (i.e., into a list). The first (and often only) element of an attribute path is a + * name. + * + * See [Filter] for more information about creating references to attributes. + */ +public interface AttributePath : Expression { + /** + * The [AttrPathElement] for this path + */ + public val element: AttrPathElement + + /** + * The parent [AttributePath] (if any). If [parent] is `null` then this instance represents a top-level attribute + * and [element] must be a name (not an index). + */ + public val parent: AttributePath? + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new [AttributePath] reference with the given name and optional parent path + * @param name The name or key of this element + * @param parent The parent [AttributePath] (if any) of this element. If [parent] is `null` then this instance + * represents a top-level attribute. + */ +public fun AttributePath(name: String, parent: AttributePath? = null): AttributePath = + AttributePathImpl(AttrPathNameImpl(name), parent) + +/** + * Creates a new [AttributePath] reference with the given index and parent path + * @param index The index (starting at `0`) of this element + * @param parent The parent [AttributePath] of this element + */ +public fun AttributePath(index: Int, parent: AttributePath): AttributePath = + AttributePathImpl(AttrPathIndexImpl(index), parent) + +/** + * Represents an `AND` expression as described in + * [DynamoDB's **logical evaluations** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.LogicalEvaluations). + * This expression will be true if `(operand[0] && operand[1] && ... && operand[n - 1])`. + */ +public interface AndExpr : BooleanExpr { + /** + * A list of 2 or more [BooleanExpr] conditions which are ANDed together + */ + public val operands: List + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new [AndExpr] with the given [operands] + * @param operands A list of 2 or more [BooleanExpr] conditions which are ANDed together + */ +public fun AndExpr(operands: List): AndExpr = AndExprImpl(operands) + +/** + * Represents a `BETWEEN` expression as described in + * [DynamoDB's **making comparisons** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Comparators). + * This expression will be true if `value >= min && value <= max`. + */ +public interface BetweenExpr : BooleanExpr { + /** + * The value being compared to the [min] and [max] + */ + public val value: Expression + + /** + * The minimum bound for the comparison + */ + public val min: Expression + + /** + * The maximum bound for the comparison + */ + public val max: Expression + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new [BetweenExpr] for the given [value] and range bounded by [min] and [max] + * @param value The value being compared to the [min] and [max] + * @param min The minimum bound for the comparison + * @param max The maximum bound for the comparison + */ +public fun BetweenExpr(value: Expression, min: Expression, max: Expression): BetweenExpr = + BetweenExprImpl(value, min, max) + +/** + * Represents a function expression that yields a boolean result as described in + * [DynamoDB's **function** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) + */ +public interface BooleanFuncExpr : BooleanExpr { + /** + * The specific boolean function to use + */ + public val func: BooleanFunc + + /** + * The attribute path to pass as the function's first argument + */ + public val path: AttributePath + + /** + * Any additional arguments used by the function + */ + public val additionalOperands: List + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new boolean function expression + * @param func The specific boolean function to use + * @param path The attribute path to pass as the function's first argument + * @param additionalOperands Any additional arguments used by the function + */ +public fun BooleanFuncExpr( + func: BooleanFunc, + path: AttributePath, + additionalOperands: List = listOf(), +): BooleanFuncExpr = BooleanFuncExprImpl(func, path, additionalOperands) + +/** + * Creates a new boolean function expression + * @param func The specific boolean function to use + * @param path The attribute path to pass as the function's first argument + * @param additionalOperands Any additional arguments used by the function + */ +public fun BooleanFuncExpr( + func: BooleanFunc, + path: AttributePath, + vararg additionalOperands: Expression, +): BooleanFuncExpr = BooleanFuncExprImpl(func, path, additionalOperands.toList()) + +/** + * Represents a comparison expression as described in + * [DynamoDB's **making comparisons** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Comparators). + * The specific type of comparison is identified by the [comparator] field. + */ +public interface ComparisonExpr : BooleanExpr { + /** + * The [Comparator] to use in the expression + */ + public val comparator: Comparator + + /** + * The left value being compared + */ + public val left: Expression + + /** + * The right value being compared + */ + public val right: Expression + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new comparison expression + * @param comparator The [Comparator] to use in the expression + * @param left The left value being compared + * @param right The right value being compared + */ +public fun ComparisonExpr(comparator: Comparator, left: Expression, right: Expression): ComparisonExpr = + ComparisonExprImpl(comparator, left, right) + +/** + * Represents an `IN` expression as described in + * [DynamoDB's **making comparisons** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Comparators). + * This expression will be true if `value in set` (or, equivalently, if `set.contains(value)`). + */ +public interface InExpr : BooleanExpr { + /** + * The value to check for in [set] + */ + public val value: Expression + + /** + * The set of values to compare against [value] + */ + public val set: Collection + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new `IN` expression + * @param value The value to check for in [set] + * @param set The set of values to compare against [value] + */ +public fun InExpr(value: Expression, set: Collection): InExpr = InExprImpl(value, set) + +/** + * Represents an expression that consists of a single literal value + */ +public interface LiteralExpr : Expression { + /** + * The low-level DynamoDB representation of the literal value + */ + public val value: AttributeValue + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new literal expression + * @param value The low-level DynamoDB representation of the literal value + */ +public fun LiteralExpr(value: AttributeValue): LiteralExpr = LiteralExprImpl(value) + +private val NULL_LITERAL = LiteralExpr(attr(null)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: Boolean?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: ByteArray?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: List?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: Map?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +@Suppress("UNUSED_PARAMETER") +public fun LiteralExpr(value: Nothing?): LiteralExpr = NULL_LITERAL + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: Number?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +@JvmName("LiteralExprSetByteArray") +public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +@JvmName("LiteralExprSetNumber") +public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +@JvmName("LiteralExprSetString") +public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +@JvmName("LiteralExprSetUByte") +public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +@JvmName("LiteralExprSetUInt") +public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +@JvmName("LiteralExprSetULong") +public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +@JvmName("LiteralExprSetUShort") +public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: String?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: UByte?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: UInt?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: ULong?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: UShort?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Represents a `NOT` expression as described in + * [DynamoDB's **logical evaluations** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.LogicalEvaluations). + * This expression will be true if `!operand` (i.e., `operand` evaluates to `false`). + */ +public interface NotExpr : BooleanExpr { + /** + * The condition to negate + */ + public val operand: BooleanExpr + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new `NOT` expression + * @param operand The condition to negate + */ +public fun NotExpr(operand: BooleanExpr): NotExpr = NotExprImpl(operand) + +/** + * Represents an `OR` expression as described in + * [DynamoDB's **logical evaluations** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.LogicalEvaluations). + * This expression will be true if `(operand[0] || operand[1] || ... || operand[n - 1])`. + */ +public interface OrExpr : BooleanExpr { + /** + * A list of 2 or more [BooleanExpr] conditions which are ANDed together + */ + public val operands: List + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new [OrExpr] with the given [operands] + * @param operands A list of 2 or more [BooleanExpr] conditions which are ORed together + */ +public fun OrExpr(operands: List): OrExpr = OrExprImpl(operands) + +/** + * Represents a function expression that yields a non-boolean result as described in + * [DynamoDB's **function** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) + */ +public interface ScalarFuncExpr : BooleanExpr { + /** + * The specific non-boolean function to use + */ + public val func: ScalarFunc + + /** + * The attribute path to pass as the function's first argument + */ + public val path: AttributePath + + /** + * Any additional arguments used by the function + */ + public val additionalOperands: List + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new non-boolean function expression + * @param func The specific non-boolean function to use + * @param path The attribute path to pass as the function's first argument + * @param additionalOperands Any additional arguments used by the function + */ +public fun ScalarFuncExpr( + func: ScalarFunc, + path: AttributePath, + additionalOperands: List = listOf(), +): ScalarFuncExpr = ScalarFuncExprImpl(func, path, additionalOperands) + +/** + * Creates a new non-boolean function expression + * @param func The specific non-boolean function to use + * @param path The attribute path to pass as the function's first argument + * @param additionalOperands Any additional arguments used by the function + */ +public fun ScalarFuncExpr( + func: ScalarFunc, + path: AttributePath, + vararg additionalOperands: Expression, +): ScalarFuncExpr = ScalarFuncExprImpl(func, path, additionalOperands.toList()) diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter.kt new file mode 100644 index 00000000000..8a873469e4e --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter.kt @@ -0,0 +1,920 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions + +import aws.sdk.kotlin.hll.dynamodbmapper.util.dynamicAttr + +/** + * A DSL interface providing support for "low-level" filter expressions. Implementations of this interface provide + * methods and properties which create boolean expressions to filter item results (e.g., in Scan or Query operations). + * Expressions are typically formed by getting a reference to an attribute path and then exercising some operation or + * function upon it. + * + * For example: + * + * ```kotlin + * filter { + * attr("foo") eq 42 + * } + * ``` + * + * This example creates an expression which checks whether an attribute named `foo` is equal to the value `42`. + * + * ## (Non-)Relationship to schema + * + * The expressions formed by [Filter] are referred to as a "low-level" filter expression. This is because they are not + * restricted by or adherent to any defined schema. Instead, they are a DSL convenience layer over [literal DynamoDB + * expression strings and expression attribute value maps](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.html). + * As such they provide **minimal type correctness** and may allow you to form expressions which are invalid given the + * shape of your data, such as attributes which don't exist, comparisons with mismatched data types, etc. + * + * # Attributes + * + * Every filter condition contains at least one attribute. Attributes are referenced by attribute paths, analogous to + * [document paths in DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.Attributes.html#Expressions.Attributes.NestedElements.DocumentPathExamples). + * Attribute paths consist of one or more elements, which are either names (e.g., of a top-level attribute or a nested + * key in a map attribute) or indices (i.e., into a list). The first (and often only) element of an attribute path is a + * name. + * + * ## Getting a top-level attribute + * + * All attribute paths start with a top-level attribute expression, created by the [attr] function: + * + * ```kotlin + * attr("foo") // References the top-level attribute "foo" + * ``` + * + * Note, the attribute `foo` may not exist for a given item or for an entire table. + * + * ## Nesting + * + * Sometimes values are nested inside other attributes like lists and maps. Filter expressions can operate on those + * nested values by forming a more detailed attribute path using the `[]` operator or [get] functions on a path. + * + * For example, consider an item structure such as: + * + * ```json + * { + * "foo": "Hello", + * "bar": { + * "baz": [ + * "Yay", + * null, + * 42, + * true + * ] + * } + * } + * ``` + * + * The value `"Yay"` can be referenced with the following DSL syntax: + * + * ```kotlin + * attr("bar")["baz"][0] + * ``` + * + * That is, in the top-level attribute `bar`, in the value keyed by `baz`, the element at index `0`. + * + * # Equalities/inequalities + * + * A very common filter condition is verifying whether some attribute is equal (or unequal) to another value—either a + * literal value or the value of another attribute. These comparisons are available by using the following functions: + * * [eq] — checks if two values are equal (equivalent to Kotlin's `==` operator) + * * [neq] — checks if two values are _not_ equal (equivalent to Kotlin's `!=` operator) + * * [lt] — checks if a value is less than another value (equivalent to Kotlin's `<` operator) + * * [lte] — checks if a value is less than _or equal to_ another value (equivalent to Kotlin's `<=` operator) + * * [gt] — checks if a value is greater than another value (equivalent to Kotlin's `>` operator) + * * [gte] — checks if a value is greater than _or equal to_ another value (equivalent to Kotlin's `>=` operator) + * + * For example: + * + * ```kotlin + * attr("foo") eq 5 // Checks whether the value of attribute `foo` is `5` + * attr("bar") gt attr("baz") // Checks whether the value of attribute `bar` is greater than attribute `baz` + * ``` + * + * # Ranges and sets + * + * Expressions can check whether some attribute value is in a given range or set of possible values. These checks are + * available via the [isBetween] or [isIn] functions: + * + * ```kotlin + * // Checks whether the value of attribute `foo` is between 40 and 60 (inclusive) + * attr("foo") isIn 40..60 + * + * // Checks whether the value of attribute `foo` is either 1, 2, 4, 8, 16, or 32 + * attr("bar") isIn setOf(1, 2, 4, 8, 16, 32) + * + * // Checks whether the value of attribute `baz` is between the value of `foo` and the value of `baz` + * attr("baz").isBetween(attr("foo"), attr("baz")) + * ``` + * + * # Boolean logic + * + * The previous sections dealt with singular conditions (e.g., `a == b`, `c in (d, e, f)`, etc.). But complex queries + * may involve multiple conditions or negative conditions akin to the boolean operations AND (`&&`), OR (`||`, and NOT + * (`!`). This logic is available via the [and], [or], and [not] functions: + * + * ```kotlin + * and( + * attr("foo") eq 42, + * attr("bar") neq 42, + * ) + * ``` + * + * This block checks for value of the attribute `foo` equalling `42` and the value of attribute `bar` _not_ equalling + * `42`. This is roughly equivalent to the Kotlin syntax: + * + * ```kotlin + * (foo == 42 && bar != 42) + * ``` + * + * These boolean functions can be composed in various ways: + * + * ```kotlin + * or( + * attr("foo") eq "apple", + * and( + * attr("bar") lt attr("baz"), + * attr("baz") gte 42, + * ), + * not( + * attr("qux") in setOf("ready", "set", "go"), + * ), + * ) + * ``` + * + * This complex DSL code checks that at least one of three conditions is met (boolean OR): + * * The value of attribute `foo` is `"apple"` + * * The value of attribute `bar` is less than the value of `baz` **–and–** the value of `baz` is greater/equal to `42` + * * The value of attribute `qux` is not one of `"ready"`, `"steady"`, or `"go"` + * + * This is roughly equivalent to the Kotlin syntax: + * + * ```kotlin + * (foo == "apple") || (bar < baz && baz >= 42) || qux !in setOf("ready", "steady", "go") + * ``` + * + * # Other functions/properties + * + * Several additional filter expressions are possible via the following methods/properties: + * + * * [contains] — checks if a string/list attribute value contains the given value + * * [exists] — checks if _any value_ (including `null`) exists for an attribute + * * [notExists] — checks if no value is present for an attribute (i.e., the attribute is "undefined" for an item) + * * [isOfType] — checks if an attribute value is of the given type + * * [size] — gets the size of an attribute (e.g., number of elements in list/map/set, the length of a string, etc.) + * * [startsWith] — checks if a string attribute value starts with the given value + */ +public interface Filter { + // ATTRIBUTES + + /** + * Creates an attribute path reference from a top-level attribute name. To reference nested properties or indexed + * elements, use the `[]` operator or [AttributePath.get]. + * @param name The top-level attribute name + */ + public fun attr(name: String): AttributePath + + /** + * Creates an attribute path reference for an index into a list or set + * @param index The index to dereference + */ + public operator fun AttributePath.get(index: Int): AttributePath + + /** + * Creates an attribute path reference for a key in map + * @param key The key to dereference + */ + public operator fun AttributePath.get(key: String): AttributePath + + // BINARY OPERATORS + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param expr The other expression in the comparison + */ + public infix fun Expression.eq(expr: Expression): BooleanExpr + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.eq(value: Boolean?): BooleanExpr = eq(LiteralExpr(value)) + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.eq(value: ByteArray?): BooleanExpr = eq(LiteralExpr(value)) + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.eq(value: List?): BooleanExpr = eq(LiteralExpr(value)) + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.eq(value: Map?): BooleanExpr = eq(LiteralExpr(value)) + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.eq(value: Nothing?): BooleanExpr = eq(LiteralExpr(null)) + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.eq(value: Number?): BooleanExpr = eq(LiteralExpr(value)) + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param value The other value in the comparison + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("eqSetByteArray") + public infix fun Expression.eq(value: Set?): BooleanExpr = eq(LiteralExpr(value)) + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param value The other value in the comparison + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("eqSetNumber") + public infix fun Expression.eq(value: Set?): BooleanExpr = eq(LiteralExpr(value)) + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param value The other value in the comparison + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("eqSetString") + public infix fun Expression.eq(value: Set?): BooleanExpr = eq(LiteralExpr(value)) + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param value The other value in the comparison + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("eqSetUByte") + public infix fun Expression.eq(value: Set?): BooleanExpr = eq(LiteralExpr(value)) + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param value The other value in the comparison + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("eqSetUInt") + public infix fun Expression.eq(value: Set?): BooleanExpr = eq(LiteralExpr(value)) + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param value The other value in the comparison + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("eqSetULong") + public infix fun Expression.eq(value: Set?): BooleanExpr = eq(LiteralExpr(value)) + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param value The other value in the comparison + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("eqSetUShort") + public infix fun Expression.eq(value: Set?): BooleanExpr = eq(LiteralExpr(value)) + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.eq(value: String?): BooleanExpr = eq(LiteralExpr(value)) + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.eq(value: UByte?): BooleanExpr = eq(LiteralExpr(value)) + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.eq(value: UInt?): BooleanExpr = eq(LiteralExpr(value)) + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.eq(value: ULong?): BooleanExpr = eq(LiteralExpr(value)) + + /** + * Creates an equality expression for verifying two expressions are equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.eq(value: UShort?): BooleanExpr = eq(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param expr The other expression in the comparison + */ + public infix fun Expression.neq(expr: Expression): BooleanExpr + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.neq(value: Boolean?): BooleanExpr = neq(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.neq(value: ByteArray?): BooleanExpr = neq(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.neq(value: List?): BooleanExpr = neq(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.neq(value: Map?): BooleanExpr = neq(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.neq(value: Nothing?): BooleanExpr = neq(LiteralExpr(null)) + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.neq(value: Number?): BooleanExpr = neq(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param value The other value in the comparison + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("neqSetByteArray") + public infix fun Expression.neq(value: Set?): BooleanExpr = neq(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param value The other value in the comparison + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("neqSetNumber") + public infix fun Expression.neq(value: Set?): BooleanExpr = neq(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param value The other value in the comparison + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("neqSetString") + public infix fun Expression.neq(value: Set?): BooleanExpr = neq(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param value The other value in the comparison + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("neqSetUByte") + public infix fun Expression.neq(value: Set?): BooleanExpr = neq(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param value The other value in the comparison + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("neqSetUInt") + public infix fun Expression.neq(value: Set?): BooleanExpr = neq(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param value The other value in the comparison + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("neqSetULong") + public infix fun Expression.neq(value: Set?): BooleanExpr = neq(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param value The other value in the comparison + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("neqSetUShort") + public infix fun Expression.neq(value: Set?): BooleanExpr = neq(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.neq(value: String?): BooleanExpr = neq(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.neq(value: UByte?): BooleanExpr = neq(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.neq(value: UInt?): BooleanExpr = neq(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.neq(value: ULong?): BooleanExpr = neq(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying two expressions are not equal to each other + * @param value The other value in the comparison + */ + public infix fun Expression.neq(value: UShort?): BooleanExpr = neq(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is less than another expression + * @param expr The other expression in the comparison + */ + public infix fun Expression.lt(expr: Expression): BooleanExpr + + /** + * Creates an inequality expression for verifying this expression is less than another expression + * @param value The other value in the comparison + */ + public infix fun Expression.lt(value: ByteArray): BooleanExpr = lt(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is less than another expression + * @param value The other value in the comparison + */ + public infix fun Expression.lt(value: Number): BooleanExpr = lt(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is less than another expression + * @param value The other value in the comparison + */ + public infix fun Expression.lt(value: String): BooleanExpr = lt(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is less than another expression + * @param value The other value in the comparison + */ + public infix fun Expression.lt(value: UByte): BooleanExpr = lt(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is less than another expression + * @param value The other value in the comparison + */ + public infix fun Expression.lt(value: UInt): BooleanExpr = lt(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is less than another expression + * @param value The other value in the comparison + */ + public infix fun Expression.lt(value: ULong): BooleanExpr = lt(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is less than another expression + * @param value The other value in the comparison + */ + public infix fun Expression.lt(value: UShort): BooleanExpr = lt(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is less than or equal to another expression + * @param expr The other expression in the comparison + */ + public infix fun Expression.lte(expr: Expression): BooleanExpr + + /** + * Creates an inequality expression for verifying this expression is less than or equal to another expression + * @param value The other value in the comparison + */ + public infix fun Expression.lte(value: ByteArray): BooleanExpr = lte(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is less than or equal to another expression + * @param value The other value in the comparison + */ + public infix fun Expression.lte(value: Number): BooleanExpr = lte(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is less than or equal to another expression + * @param value The other value in the comparison + */ + public infix fun Expression.lte(value: String): BooleanExpr = lte(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is less than or equal to another expression + * @param value The other value in the comparison + */ + public infix fun Expression.lte(value: UByte): BooleanExpr = lte(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is less than or equal to another expression + * @param value The other value in the comparison + */ + public infix fun Expression.lte(value: UInt): BooleanExpr = lte(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is less than or equal to another expression + * @param value The other value in the comparison + */ + public infix fun Expression.lte(value: ULong): BooleanExpr = lte(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is less than or equal to another expression + * @param value The other value in the comparison + */ + public infix fun Expression.lte(value: UShort): BooleanExpr = lte(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is greater than another expression + * @param expr The other expression in the comparison + */ + public infix fun Expression.gt(expr: Expression): BooleanExpr + + /** + * Creates an inequality expression for verifying this expression is greater than another expression + * @param value The other value in the comparison + */ + public infix fun Expression.gt(value: ByteArray): BooleanExpr = gt(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is greater than another expression + * @param value The other value in the comparison + */ + public infix fun Expression.gt(value: Number): BooleanExpr = gt(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is greater than another expression + * @param value The other value in the comparison + */ + public infix fun Expression.gt(value: String): BooleanExpr = gt(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is greater than another expression + * @param value The other value in the comparison + */ + public infix fun Expression.gt(value: UByte): BooleanExpr = gt(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is greater than another expression + * @param value The other value in the comparison + */ + public infix fun Expression.gt(value: UInt): BooleanExpr = gt(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is greater than another expression + * @param value The other value in the comparison + */ + public infix fun Expression.gt(value: ULong): BooleanExpr = gt(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is greater than another expression + * @param value The other value in the comparison + */ + public infix fun Expression.gt(value: UShort): BooleanExpr = gt(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is greater than or equal to another expression + * @param expr The other expression in the comparison + */ + public infix fun Expression.gte(expr: Expression): BooleanExpr + + /** + * Creates an inequality expression for verifying this expression is greater than or equal to another expression + * @param value The other value in the comparison + */ + public infix fun Expression.gte(value: ByteArray): BooleanExpr = gte(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is greater than or equal to another expression + * @param value The other value in the comparison + */ + public infix fun Expression.gte(value: Number): BooleanExpr = gte(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is greater than or equal to another expression + * @param value The other value in the comparison + */ + public infix fun Expression.gte(value: String): BooleanExpr = gte(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is greater than or equal to another expression + * @param value The other value in the comparison + */ + public infix fun Expression.gte(value: UByte): BooleanExpr = gte(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is greater than or equal to another expression + * @param value The other value in the comparison + */ + public infix fun Expression.gte(value: UInt): BooleanExpr = gte(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is greater than or equal to another expression + * @param value The other value in the comparison + */ + public infix fun Expression.gte(value: ULong): BooleanExpr = gte(LiteralExpr(value)) + + /** + * Creates an inequality expression for verifying this expression is greater than or equal to another expression + * @param value The other value in the comparison + */ + public infix fun Expression.gte(value: UShort): BooleanExpr = gte(LiteralExpr(value)) + + // RANGES & SETS + + /** + * Creates a range expression for verifying this expression is between two other expressions + * @param min The lower bound expression + * @param max The upper bound expression (inclusive) + */ + public fun AttributePath.isBetween(min: Expression, max: Expression): BooleanExpr + + /** + * Creates a range expression for verifying this expression is in the given range + * @param range The range to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInRangeNumber") + public infix fun AttributePath.isIn(range: ClosedRange): BooleanExpr where N : Number, N : Comparable = + isBetween(LiteralExpr(range.start), LiteralExpr(range.endInclusive)) + + /** + * Creates a range expression for verifying this expression is in the given range + * @param range The range to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInRangeString") + public infix fun AttributePath.isIn(range: ClosedRange): BooleanExpr = + isBetween(LiteralExpr(range.start), LiteralExpr(range.endInclusive)) + + /** + * Creates a range expression for verifying this expression is in the given range + * @param range The range to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInRangeUByte") + public infix fun AttributePath.isIn(range: ClosedRange): BooleanExpr = + isBetween(LiteralExpr(range.start), LiteralExpr(range.endInclusive)) + + /** + * Creates a range expression for verifying this expression is in the given range + * @param range The range to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInRangeUInt") + public infix fun AttributePath.isIn(range: ClosedRange): BooleanExpr = + isBetween(LiteralExpr(range.start), LiteralExpr(range.endInclusive)) + + /** + * Creates a range expression for verifying this expression is in the given range + * @param range The range to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInRangeULong") + public infix fun AttributePath.isIn(range: ClosedRange): BooleanExpr = + isBetween(LiteralExpr(range.start), LiteralExpr(range.endInclusive)) + + /** + * Creates a range expression for verifying this expression is in the given range + * @param range The range to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInRangeUShort") + public infix fun AttributePath.isIn(range: ClosedRange): BooleanExpr = + isBetween(LiteralExpr(range.start), LiteralExpr(range.endInclusive)) + + /** + * Creates a contains expression for verifying this expression is in the given set of elements + * @param set The collection to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInCollectionExpression") + public infix fun AttributePath.isIn(set: Collection): BooleanExpr + + /** + * Creates a contains expression for verifying this expression is in the given set of elements + * @param set The collection to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInCollectionByteArray") + public infix fun AttributePath.isIn(set: Collection): BooleanExpr = isIn(set.map(::LiteralExpr)) + + /** + * Creates a contains expression for verifying this expression is in the given set of elements + * @param set The collection to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInCollectionList") + public infix fun AttributePath.isIn(set: Collection?>): BooleanExpr = isIn(set.map(::LiteralExpr)) + + /** + * Creates a contains expression for verifying this expression is in the given set of elements + * @param set The collection to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInCollectionMap") + public infix fun AttributePath.isIn(set: Collection?>): BooleanExpr = isIn(set.map(::LiteralExpr)) + + /** + * Creates a contains expression for verifying this expression is in the given set of elements + * @param set The collection to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInCollectionNumber") + public infix fun AttributePath.isIn(set: Collection): BooleanExpr = isIn(set.map(::LiteralExpr)) + + /** + * Creates a contains expression for verifying this expression is in the given set of elements + * @param set The collection to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInCollectionSetByteArray") + public infix fun AttributePath.isIn(set: Collection?>): BooleanExpr = isIn(set.map(::LiteralExpr)) + + /** + * Creates a contains expression for verifying this expression is in the given set of elements + * @param set The collection to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInCollectionSetNumber") + public infix fun AttributePath.isIn(set: Collection?>): BooleanExpr = isIn(set.map(::LiteralExpr)) + + /** + * Creates a contains expression for verifying this expression is in the given set of elements + * @param set The collection to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInCollectionSetString") + public infix fun AttributePath.isIn(set: Collection?>): BooleanExpr = isIn(set.map(::LiteralExpr)) + + /** + * Creates a contains expression for verifying this expression is in the given set of elements + * @param set The collection to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInCollectionSetUByte") + public infix fun AttributePath.isIn(set: Collection?>): BooleanExpr = isIn(set.map(::LiteralExpr)) + + /** + * Creates a contains expression for verifying this expression is in the given set of elements + * @param set The collection to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInCollectionSetUInt") + public infix fun AttributePath.isIn(set: Collection?>): BooleanExpr = isIn(set.map(::LiteralExpr)) + + /** + * Creates a contains expression for verifying this expression is in the given set of elements + * @param set The collection to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInCollectionSetULong") + public infix fun AttributePath.isIn(set: Collection?>): BooleanExpr = isIn(set.map(::LiteralExpr)) + + /** + * Creates a contains expression for verifying this expression is in the given set of elements + * @param set The collection to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInCollectionSetUShort") + public infix fun AttributePath.isIn(set: Collection?>): BooleanExpr = isIn(set.map(::LiteralExpr)) + + /** + * Creates a contains expression for verifying this expression is in the given set of elements + * @param set The collection to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInCollectionString") + public infix fun AttributePath.isIn(set: Collection): BooleanExpr = isIn(set.map(::LiteralExpr)) + + /** + * Creates a contains expression for verifying this expression is in the given set of elements + * @param set The collection to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInCollectionUByte") + public infix fun AttributePath.isIn(set: Collection): BooleanExpr = isIn(set.map(::LiteralExpr)) + + /** + * Creates a contains expression for verifying this expression is in the given set of elements + * @param set The collection to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInCollectionUInt") + public infix fun AttributePath.isIn(set: Collection): BooleanExpr = isIn(set.map(::LiteralExpr)) + + /** + * Creates a contains expression for verifying this expression is in the given set of elements + * @param set The collection to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInCollectionULong") + public infix fun AttributePath.isIn(set: Collection): BooleanExpr = isIn(set.map(::LiteralExpr)) + + /** + * Creates a contains expression for verifying this expression is in the given set of elements + * @param set The collection to check + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("isInCollectionUShort") + public infix fun AttributePath.isIn(set: Collection): BooleanExpr = isIn(set.map(::LiteralExpr)) + + // FUNCTIONS + + /** + * Creates a contains expression for verifying this expression contains the given expression + * @param expr The expression which may be contained + */ + public infix fun AttributePath.contains(expr: Expression): BooleanExpr + + /** + * Creates a contains expression for verifying this expression contains the given expression + * @param value The value which may be contained + */ + public infix fun AttributePath.contains(value: Any?): BooleanExpr = contains(LiteralExpr(dynamicAttr(value))) + + /** + * Creates an expression for verifying an attribute exists + */ + public fun AttributePath.exists(): BooleanExpr + + /** + * Creates an expression for verifying an attribute does not exist + */ + public fun AttributePath.notExists(): BooleanExpr + + /** + * Creates an expression for verifying an attribute exists + * @param type The [AttributeType] to test for + */ + public infix fun AttributePath.isOfType(type: AttributeType): BooleanExpr + + /** + * Creates an expression for getting the size (or length) of an attribute + */ + public val AttributePath.size: Expression + + /** + * Creates an expression for verifying this attribute starts with the given expression + * @param expr The expression to test for at the beginning of this attribute + */ + public infix fun AttributePath.startsWith(expr: Expression): BooleanExpr + + /** + * Creates an expression for verifying this attribute starts with the given expression + * @param value The value to test for at the beginning of this attribute + */ + public infix fun AttributePath.startsWith(value: String): BooleanExpr = startsWith(LiteralExpr(value)) + + // BOOLEAN LOGIC + + /** + * Creates a boolean expression for verifying that multiple conditions are all met + * @param conditions A list of 2 or more conditions + */ + public fun and(conditions: List): BooleanExpr + + /** + * Creates a boolean expression for verifying that multiple conditions are all met + * @param conditions A list of 2 or more conditions + */ + public fun and(vararg conditions: BooleanExpr): BooleanExpr = and(conditions.toList()) + + /** + * Creates a boolean expression for verifying the opposite of a condition is met + * @param condition The condition to negate + */ + public fun not(condition: BooleanExpr): BooleanExpr + + /** + * Creates a boolean expression for verifying that at least one of several conditions is met + * @param conditions A list of 2 or more conditions + */ + public fun or(conditions: List): BooleanExpr + + /** + * Creates a boolean expression for verifying that at least one of several conditions is met + * @param conditions A list of 2 or more conditions + */ + public fun or(vararg conditions: BooleanExpr): BooleanExpr = or(conditions.toList()) +} diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc.kt new file mode 100644 index 00000000000..5a713db6601 --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc.kt @@ -0,0 +1,18 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions + +/** + * Identifies a + * [DynamoDB expression function](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) + * which returns a non-boolean value + * @param exprString The literal name of the function to use in expression strings + */ +public enum class ScalarFunc(public val exprString: String) { + /** + * The `size` function + */ + SIZE("size"), +} diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ExpressionImpls.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ExpressionImpls.kt new file mode 100644 index 00000000000..bc18d76c91b --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ExpressionImpls.kt @@ -0,0 +1,139 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.* +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.LiteralExpr +import aws.sdk.kotlin.services.dynamodb.model.AttributeValue + +/** + * Represents the name of a top-level attribute or a key in a map + * @param name The name or key + */ +internal data class AttrPathNameImpl(override val name: String) : AttrPathElement.Name + +/** + * Represents an index into a list/set + * @param index The index (starting at `0`) + */ +internal data class AttrPathIndexImpl(override val index: Int) : AttrPathElement.Index + +/** + * Represents an expression that consists of an attribute path + * @param element The [AttrPathElement] for this path + * @param parent The parent [AttributePath] (if any). If [parent] is `null` then this instance represents a top-level + * attribute and [element] must be a name (not an index). Defaults to `null`. + */ +internal data class AttributePathImpl( + override val element: AttrPathElement, + override val parent: AttributePath? = null, +) : AttributePath { + init { + require(element is AttrPathElement.Name || parent != null) { + "Top-level attribute paths must be names (not indices)" + } + } +} + +/** + * Represents an `AND` expression as described in + * [DynamoDB's **logical evaluations** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.LogicalEvaluations). + * This expression will be true if `(operand[0] && operand[1] && ... && operand[n - 1])`. + * @param operands A list of 2 or more [BooleanExpr] conditions which are ANDed together + */ +internal data class AndExprImpl(override val operands: List) : AndExpr { + init { + require(operands.size > 1) { "AND operations require two or more operands" } + } +} + +/** + * Represents a `BETWEEN` expression as described in + * [DynamoDB's **making comparisons** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Comparators). + * This expression will be true if `value >= min && value <= max`. + * @param value The value being compared to the [min] and [max] + * @param min The minimum bound for the comparison + * @param max The maximum bound for the comparison + */ +internal data class BetweenExprImpl( + override val value: Expression, + override val min: Expression, + override val max: Expression, +) : BetweenExpr + +/** + * Represents a function expression that yields a boolean result as described in + * [DynamoDB's **function** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) + * @param func The specific boolean function to use + * @param path The attribute path to pass as the function's first argument + * @param additionalOperands Any additional arguments used by the function + */ +internal data class BooleanFuncExprImpl( + override val func: BooleanFunc, + override val path: AttributePath, + override val additionalOperands: List = listOf(), +) : BooleanFuncExpr + +/** + * Represents a comparison expression as described in + * [DynamoDB's **making comparisons** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Comparators). + * The specific type of comparison is identified by the [comparator] field. + * @param comparator The [Comparator] to use in the expression + * @param left The left value being compared + * @param right The right value being compared + */ +internal data class ComparisonExprImpl( + override val comparator: Comparator, + override val left: Expression, + override val right: Expression, +) : ComparisonExpr + +/** + * Represents an `IN` expression as described in + * [DynamoDB's **making comparisons** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Comparators). + * This expression will be true if `value in set` (or, equivalently, if `set.contains(value)`). + * @param value The value to check for in [set] + * @param set The set of values to compare against [value] + */ +internal data class InExprImpl(override val value: Expression, override val set: Collection) : InExpr + +/** + * Represents an expression that consists of a single literal value + * @param value The low-level DynamoDB representation of the literal value + */ +internal data class LiteralExprImpl(override val value: AttributeValue) : LiteralExpr + +/** + * Represents a `NOT` expression as described in + * [DynamoDB's **logical evaluations** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.LogicalEvaluations). + * This expression will be true if `!operand` (i.e., `operand` evaluates to `false`). + * @param operand The condition to negate + */ +internal data class NotExprImpl(override val operand: BooleanExpr) : NotExpr + +/** + * Represents an `OR` expression as described in + * [DynamoDB's **logical evaluations** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.LogicalEvaluations). + * This expression will be true if `(operand[0] || operand[1] || ... || operand[n - 1])`. + * @param operands A list of 2 or more [BooleanExpr] conditions which are ORed together + */ +internal data class OrExprImpl(override val operands: List) : OrExpr { + init { + require(operands.size > 1) { "OR operations require two or more operands" } + } +} + +/** + * Represents a function expression that yields a non-boolean result as described in + * [DynamoDB's **function** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) + * @param func The specific boolean function to use + * @param path The attribute path to pass as the function's first argument + * @param additionalOperands Any additional arguments used by the function + */ +internal data class ScalarFuncExprImpl( + override val func: ScalarFunc, + override val path: AttributePath, + override val additionalOperands: List = listOf(), +) : ScalarFuncExpr diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/FilterImpl.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/FilterImpl.kt new file mode 100644 index 00000000000..f1ad451759a --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/FilterImpl.kt @@ -0,0 +1,44 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.* + +internal data object FilterImpl : Filter { + // ATTRIBUTES + + override fun attr(name: String) = AttributePath(name) + override fun AttributePath.get(index: Int) = AttributePath(index, parent = this) + override fun AttributePath.get(key: String) = AttributePath(key, parent = this) + + // BINARY OPERATORS + + override fun Expression.eq(expr: Expression) = ComparisonExpr(Comparator.EQUALS, this, expr) + override fun Expression.neq(expr: Expression) = ComparisonExpr(Comparator.NOT_EQUALS, this, expr) + override fun Expression.lt(expr: Expression) = ComparisonExpr(Comparator.LESS_THAN, this, expr) + override fun Expression.lte(expr: Expression) = ComparisonExpr(Comparator.LESS_THAN_OR_EQUAL, this, expr) + override fun Expression.gt(expr: Expression) = ComparisonExpr(Comparator.GREATER_THAN, this, expr) + override fun Expression.gte(expr: Expression) = ComparisonExpr(Comparator.GREATER_THAN_OR_EQUAL, this, expr) + + // RANGES & SETS + + override fun AttributePath.isBetween(min: Expression, max: Expression) = BetweenExpr(this, min, max) + override fun AttributePath.isIn(set: Collection) = InExpr(this, set) + + // FUNCTIONS + + override fun AttributePath.contains(expr: Expression) = BooleanFuncExpr(BooleanFunc.CONTAINS, this, expr) + override fun AttributePath.exists() = BooleanFuncExpr(BooleanFunc.ATTRIBUTE_EXISTS, this) + override fun AttributePath.notExists() = BooleanFuncExpr(BooleanFunc.ATTRIBUTE_NOT_EXISTS, this) + override fun AttributePath.isOfType(type: AttributeType) = BooleanFuncExpr(BooleanFunc.ATTRIBUTE_TYPE, this, LiteralExpr(type.abbreviation)) + override val AttributePath.size get() = ScalarFuncExpr(ScalarFunc.SIZE, this) + override fun AttributePath.startsWith(expr: Expression) = BooleanFuncExpr(BooleanFunc.BEGINS_WITH, this, expr) + + // BOOLEAN LOGIC + + override fun and(conditions: List) = AndExpr(conditions) + override fun not(condition: BooleanExpr) = NotExpr(condition) + override fun or(conditions: List) = OrExpr(conditions) +} diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ParameterizingExpressionVisitor.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ParameterizingExpressionVisitor.kt new file mode 100644 index 00000000000..f28e6d1df61 --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ParameterizingExpressionVisitor.kt @@ -0,0 +1,711 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.* +import aws.sdk.kotlin.services.dynamodb.model.AttributeValue + +/** + * An [ExpressionVisitor] that traverses an [Expression] to yield an expression string, map of attribute names, and map + * of attribute values suitable for passing to DynamoDB. This visitor is designed for reuse across multiple expressions, + * yielding multiple expression strings but unified maps of attribute names and values. + * + * For example: + * + * ```kotlin + * val visitor = ParameterizingExpressionVisitor() + * + * ddb.query { + * filterExpression = visitor.visit() + * keyConditionExpression = visitor.visit() + * expressionAttributeNames = visitor.expressionAttributeNames() + * expressionAttributeValues = visitor.expressionAttributeValues() + * // … + * } + * ``` + */ +internal class ParameterizingExpressionVisitor : ExpressionVisitor { + private val namePlaceholders = mutableMapOf() + private val valuePlaceholders = mutableMapOf() + + private fun Expression.accept(): String = accept(this@ParameterizingExpressionVisitor) + + fun expressionAttributeNames(): Map? = namePlaceholders + .entries + .associate { (name, placeholder) -> placeholder to name } + .takeUnless { it.isEmpty() } + + fun expressionAttributeValues(): Map? = valuePlaceholders + .entries + .associate { (value, placeholder) -> placeholder to value } + .takeUnless { it.isEmpty() } + + private fun funcString(funcName: String, path: AttributePath, additionalOperands: List) = buildString { + append(funcName) + append('(') + append(path.accept()) + additionalOperands.forEach { operand -> + append(", ") + append(operand.accept()) + } + append(')') + } + + override fun visit(expr: AndExpr) = expr.operands.joinToString(" AND ") { "(${it.accept()})" } + + override fun visit(expr: AttributePath) = buildString { + expr.parent?.let { parent -> append(parent.accept()) } + + when (val element = expr.element) { + is AttrPathElement.Index -> { + append('[') + append(element.index) + append(']') + } + + is AttrPathElement.Name -> { + if (expr.parent != null) append('.') + + val literal = if (element.name.attributeNameNeedsEscaping) { + namePlaceholders.getOrPut(element.name) { "#k${namePlaceholders.size}" } + } else { + element.name + } + append(literal) + } + } + } + + override fun visit(expr: BetweenExpr) = buildString { + append(expr.value.accept()) + append(" BETWEEN ") + append(expr.min.accept()) + append(" AND ") + append(expr.max.accept()) + } + + override fun visit(expr: BooleanFuncExpr) = funcString(expr.func.exprString, expr.path, expr.additionalOperands) + + override fun visit(expr: ComparisonExpr) = buildString { + append(expr.left.accept()) + append(' ') + append(expr.comparator.exprString) + append(' ') + append(expr.right.accept()) + } + + override fun visit(expr: LiteralExpr) = valuePlaceholders.getOrPut(expr.value) { ":v${valuePlaceholders.size}" } + + override fun visit(expr: InExpr): String = buildString { + append(expr.value.accept()) + append(" IN (") + expr.set.joinTo(this, ", ") { it.accept() } + append(')') + } + + override fun visit(expr: NotExpr) = "NOT (${expr.operand.accept()})" + + override fun visit(expr: OrExpr) = expr.operands.joinToString(" OR ") { "(${it.accept()})" } + + override fun visit(expr: ScalarFuncExpr) = funcString(expr.func.exprString, expr.path, expr.additionalOperands) +} + +/** + * The set of + * [DynamoDB reserved words](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html) + */ +private val reservedWords = setOf( + "abort", + "absolute", + "action", + "add", + "after", + "agent", + "aggregate", + "all", + "allocate", + "alter", + "analyze", + "and", + "any", + "archive", + "are", + "array", + "as", + "asc", + "ascii", + "asensitive", + "assertion", + "asymmetric", + "at", + "atomic", + "attach", + "attribute", + "auth", + "authorization", + "authorize", + "auto", + "avg", + "back", + "backup", + "base", + "batch", + "before", + "begin", + "between", + "bigint", + "binary", + "bit", + "blob", + "block", + "boolean", + "both", + "breadth", + "bucket", + "bulk", + "by", + "byte", + "call", + "called", + "calling", + "capacity", + "cascade", + "cascaded", + "case", + "cast", + "catalog", + "char", + "character", + "check", + "class", + "clob", + "close", + "cluster", + "clustered", + "clustering", + "clusters", + "coalesce", + "collate", + "collation", + "collection", + "column", + "columns", + "combine", + "comment", + "commit", + "compact", + "compile", + "compress", + "condition", + "conflict", + "connect", + "connection", + "consistency", + "consistent", + "constraint", + "constraints", + "constructor", + "consumed", + "continue", + "convert", + "copy", + "corresponding", + "count", + "counter", + "create", + "cross", + "cube", + "current", + "cursor", + "cycle", + "data", + "database", + "date", + "datetime", + "day", + "deallocate", + "dec", + "decimal", + "declare", + "default", + "deferrable", + "deferred", + "define", + "defined", + "definition", + "delete", + "delimited", + "depth", + "deref", + "desc", + "describe", + "descriptor", + "detach", + "deterministic", + "diagnostics", + "directories", + "disable", + "disconnect", + "distinct", + "distribute", + "do", + "domain", + "double", + "drop", + "dump", + "duration", + "dynamic", + "each", + "element", + "else", + "elseif", + "empty", + "enable", + "end", + "equal", + "equals", + "error", + "escape", + "escaped", + "eval", + "evaluate", + "exceeded", + "except", + "exception", + "exceptions", + "exclusive", + "exec", + "execute", + "exists", + "exit", + "explain", + "explode", + "export", + "expression", + "extended", + "external", + "extract", + "fail", + "false", + "family", + "fetch", + "fields", + "file", + "filter", + "filtering", + "final", + "finish", + "first", + "fixed", + "flattern", + "float", + "for", + "force", + "foreign", + "format", + "forward", + "found", + "free", + "from", + "full", + "function", + "functions", + "general", + "generate", + "get", + "glob", + "global", + "go", + "goto", + "grant", + "greater", + "group", + "grouping", + "handler", + "hash", + "have", + "having", + "heap", + "hidden", + "hold", + "hour", + "identified", + "identity", + "if", + "ignore", + "immediate", + "import", + "in", + "including", + "inclusive", + "increment", + "incremental", + "index", + "indexed", + "indexes", + "indicator", + "infinite", + "initially", + "inline", + "inner", + "innter", + "inout", + "input", + "insensitive", + "insert", + "instead", + "int", + "integer", + "intersect", + "interval", + "into", + "invalidate", + "is", + "isolation", + "item", + "items", + "iterate", + "join", + "key", + "keys", + "lag", + "language", + "large", + "last", + "lateral", + "lead", + "leading", + "leave", + "left", + "length", + "less", + "level", + "like", + "limit", + "limited", + "lines", + "list", + "load", + "local", + "localtime", + "localtimestamp", + "location", + "locator", + "lock", + "locks", + "log", + "loged", + "long", + "loop", + "lower", + "map", + "match", + "materialized", + "max", + "maxlen", + "member", + "merge", + "method", + "metrics", + "min", + "minus", + "minute", + "missing", + "mod", + "mode", + "modifies", + "modify", + "module", + "month", + "multi", + "multiset", + "name", + "names", + "national", + "natural", + "nchar", + "nclob", + "new", + "next", + "no", + "none", + "not", + "null", + "nullif", + "number", + "numeric", + "object", + "of", + "offline", + "offset", + "old", + "on", + "online", + "only", + "opaque", + "open", + "operator", + "option", + "or", + "order", + "ordinality", + "other", + "others", + "out", + "outer", + "output", + "over", + "overlaps", + "override", + "owner", + "pad", + "parallel", + "parameter", + "parameters", + "partial", + "partition", + "partitioned", + "partitions", + "path", + "percent", + "percentile", + "permission", + "permissions", + "pipe", + "pipelined", + "plan", + "pool", + "position", + "precision", + "prepare", + "preserve", + "primary", + "prior", + "private", + "privileges", + "procedure", + "processed", + "project", + "projection", + "property", + "provisioning", + "public", + "put", + "query", + "quit", + "quorum", + "raise", + "random", + "range", + "rank", + "raw", + "read", + "reads", + "real", + "rebuild", + "record", + "recursive", + "reduce", + "ref", + "reference", + "references", + "referencing", + "regexp", + "region", + "reindex", + "relative", + "release", + "remainder", + "rename", + "repeat", + "replace", + "request", + "reset", + "resignal", + "resource", + "response", + "restore", + "restrict", + "result", + "return", + "returning", + "returns", + "reverse", + "revoke", + "right", + "role", + "roles", + "rollback", + "rollup", + "routine", + "row", + "rows", + "rule", + "rules", + "sample", + "satisfies", + "save", + "savepoint", + "scan", + "schema", + "scope", + "scroll", + "search", + "second", + "section", + "segment", + "segments", + "select", + "self", + "semi", + "sensitive", + "separate", + "sequence", + "serializable", + "session", + "set", + "sets", + "shard", + "share", + "shared", + "short", + "show", + "signal", + "similar", + "size", + "skewed", + "smallint", + "snapshot", + "some", + "source", + "space", + "spaces", + "sparse", + "specific", + "specifictype", + "split", + "sql", + "sqlcode", + "sqlerror", + "sqlexception", + "sqlstate", + "sqlwarning", + "start", + "state", + "static", + "status", + "storage", + "store", + "stored", + "stream", + "string", + "struct", + "style", + "sub", + "submultiset", + "subpartition", + "substring", + "subtype", + "sum", + "super", + "symmetric", + "synonym", + "system", + "table", + "tablesample", + "temp", + "temporary", + "terminated", + "text", + "than", + "then", + "throughput", + "time", + "timestamp", + "timezone", + "tinyint", + "to", + "token", + "total", + "touch", + "trailing", + "transaction", + "transform", + "translate", + "translation", + "treat", + "trigger", + "trim", + "true", + "truncate", + "ttl", + "tuple", + "type", + "under", + "undo", + "union", + "unique", + "unit", + "unknown", + "unlogged", + "unnest", + "unprocessed", + "unsigned", + "until", + "update", + "upper", + "url", + "usage", + "use", + "user", + "users", + "using", + "uuid", + "vacuum", + "value", + "valued", + "values", + "varchar", + "variable", + "variance", + "varint", + "varying", + "view", + "views", + "virtual", + "void", + "wait", + "when", + "whenever", + "where", + "while", + "window", + "with", + "within", + "without", + "work", + "wrapped", + "write", + "year", + "zone", +) + +private val String.attributeNameNeedsEscaping: Boolean + get() = contains(attributeNameNeedsEscapingRegex) + +private val attributeNameNeedsEscapingRegex = buildString { + append('(') + + // Alternative 1: entire string is a reserved word + reservedWords.joinTo(this, separator = "|", prefix = "^(", postfix = ")$") + + // OR + append('|') + + // Alternative 2: string contains any non-alphanumeric character anywhere + append("[^A-Za-z0-9]") + + append(')') +}.toRegex(RegexOption.IGNORE_CASE) diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/items/DocumentConverter.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/items/DocumentConverter.kt index d1d67b66928..a68891f4083 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/items/DocumentConverter.kt +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/items/DocumentConverter.kt @@ -6,6 +6,7 @@ package aws.sdk.kotlin.hll.dynamodbmapper.items import aws.sdk.kotlin.hll.dynamodbmapper.model.Item import aws.sdk.kotlin.hll.dynamodbmapper.model.toItem +import aws.sdk.kotlin.hll.dynamodbmapper.util.NULL_ATTR import aws.sdk.kotlin.services.dynamodb.model.AttributeValue import aws.smithy.kotlin.runtime.InternalApi import aws.smithy.kotlin.runtime.content.Document @@ -42,7 +43,7 @@ private fun fromAttributeValue(attr: AttributeValue): Document? = when (attr) { } private fun toAttributeValue(value: Document?): AttributeValue = when (value) { - null -> AttributeValue.Null(true) + null -> NULL_ATTR is Document.Number -> AttributeValue.N(value.value.toString()) is Document.String -> AttributeValue.S(value.value) is Document.Boolean -> AttributeValue.Bool(value.value) diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/model/Item.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/model/Item.kt index f01133c86de..ce67991d2e7 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/model/Item.kt +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/model/Item.kt @@ -5,6 +5,7 @@ package aws.sdk.kotlin.hll.dynamodbmapper.model import aws.sdk.kotlin.hll.dynamodbmapper.model.internal.ItemImpl +import aws.sdk.kotlin.hll.dynamodbmapper.util.dynamicAttr import aws.sdk.kotlin.services.dynamodb.model.AttributeValue /** @@ -31,9 +32,23 @@ public fun Item.toMutableItem(): MutableItem = toMutableMap().toMutableItem() */ public fun Map.toItem(): Item = ItemImpl(this) +/** + * Dynamically converts this map to an immutable [Item] + */ +@JvmName("mapStringAnyToItem") +internal fun Map.toItem() = mapValues { (_, v) -> dynamicAttr(v) }.toItem() + /** * Returns a new immutable [Item] with the specified attributes, given as name-value pairs * @param pairs A collection of [Pair]<[String], [AttributeValue]> where the first value is the attribute name and the * second is the attribute value. */ -public fun itemOf(vararg pairs: Pair): Item = ItemImpl(mapOf(*pairs)) +public fun itemOf(vararg pairs: Pair): Item = mapOf(*pairs).toItem() + +/** + * Returns a new immutable [Item] with the specified attributes, given as name-value pairs + * @param pairs A collection of [Pair]<[String], [Any]`?`> where the first value is the attribute name and the + * second is the attribute value. + */ +@JvmName("itemOfPairStringAny") +internal fun itemOf(vararg pairs: Pair): Item = mapOf(*pairs).toItem() diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/util/AttributeValues.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/util/AttributeValues.kt new file mode 100644 index 00000000000..597f2636aa7 --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/util/AttributeValues.kt @@ -0,0 +1,79 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.util + +import aws.sdk.kotlin.services.dynamodb.model.AttributeValue + +internal val NULL_ATTR = AttributeValue.Null(true) + +internal fun attr(value: Boolean?) = value?.let(AttributeValue::Bool) ?: NULL_ATTR +internal fun attr(value: ByteArray?) = value?.let(AttributeValue::B) ?: NULL_ATTR + +@JvmName("attrListAny") +internal fun attr(value: List?) = attr(value?.map(::dynamicAttr)) + +internal fun attr(value: List?) = value?.let(AttributeValue::L) ?: NULL_ATTR + +@JvmName("attrMapStringAny") +internal fun attr(value: Map?) = attr(value?.mapValues { (_, v) -> dynamicAttr(v) }) + +internal fun attr(value: Map?) = value?.let(AttributeValue::M) ?: NULL_ATTR + +@Suppress("UNUSED_PARAMETER") +internal fun attr(value: Nothing?) = NULL_ATTR + +internal fun attr(value: Number?) = value?.let { AttributeValue.N(it.toString()) } ?: NULL_ATTR + +@JvmName("attrSetByteArray") +internal fun attr(value: Set?) = value?.let { AttributeValue.Bs(it.toList()) } ?: NULL_ATTR + +@JvmName("attrSetNumber") +internal fun attr(value: Set?) = value?.let { AttributeValue.Ns(it.map(Number::toString)) } ?: NULL_ATTR + +@JvmName("attrSetString") +internal fun attr(value: Set?) = value?.let { AttributeValue.Ss(it.toList()) } ?: NULL_ATTR + +internal fun attr(value: String?) = value?.let(AttributeValue::S) ?: NULL_ATTR + +@JvmName("attrSetUByte") +internal fun attr(value: Set?) = value?.let { AttributeValue.Ns(it.map(UByte::toString)) } ?: NULL_ATTR + +@JvmName("attrSetUInt") +internal fun attr(value: Set?) = value?.let { AttributeValue.Ns(it.map(UInt::toString)) } ?: NULL_ATTR + +@JvmName("attrSetULong") +internal fun attr(value: Set?) = value?.let { AttributeValue.Ns(it.map(ULong::toString)) } ?: NULL_ATTR + +@JvmName("attrSetUShort") +internal fun attr(value: Set?) = value?.let { AttributeValue.Ns(it.map(UShort::toString)) } ?: NULL_ATTR + +internal fun attr(value: UByte?) = value?.let { AttributeValue.N(it.toString()) } ?: NULL_ATTR +internal fun attr(value: UInt?) = value?.let { AttributeValue.N(it.toString()) } ?: NULL_ATTR +internal fun attr(value: ULong?) = value?.let { AttributeValue.N(it.toString()) } ?: NULL_ATTR +internal fun attr(value: UShort?) = value?.let { AttributeValue.N(it.toString()) } ?: NULL_ATTR + +@Suppress("UNCHECKED_CAST") +internal fun dynamicAttr(value: Any?): AttributeValue = when (value) { + null -> NULL_ATTR + is AttributeValue -> value + is Boolean -> attr(value) + is ByteArray -> attr(value) + is List<*> -> attr(value) + is Map<*, *> -> attr(value as Map) + is Number -> attr(value) + is Set<*> -> when (val type = value.firstOrNull()) { // Attempt to determine set type by first element + null -> attr(value as Set) // FIXME Is this a bad idea for the empty set case? + is ByteArray -> attr(value as Set) + is Number -> attr(value as Set) + is String -> attr(value as Set) + is UByte -> attr(value as Set) + is UInt -> attr(value as Set) + is ULong -> attr(value as Set) + is UShort -> attr(value as Set) + else -> error("Unsupported set element type $type") + } + is String -> attr(value) + else -> error("Unsupported attribute value type ${value::class}") +} diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/values/NullableConverter.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/values/NullableConverter.kt index 89224861d22..44da31ecf64 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/values/NullableConverter.kt +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/values/NullableConverter.kt @@ -4,6 +4,7 @@ */ package aws.sdk.kotlin.hll.dynamodbmapper.values +import aws.sdk.kotlin.hll.dynamodbmapper.util.NULL_ATTR import aws.sdk.kotlin.hll.mapping.core.converters.Converter import aws.sdk.kotlin.hll.mapping.core.converters.SplittingConverter import aws.sdk.kotlin.hll.mapping.core.converters.mergeBy @@ -20,7 +21,7 @@ import kotlin.reflect.KClass */ public class NullableConverter(klass: KClass) : SplittingConverter { override fun convertTo(from: V?): Either = when (from) { - null -> Either.Left(AttributeValue.Null(true)) + null -> Either.Left(NULL_ATTR) else -> Either.Right(from) } diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/expressions/FilterTest.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/expressions/FilterTest.kt new file mode 100644 index 00000000000..72f00391213 --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/expressions/FilterTest.kt @@ -0,0 +1,799 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.FilterImpl +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.ParameterizingExpressionVisitor +import aws.sdk.kotlin.hll.dynamodbmapper.util.attr +import aws.sdk.kotlin.services.dynamodb.model.AttributeValue +import kotlin.test.Test +import kotlin.test.assertEquals + +class FilterTest { + @Test + fun testAnd() { + testFilters( + mapOf( + ":v0" to attr(5), + ":v1" to attr("banana"), + ":v2" to attr(null), + ), + "(foo = :v0) AND (bar < :v1) AND (baz <> :v2)" to { + and( + attr("foo") eq 5, + attr("bar") lt "banana", + attr("baz") neq null, + ) + }, + ) + } + + @Test + fun testBooleans() { + listOf(false, true, null).forEach { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + "contains(foo, :v0)" to { attr("foo") contains value }, + ) + } + } + + @Test + fun testByteArrays() { + listOf( + byteArrayOf(1, 2, 3), + byteArrayOf(4, 5, 6), + byteArrayOf(7, 8, 9), + ).forEach { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + "foo < :v0" to { attr("foo") lt value }, + "foo <= :v0" to { attr("foo") lte value }, + "foo > :v0" to { attr("foo") gt value }, + "foo >= :v0" to { attr("foo") gte value }, + "contains(foo, :v0)" to { attr("foo") contains value }, + ) + } + + (null as ByteArray?).let { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + "contains(foo, :v0)" to { attr("foo") contains value }, + ) + } + } + + @Test + fun testCollectionsOfByteArrays() { + testFilters( + mapOf( + ":v0" to attr(byteArrayOf(1, 2, 3)), + ":v1" to attr(byteArrayOf(4, 5, 6)), + ":v2" to attr(byteArrayOf(7, 8, 9)), + ), + "foo IN (:v0, :v1, :v2)" to { + attr("foo") isIn setOf( + byteArrayOf(1, 2, 3), + byteArrayOf(4, 5, 6), + byteArrayOf(7, 8, 9), + ) + }, + ) + } + + @Test + fun testCollectionsOfLists() { + testFilters( + mapOf( + ":v0" to attr(listOf("apple", false, 1, null)), + ":v1" to attr(listOf("banana", true, 2)), + ":v2" to attr(listOf("cherry", 3)), + ":v3" to attr(null), + ), + "foo IN (:v0, :v1, :v2, :v3)" to { + attr("foo") isIn setOf( + listOf("apple", false, 1, null), + listOf("banana", true, 2), + listOf("cherry", 3), + null, + ) + }, + ) + } + + @Test + fun testCollectionsOfMaps() { + testFilters( + mapOf( + ":v0" to attr(mapOf("a" to "apple", "b" to false, "c" to 1, "d" to null)), + ":v1" to attr(mapOf("e" to "banana", "f" to true, "g" to 2)), + ":v2" to attr(mapOf("h" to "cherry", "i" to 3)), + ":v3" to attr(null), + ), + "foo IN (:v0, :v1, :v2, :v3)" to { + attr("foo") isIn setOf( + mapOf("a" to "apple", "b" to false, "c" to 1, "d" to null), + mapOf("e" to "banana", "f" to true, "g" to 2), + mapOf("h" to "cherry", "i" to 3), + null, + ) + }, + ) + } + + @Test + fun testCollectionsOfNumbers() { + testFilters( + mapOf( + ":v0" to attr(42), + ":v1" to attr(-1_000_000_000_000_000L), + ":v2" to attr(null), + ), + "foo IN (:v0, :v1, :v2)" to { attr("foo") isIn setOf(42, -1_000_000_000_000_000L, null) }, + ) + } + + @Test + fun testCollectionsOfSetsOfByteArrays() { + // Collections of sets of arrays 😵‍💫 + + val sets = listOf( + setOf( + byteArrayOf(1, 2, 3), + byteArrayOf(4, 5, 6), + byteArrayOf(7, 8, 9), + ), + setOf(), + null, + ) + + testFilters( + mapOf( + ":v0" to attr(sets[0]), + ":v1" to attr(sets[1]), + ":v2" to attr(sets[2]), + ), + "foo IN (:v0, :v1, :v2)" to { attr("foo") isIn sets }, + ) + } + + @Test + fun testCollectionsOfSetsOfNumbers() { + val sets = listOf( + setOf( + 13.toByte(), + (-42).toShort(), + -5, + 31_556_952_000L, + 2.71828f, + 3.14159, + ), + setOf(), + null, + ) + + testFilters( + mapOf( + ":v0" to attr(sets[0]), + ":v1" to attr(sets[1]), + ":v2" to attr(sets[2]), + ), + "foo IN (:v0, :v1, :v2)" to { attr("foo") isIn sets }, + ) + } + + @Test + fun testCollectionsOfSetsOfStrings() { + val sets = listOf( + setOf( + "apple", + "banana", + "cherry", + ), + setOf(), + null, + ) + + testFilters( + mapOf( + ":v0" to attr(sets[0]), + ":v1" to attr(sets[1]), + ":v2" to attr(sets[2]), + ), + "foo IN (:v0, :v1, :v2)" to { attr("foo") isIn sets }, + ) + } + + @Test + fun testCollectionsOfSetsOfUBytes() { + val sets = listOf( + setOf( + UByte.MIN_VALUE, + 42.toUByte(), + UByte.MAX_VALUE, + ), + setOf(), + null, + ) + + testFilters( + mapOf( + ":v0" to attr(sets[0]), + ":v1" to attr(sets[1]), + ":v2" to attr(sets[2]), + ), + "foo IN (:v0, :v1, :v2)" to { attr("foo") isIn sets }, + ) + } + + @Test + fun testCollectionsOfSetsOfUInt() { + val sets = listOf( + setOf( + UInt.MIN_VALUE, + 42.toUInt(), + UInt.MAX_VALUE, + ), + setOf(), + null, + ) + + testFilters( + mapOf( + ":v0" to attr(sets[0]), + ":v1" to attr(sets[1]), + ":v2" to attr(sets[2]), + ), + "foo IN (:v0, :v1, :v2)" to { attr("foo") isIn sets }, + ) + } + + @Test + fun testCollectionsOfSetsOfULong() { + val sets = listOf( + setOf( + ULong.MIN_VALUE, + 42.toULong(), + ULong.MAX_VALUE, + ), + setOf(), + null, + ) + + testFilters( + mapOf( + ":v0" to attr(sets[0]), + ":v1" to attr(sets[1]), + ":v2" to attr(sets[2]), + ), + "foo IN (:v0, :v1, :v2)" to { attr("foo") isIn sets }, + ) + } + + @Test + fun testCollectionsOfSetsOfUShorts() { + val sets = listOf( + setOf( + UShort.MIN_VALUE, + 42.toUShort(), + UShort.MAX_VALUE, + ), + setOf(), + null, + ) + + testFilters( + mapOf( + ":v0" to attr(sets[0]), + ":v1" to attr(sets[1]), + ":v2" to attr(sets[2]), + ), + "foo IN (:v0, :v1, :v2)" to { attr("foo") isIn sets }, + ) + } + + @Test + fun testExists() = testFilters( + "attribute_exists(foo)" to { attr("foo").exists() }, + ) + + @Test + fun testExpressions() { + testFilters( + "foo = bar" to { attr("foo") eq attr("bar") }, + "foo <> bar" to { attr("foo") neq attr("bar") }, + "foo < bar" to { attr("foo") lt attr("bar") }, + "foo <= bar" to { attr("foo") lte attr("bar") }, + "foo > bar" to { attr("foo") gt attr("bar") }, + "foo >= bar" to { attr("foo") gte attr("bar") }, + "contains(foo, bar)" to { attr("foo") contains attr("bar") }, + "begins_with(foo, bar)" to { attr("foo") startsWith attr("bar") }, + "foo BETWEEN bar AND baz" to { attr("foo").isBetween(attr("bar"), attr("baz")) }, + "foo IN (bar, baz, qux)" to { attr("foo") isIn listOf(attr("bar"), attr("baz"), attr("qux")) }, + ) + + testFilters( + expectedAVs = null, + expectedANs = mapOf( + "#k0" to "Key.With.Dots", + "#k1" to "And", + "#k2" to "Or", + ), + tests = arrayOf( + "foo = Attr.#k0.#k1.#k2.Indices[5]" to { + attr("foo") eq attr("Attr")["Key.With.Dots"]["And"]["Or"]["Indices"][5] + }, + ), + ) + } + + @Test + fun testIsOfType() = + testFilters( + attr("S"), + "attribute_type(foo, :v0)" to { attr("foo") isOfType AttributeType.String }, + ) + + @Test + fun testLists() { + listOf( + listOf("apple", false, 1, null), + listOf("banana", true, 2), + listOf("cherry", 3), + null, + ).forEach { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + ) + } + } + + @Test + fun testMaps() { + listOf( + mapOf("a" to "apple", "b" to false, "c" to 1, "d" to null), + mapOf("e" to "banana", "f" to true, "g" to 2), + mapOf("h" to "cherry", "i" to 3), + null, + ).forEach { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + ) + } + } + + @Test + fun testNot() = testFilters( + "NOT (foo = bar)" to { not(attr("foo") eq attr("bar")) }, + ) + + @Test + fun testNotExists() = testFilters( + "attribute_not_exists(foo)" to { attr("foo").notExists() }, + ) + + @Test + fun testNumbers() { + listOf( + 13.toByte(), + (-42).toShort(), + -5, + 31_556_952_000L, + 2.71828f, + 3.14159, + ).forEach { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + "foo < :v0" to { attr("foo") lt value }, + "foo <= :v0" to { attr("foo") lte value }, + "foo > :v0" to { attr("foo") gt value }, + "foo >= :v0" to { attr("foo") gte value }, + "contains(foo, :v0)" to { attr("foo") contains value }, + ) + } + + testFilters( + mapOf( + ":v0" to attr(100), + ":v1" to attr(200), + ), + "foo BETWEEN :v0 AND :v1" to { attr("foo") isIn 100..200 }, + "foo IN (:v0, :v1)" to { attr("foo") isIn setOf(100, 200) }, + ) + + (null as Number?).let { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + "contains(foo, :v0)" to { attr("foo") contains value }, + ) + } + } + + @Test + fun testOr() { + testFilters( + mapOf( + ":v0" to attr(5), + ":v1" to attr("banana"), + ":v2" to attr(null), + ), + "(foo > :v0) OR (bar >= :v1) OR (baz = :v2)" to { + or( + attr("foo") gt 5, + attr("bar") gte "banana", + attr("baz") eq null, + ) + }, + ) + } + + @Test + fun testSetsOfByteArrays() { + listOf( + setOf( + byteArrayOf(1, 2, 3), + byteArrayOf(4, 5, 6), + byteArrayOf(7, 8, 9), + ), + setOf(), + null, + ).forEach { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + ) + } + } + + @Test + fun testSetsOfNumbers() { + listOf( + setOf( + 13.toByte(), + (-42).toShort(), + -5, + 31_556_952_000L, + 2.71828f, + 3.14159, + ), + setOf(), + null, + ).forEach { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + ) + } + } + + @Test + fun testSetsOfStrings() { + listOf( + setOf( + "apple", + "banana", + "cherry", + ), + setOf(), + null, + ).forEach { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + ) + } + } + + @Test + fun testSetsOfUBytes() { + listOf( + setOf( + UByte.MIN_VALUE, + 42.toUByte(), + UByte.MAX_VALUE, + ), + setOf(), + null, + ).forEach { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + ) + } + } + + @Test + fun testSetsOfUInts() { + listOf( + setOf( + UInt.MIN_VALUE, + 42.toUInt(), + UInt.MAX_VALUE, + ), + setOf(), + null, + ).forEach { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + ) + } + } + + @Test + fun testSetsOfULongs() { + listOf( + setOf( + ULong.MIN_VALUE, + 42.toULong(), + ULong.MAX_VALUE, + ), + setOf(), + null, + ).forEach { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + ) + } + } + + @Test + fun testSetsOfUShorts() { + listOf( + setOf( + UShort.MIN_VALUE, + 42.toUShort(), + UShort.MAX_VALUE, + ), + setOf(), + null, + ).forEach { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + ) + } + } + + @Test + fun testSize() = testFilters( + "size(foo)" to { attr("foo").size }, + ) + + @Test + fun testStrings() { + listOf( + "apple", + "banana", + "cherry", + ).forEach { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + "foo < :v0" to { attr("foo") lt value }, + "foo <= :v0" to { attr("foo") lte value }, + "foo > :v0" to { attr("foo") gt value }, + "foo >= :v0" to { attr("foo") gte value }, + "contains(foo, :v0)" to { attr("foo") contains value }, + "begins_with(foo, :v0)" to { attr("foo") startsWith value }, + ) + } + + testFilters( + mapOf( + ":v0" to attr("apple"), + ":v1" to attr("banana"), + ), + "foo BETWEEN :v0 AND :v1" to { attr("foo") isIn "apple".."banana" }, + "foo IN (:v0, :v1)" to { attr("foo") isIn setOf("apple", "banana") }, + ) + + (null as String?).let { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + "contains(foo, :v0)" to { attr("foo") contains value }, + ) + } + } + + @Test + fun testUBytes() { + listOf( + UByte.MIN_VALUE, + 42.toUByte(), + UByte.MAX_VALUE, + ).forEach { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + "foo < :v0" to { attr("foo") lt value }, + "foo <= :v0" to { attr("foo") lte value }, + "foo > :v0" to { attr("foo") gt value }, + "foo >= :v0" to { attr("foo") gte value }, + ) + } + + testFilters( + mapOf( + ":v0" to attr(100.toUByte()), + ":v1" to attr(200.toUByte()), + ), + "foo BETWEEN :v0 AND :v1" to { attr("foo") isIn UByteRange(100.toUByte(), 200.toUByte()) }, + "foo IN (:v0, :v1)" to { attr("foo") isIn setOf(100.toUByte(), 200.toUByte()) }, + ) + + (null as UByte?).let { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + ) + } + } + + @Test + fun testUInts() { + listOf( + UInt.MIN_VALUE, + 42.toUInt(), + UInt.MAX_VALUE, + ).forEach { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + "foo < :v0" to { attr("foo") lt value }, + "foo <= :v0" to { attr("foo") lte value }, + "foo > :v0" to { attr("foo") gt value }, + "foo >= :v0" to { attr("foo") gte value }, + ) + } + + testFilters( + mapOf( + ":v0" to attr(100.toUInt()), + ":v1" to attr(200.toUInt()), + ), + "foo BETWEEN :v0 AND :v1" to { attr("foo") isIn 100.toUInt().rangeTo(200.toUInt()) }, + "foo IN (:v0, :v1)" to { attr("foo") isIn setOf(100.toUInt(), 200.toUInt()) }, + ) + + (null as UInt?).let { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + ) + } + } + + @Test + fun testULongs() { + listOf( + ULong.MIN_VALUE, + 42.toULong(), + ULong.MAX_VALUE, + ).forEach { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + "foo < :v0" to { attr("foo") lt value }, + "foo <= :v0" to { attr("foo") lte value }, + "foo > :v0" to { attr("foo") gt value }, + "foo >= :v0" to { attr("foo") gte value }, + ) + } + + testFilters( + mapOf( + ":v0" to attr(100.toULong()), + ":v1" to attr(200.toULong()), + ), + "foo BETWEEN :v0 AND :v1" to { attr("foo") isIn 100.toULong().rangeTo(200.toULong()) }, + "foo IN (:v0, :v1)" to { attr("foo") isIn setOf(100.toULong(), 200.toULong()) }, + ) + + (null as ULong?).let { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + ) + } + } + + @Test + fun testUShorts() { + listOf( + UShort.MIN_VALUE, + 42.toUShort(), + UShort.MAX_VALUE, + ).forEach { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + "foo < :v0" to { attr("foo") lt value }, + "foo <= :v0" to { attr("foo") lte value }, + "foo > :v0" to { attr("foo") gt value }, + "foo >= :v0" to { attr("foo") gte value }, + ) + } + + testFilters( + mapOf( + ":v0" to attr(100.toUShort()), + ":v1" to attr(200.toUShort()), + ), + "foo BETWEEN :v0 AND :v1" to { attr("foo") isIn UShortRange(100.toUShort(), 200.toUShort()) }, + "foo IN (:v0, :v1)" to { attr("foo") isIn setOf(100.toUShort(), 200.toUShort()) }, + ) + + (null as UShort?).let { value -> + testFilters( + attr(value), + "foo = :v0" to { attr("foo") eq value }, + "foo <> :v0" to { attr("foo") neq value }, + ) + } + } + + private fun testFilters(vararg tests: Pair Expression>) { + testFilters(null, *tests) + } + + private fun testFilters(expectedAV: AttributeValue, vararg tests: Pair Expression>) = + testFilters(mapOf(":v0" to expectedAV), *tests) + + private fun testFilters( + expectedAVs: Map?, + vararg tests: Pair Expression>, + expectedANs: Map? = null, + ) = tests.forEach { (expectedExprString, block) -> + val parameterizer = ParameterizingExpressionVisitor() + val expr = FilterImpl.block() + val actualExprString = expr.accept(parameterizer) + + assertEquals(expectedExprString, actualExprString) + + val actualAVs = parameterizer.expressionAttributeValues() + assertEquals(expectedAVs, actualAVs) + + val actualANs = parameterizer.expressionAttributeNames() + assertEquals(expectedANs, actualANs) + } +} + +// Weirdly, Kotlin stdlib doesn't have range implementations for UByte and UShort (but it _does_ have UInt and ULong). +// So we're rolling our own here! +private data class UByteRange(override val start: UByte, override val endInclusive: UByte) : ClosedRange +private data class UShortRange(override val start: UShort, override val endInclusive: UShort) : ClosedRange diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/operations/DeleteItemTest.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/operations/DeleteItemTest.kt index ac161d60697..28f3aa121f2 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/operations/DeleteItemTest.kt +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/operations/DeleteItemTest.kt @@ -8,6 +8,7 @@ import aws.sdk.kotlin.hll.dynamodbmapper.items.AttributeDescriptor import aws.sdk.kotlin.hll.dynamodbmapper.items.ItemSchema import aws.sdk.kotlin.hll.dynamodbmapper.items.KeySpec import aws.sdk.kotlin.hll.dynamodbmapper.items.SimpleItemConverter +import aws.sdk.kotlin.hll.dynamodbmapper.model.itemOf import aws.sdk.kotlin.hll.dynamodbmapper.testutils.DdbLocalTest import aws.sdk.kotlin.hll.dynamodbmapper.values.scalars.IntConverter import aws.sdk.kotlin.hll.dynamodbmapper.values.scalars.StringConverter @@ -37,7 +38,7 @@ class DeleteItemTest : DdbLocalTest() { createTable( TABLE_NAME, schema, - mapOf("id" to "foo", "value" to 42), + itemOf("id" to "foo", "value" to 42), ) } diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/operations/GetItemTest.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/operations/GetItemTest.kt index 43e19754d43..fdacaa11c52 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/operations/GetItemTest.kt +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/operations/GetItemTest.kt @@ -9,6 +9,7 @@ import aws.sdk.kotlin.hll.dynamodbmapper.items.ItemSchema import aws.sdk.kotlin.hll.dynamodbmapper.items.KeySpec import aws.sdk.kotlin.hll.dynamodbmapper.items.SimpleItemConverter import aws.sdk.kotlin.hll.dynamodbmapper.model.Table +import aws.sdk.kotlin.hll.dynamodbmapper.model.itemOf import aws.sdk.kotlin.hll.dynamodbmapper.testutils.DdbLocalTest import aws.sdk.kotlin.hll.dynamodbmapper.values.scalars.IntConverter import aws.sdk.kotlin.hll.dynamodbmapper.values.scalars.StringConverter @@ -47,8 +48,8 @@ class GetItemTest : DdbLocalTest() { @BeforeAll fun setUp() = runTest { - createTable(PK_TABLE_NAME, pkSchema, mapOf("id" to 1, "value" to "foo")) - createTable(CK_TABLE_NAME, ckSchema, mapOf("id" to "abcd", "version" to 42, "value" to "foo")) + createTable(PK_TABLE_NAME, pkSchema, itemOf("id" to 1, "value" to "foo")) + createTable(CK_TABLE_NAME, ckSchema, itemOf("id" to "abcd", "version" to 42, "value" to "foo")) } private fun testGetItem( diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/operations/QueryTest.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/operations/QueryTest.kt index 9541cf75eff..525f9843aa1 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/operations/QueryTest.kt +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/operations/QueryTest.kt @@ -8,10 +8,11 @@ import aws.sdk.kotlin.hll.dynamodbmapper.items.AttributeDescriptor import aws.sdk.kotlin.hll.dynamodbmapper.items.ItemSchema import aws.sdk.kotlin.hll.dynamodbmapper.items.KeySpec import aws.sdk.kotlin.hll.dynamodbmapper.items.SimpleItemConverter +import aws.sdk.kotlin.hll.dynamodbmapper.model.itemOf +import aws.sdk.kotlin.hll.dynamodbmapper.model.toItem import aws.sdk.kotlin.hll.dynamodbmapper.pipeline.Interceptor import aws.sdk.kotlin.hll.dynamodbmapper.pipeline.LReqContext import aws.sdk.kotlin.hll.dynamodbmapper.testutils.DdbLocalTest -import aws.sdk.kotlin.hll.dynamodbmapper.testutils.ddbItem import aws.sdk.kotlin.hll.dynamodbmapper.values.scalars.IntConverter import aws.sdk.kotlin.hll.dynamodbmapper.values.scalars.StringConverter import kotlinx.coroutines.test.runTest @@ -75,28 +76,28 @@ class QueryTest : DdbLocalTest() { gsis = mapOf(TITLE_INDEX_NAME to titleSchema), lsis = mapOf(NAME_INDEX_NAME to empsByNameSchema), items = listOf( - mapOf( + itemOf( "companyId" to "foo-corp", "empId" to "AB0123", "name" to "Alice Birch", "title" to "SDE", "tenureYears" to 5, ), - mapOf( + itemOf( "companyId" to "foo-corp", "empId" to "AB0126", "name" to "Adriana Beech", "title" to "Manager", "tenureYears" to 7, ), - mapOf( + itemOf( "companyId" to "foo-corp", "empId" to "EF0124", "name" to "Eddie Fraser", "title" to "SDE", "tenureYears" to 3, ), - mapOf( + itemOf( "companyId" to "bar-corp", "empId" to "157X", "name" to "Charlie Douglas", @@ -128,30 +129,30 @@ class QueryTest : DdbLocalTest() { val items = assertNotNull(result.items) val expected = listOf( // FIXME query/scan don't support object mapping yet - mapOf( + itemOf( "companyId" to "foo-corp", "empId" to "AB0123", "name" to "Alice Birch", "title" to "SDE", "tenureYears" to 5, ), - mapOf( + itemOf( "companyId" to "foo-corp", "empId" to "AB0126", "name" to "Adriana Beech", "title" to "Manager", "tenureYears" to 7, ), - mapOf( + itemOf( "companyId" to "foo-corp", "empId" to "EF0124", "name" to "Eddie Fraser", "title" to "SDE", "tenureYears" to 3, ), - ).map(::ddbItem) + ) - assertContentEquals(expected, items) + assertContentEquals(expected, items.map { it.toItem() }) } @Test @@ -176,21 +177,21 @@ class QueryTest : DdbLocalTest() { val items = assertNotNull(result.items) val expected = listOf( // FIXME query/scan don't support object mapping yet - mapOf( + itemOf( "companyId" to "foo-corp", "empId" to "AB0126", "name" to "Adriana Beech", "title" to "Manager", ), - mapOf( + itemOf( "companyId" to "bar-corp", "empId" to "157X", "name" to "Charlie Douglas", "title" to "Manager", ), - ).map(::ddbItem) + ) - assertContentEquals(expected, items) + assertContentEquals(expected, items.map { it.toItem() }) } @Test @@ -215,39 +216,39 @@ class QueryTest : DdbLocalTest() { val items = assertNotNull(result.items) val expected = listOf( // FIXME query/scan don't support object mapping yet - mapOf( + itemOf( "companyId" to "foo-corp", "empId" to "AB0126", "name" to "Adriana Beech", "title" to "Manager", "tenureYears" to 7, ), - mapOf( + itemOf( "companyId" to "foo-corp", "empId" to "AB0123", "name" to "Alice Birch", "title" to "SDE", "tenureYears" to 5, ), - mapOf( + itemOf( "companyId" to "foo-corp", "empId" to "EF0124", "name" to "Eddie Fraser", "title" to "SDE", "tenureYears" to 3, ), - ).map(::ddbItem) + ) - assertContentEquals(expected, items) + assertContentEquals(expected, items.map { it.toItem() }) } } // FIXME ugly hack until conditions are implemented private class ExpressionAttributeInterceptor( - vararg attributeValues: Pair, + vararg attributeValues: Pair, ) : Interceptor { - val attributeValues = ddbItem(*attributeValues).mapKeys { (k, _) -> ":$k" } + val attributeValues = itemOf(*attributeValues).mapKeys { (k, _) -> ":$k" } override fun modifyBeforeInvocation(ctx: LReqContext): LowLevelQueryRequest = ctx.lowLevelRequest.copy { expressionAttributeValues = attributeValues } diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/testutils/AttributeValues.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/testutils/AttributeValues.kt deleted file mode 100644 index 7d51bf1b64f..00000000000 --- a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/testutils/AttributeValues.kt +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ -package aws.sdk.kotlin.hll.dynamodbmapper.testutils - -import aws.sdk.kotlin.services.dynamodb.model.AttributeValue -import kotlin.reflect.KClass -import kotlin.reflect.full.isSubclassOf - -fun attr(value: Boolean) = AttributeValue.Bool(value) -fun attr(value: ByteArray) = AttributeValue.B(value) -fun attr(value: List) = AttributeValue.L(value.map(::dynamicAttr)) -fun attr(vararg value: Any?) = attr(value.toList()) -fun attr(value: Map) = AttributeValue.M(value.mapValues { (_, v) -> dynamicAttr(v) }) -fun attr(vararg values: Pair) = attr(values.toMap()) -fun attr(value: Nothing?) = AttributeValue.Null(true) -fun attr(value: Number) = AttributeValue.N(value.toString()) -fun attr(value: Set) = AttributeValue.Bs(value.toList()) -fun attr(value: Set) = AttributeValue.Ns(value.map(Number::toString)) -fun attr(value: Set) = AttributeValue.Ss(value.toList()) -fun attr(value: String) = AttributeValue.S(value) - -// The unsigned types don't implement `Number` and so have to be handled individually - -@JvmName("attrUByte") -fun attr(value: Set) = AttributeValue.Ns(value.map(UByte::toString)) - -@JvmName("attrUInt") -fun attr(value: Set) = AttributeValue.Ns(value.map(UInt::toString)) - -@JvmName("attrULong") -fun attr(value: Set) = AttributeValue.Ns(value.map(ULong::toString)) - -@JvmName("attrUShort") -fun attr(value: Set) = AttributeValue.Ns(value.map(UShort::toString)) - -/** - * Converts a map of strings to values to a map of strings to [AttributeValue] - * @param item The item to convert - */ -fun ddbItem(item: Map) = item.mapValues { (_, v) -> dynamicAttr(v) } - -/** - * Converts a collection of tuples of strings to values to a map of strings to [AttributeValue] - * @param attributes The attributes to convert - */ -fun ddbItem(vararg attributes: Pair) = ddbItem(attributes.toMap()) - -@Suppress("UNCHECKED_CAST") -fun dynamicAttr(value: Any?): AttributeValue = when (value) { - null -> attr(null) - is Boolean -> attr(value) - is ByteArray -> attr(value) - is List<*> -> attr(value) - is Map<*, *> -> attr(value as Map) - is Number -> attr(value) - is Set<*> -> { - require(value.isNotEmpty()) { "Cannot determine type of empty set at runtime" } - val types = value.groupBy { it.getClass() }.keys - val type = types.singleOrNull() ?: error("Mixed set element types: $types") - - when { - type.isSubclassOf(ByteArray::class) -> attr(value as Set) - type.isSubclassOf(Number::class) -> attr(value as Set) - type.isSubclassOf(String::class) -> attr(value as Set) - type.isSubclassOf(UByte::class) -> attr(value as Set) - type.isSubclassOf(UInt::class) -> attr(value as Set) - type.isSubclassOf(ULong::class) -> attr(value as Set) - type.isSubclassOf(UShort::class) -> attr(value as Set) - else -> error("Unsupported set element type $type") - } - } - is String -> attr(value) - else -> error("Unsupported attribute value type ${value::class}") -} - -private fun Any?.getClass(): KClass<*> = if (this == null) Nothing::class else (this::class) diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/testutils/DdbClientExtensions.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/testutils/DdbClientExtensions.kt index 1f518f2e594..76bb72717e0 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/testutils/DdbClientExtensions.kt +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/testutils/DdbClientExtensions.kt @@ -7,6 +7,8 @@ package aws.sdk.kotlin.hll.dynamodbmapper.testutils import aws.sdk.kotlin.hll.dynamodbmapper.items.ItemSchema import aws.sdk.kotlin.hll.dynamodbmapper.items.KeySpec import aws.sdk.kotlin.hll.dynamodbmapper.items.SimpleItemConverter +import aws.sdk.kotlin.hll.dynamodbmapper.model.Item +import aws.sdk.kotlin.hll.dynamodbmapper.model.itemOf import aws.sdk.kotlin.services.dynamodb.DynamoDbClient import aws.sdk.kotlin.services.dynamodb.batchWriteItem import aws.sdk.kotlin.services.dynamodb.createTable @@ -75,9 +77,9 @@ suspend fun DynamoDbClient.createTable( * @param tableName The name of the table to fetch from * @param keys One or more tuples of string key to value */ -suspend fun DynamoDbClient.getItem(tableName: String, vararg keys: Pair) = getItem { +suspend fun DynamoDbClient.getItem(tableName: String, vararg keys: Pair) = getItem { this.tableName = tableName - key = ddbItem(keys.toMap()) + key = itemOf(*keys) } /** @@ -85,11 +87,11 @@ suspend fun DynamoDbClient.getItem(tableName: String, vararg keys: Pair>) { - val writeRequests = items.map { mapItem -> +suspend fun DynamoDbClient.putItems(tableName: String, items: List) { + val writeRequests = items.map { item -> WriteRequest { putRequest { - item = ddbItem(mapItem) + this.item = item } } } diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/testutils/DdbLocalTest.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/testutils/DdbLocalTest.kt index 487d59e1ed7..8c1a728e8ca 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/testutils/DdbLocalTest.kt +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/testutils/DdbLocalTest.kt @@ -6,6 +6,7 @@ package aws.sdk.kotlin.hll.dynamodbmapper.testutils import aws.sdk.kotlin.hll.dynamodbmapper.DynamoDbMapper import aws.sdk.kotlin.hll.dynamodbmapper.items.ItemSchema +import aws.sdk.kotlin.hll.dynamodbmapper.model.Item import aws.sdk.kotlin.runtime.auth.credentials.StaticCredentialsProvider import aws.sdk.kotlin.services.dynamodb.DynamoDbClient import aws.sdk.kotlin.services.dynamodb.deleteTable @@ -74,7 +75,7 @@ abstract class DdbLocalTest : AnnotationSpec() { * @param items A collection of maps of strings to values which will be mapped and persisted to the new table before * returning. This can be used to pre-populate a table for a test. */ - suspend fun createTable(name: String, schema: ItemSchema<*>, vararg items: Map) = + suspend fun createTable(name: String, schema: ItemSchema<*>, vararg items: Item) = createTable(name, schema, mapOf(), mapOf(), items.toList()) /** @@ -92,7 +93,7 @@ abstract class DdbLocalTest : AnnotationSpec() { schema: ItemSchema<*>, gsis: Map>, lsis: Map>, - items: List>, + items: List, ) { ddb.createTable(name, schema, gsis, lsis) tempTables += name diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/values/ValueConvertersTest.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/values/ValueConvertersTest.kt index e940632828e..87b91e87554 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/values/ValueConvertersTest.kt +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/values/ValueConvertersTest.kt @@ -4,8 +4,8 @@ */ package aws.sdk.kotlin.hll.dynamodbmapper.values -import aws.sdk.kotlin.hll.dynamodbmapper.testutils.attr -import aws.sdk.kotlin.hll.dynamodbmapper.testutils.dynamicAttr +import aws.sdk.kotlin.hll.dynamodbmapper.util.attr +import aws.sdk.kotlin.hll.dynamodbmapper.util.dynamicAttr import aws.sdk.kotlin.services.dynamodb.model.AttributeValue import kotlin.test.assertContentEquals import kotlin.test.assertEquals diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/values/collections/ListConverterTest.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/values/collections/ListConverterTest.kt index 307821dd8c4..cc67cfde4d4 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/values/collections/ListConverterTest.kt +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/values/collections/ListConverterTest.kt @@ -4,7 +4,7 @@ */ package aws.sdk.kotlin.hll.dynamodbmapper.values.collections -import aws.sdk.kotlin.hll.dynamodbmapper.testutils.attr +import aws.sdk.kotlin.hll.dynamodbmapper.util.attr import aws.sdk.kotlin.hll.dynamodbmapper.values.ValueConverter import aws.sdk.kotlin.hll.dynamodbmapper.values.ValueConvertersTest import aws.sdk.kotlin.services.dynamodb.model.AttributeValue diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/values/collections/MapConverterTest.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/values/collections/MapConverterTest.kt index 0373e6e4332..a9e65525349 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/values/collections/MapConverterTest.kt +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/test/aws/sdk/kotlin/hll/dynamodbmapper/values/collections/MapConverterTest.kt @@ -4,7 +4,7 @@ */ package aws.sdk.kotlin.hll.dynamodbmapper.values.collections -import aws.sdk.kotlin.hll.dynamodbmapper.testutils.attr +import aws.sdk.kotlin.hll.dynamodbmapper.util.attr import aws.sdk.kotlin.hll.dynamodbmapper.values.ValueConverter import aws.sdk.kotlin.hll.dynamodbmapper.values.ValueConvertersTest import aws.sdk.kotlin.services.dynamodb.model.AttributeValue diff --git a/settings.gradle.kts b/settings.gradle.kts index 49237132653..a48c72b988c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -75,7 +75,7 @@ if ("dynamodb".isBootstrappedService) { include(":hll:dynamodb-mapper:dynamodb-mapper-annotations") include(":hll:dynamodb-mapper:tests:dynamodb-mapper-annotation-processor-test") include(":hll:dynamodb-mapper:dynamodb-mapper-schema-generator-plugin") - include(":hll:dynamodb-mapper:tests:dynamodb-mapper-schema-generator-plugin-test") + // include(":hll:dynamodb-mapper:tests:dynamodb-mapper-schema-generator-plugin-test") } else { logger.warn(":services:dynamodb is not bootstrapped, skipping :hll:dynamodb-mapper and subprojects") } From 6e70b84804d7c95c483b5da22bcc8807c5438b8c Mon Sep 17 00:00:00 2001 From: Ian Botsford <83236726+ianbotsf@users.noreply.github.com> Date: Mon, 9 Sep 2024 22:02:28 +0000 Subject: [PATCH 2/4] (remove accidentally-included file) --- .../codegen/operations/model/MemberCodegenBehavior.kt | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/hll/dynamodb-mapper/dynamodb-mapper-codegen/src/main/kotlin/aws/sdk/kotlin/hll/dynamodbmapper/codegen/operations/model/MemberCodegenBehavior.kt b/hll/dynamodb-mapper/dynamodb-mapper-codegen/src/main/kotlin/aws/sdk/kotlin/hll/dynamodbmapper/codegen/operations/model/MemberCodegenBehavior.kt index 2c7d79b9255..079c475f249 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper-codegen/src/main/kotlin/aws/sdk/kotlin/hll/dynamodbmapper/codegen/operations/model/MemberCodegenBehavior.kt +++ b/hll/dynamodb-mapper/dynamodb-mapper-codegen/src/main/kotlin/aws/sdk/kotlin/hll/dynamodbmapper/codegen/operations/model/MemberCodegenBehavior.kt @@ -28,7 +28,6 @@ internal sealed interface MemberCodegenBehavior { member in unsupportedMembers -> Drop member.type in attrMapTypes -> if (member.name == "key") MapKeys else MapAll member.isTableName -> Hoist - member.isFilterExpression -> FilterExpression else -> PassThrough } } @@ -66,12 +65,6 @@ internal sealed interface MemberCodegenBehavior { * structure). */ data object Hoist : MemberCodegenBehavior - - /** - * Indicates that a member from a low-level structure represents a filter expression and should be replaced with a - * filter DSL - */ - data object FilterExpression : MemberCodegenBehavior } /** @@ -85,9 +78,6 @@ internal val Member.codegenBehavior: MemberCodegenBehavior else -> MemberCodegenBehavior.PassThrough } -private val Member.isFilterExpression: Boolean - get() = name == "filterExpression" && type == Types.Kotlin.StringNullable - private val Member.isTableName: Boolean get() = name == "tableName" && type == Types.Kotlin.StringNullable From 4668fd0de3afa88f597ca48246f4e77dce575678 Mon Sep 17 00:00:00 2001 From: Ian Botsford <83236726+ianbotsf@users.noreply.github.com> Date: Mon, 9 Sep 2024 22:03:33 +0000 Subject: [PATCH 3/4] (remove debugging build plugin) --- hll/dynamodb-mapper/dynamodb-mapper/build.gradle.kts | 2 -- 1 file changed, 2 deletions(-) diff --git a/hll/dynamodb-mapper/dynamodb-mapper/build.gradle.kts b/hll/dynamodb-mapper/dynamodb-mapper/build.gradle.kts index 05fc9e97132..2596d4194df 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/build.gradle.kts +++ b/hll/dynamodb-mapper/dynamodb-mapper/build.gradle.kts @@ -20,8 +20,6 @@ buildscript { plugins { alias(libs.plugins.ksp) - - id("org.jetbrains.kotlinx.kover") version "0.9.0-RC" // REMOVE ME } kotlin { From aa20947fd6f3182bb86a2bfbe1c870c058adc561 Mon Sep 17 00:00:00 2001 From: Ian Botsford <83236726+ianbotsf@users.noreply.github.com> Date: Thu, 12 Sep 2024 22:24:33 +0000 Subject: [PATCH 4/4] addressing PR feedback: refactor subinterfaces/implementations into their own files, revert accidental settings.gradle.kts change, clean up various KDocs --- .../dynamodb-mapper/api/dynamodb-mapper.api | 101 ++-- .../hll/dynamodbmapper/expressions/AndExpr.kt | 27 ++ .../expressions/AttributePath.kt | 75 +++ .../expressions/AttributeType.kt | 2 +- .../dynamodbmapper/expressions/BetweenExpr.kt | 40 ++ .../expressions/BooleanFuncExpr.kt | 54 +++ .../dynamodbmapper/expressions/Comparator.kt | 2 +- .../expressions/ComparisonExpr.kt | 40 ++ .../dynamodbmapper/expressions/Expressions.kt | 456 ------------------ .../hll/dynamodbmapper/expressions/Filter.kt | 30 +- .../hll/dynamodbmapper/expressions/InExpr.kt | 33 ++ .../dynamodbmapper/expressions/LiteralExpr.kt | 144 ++++++ .../hll/dynamodbmapper/expressions/NotExpr.kt | 27 ++ .../hll/dynamodbmapper/expressions/OrExpr.kt | 27 ++ .../expressions/ScalarFuncExpr.kt | 54 +++ .../expressions/internal/AndExprImpl.kt | 14 + .../expressions/internal/AttributePathImpl.kt | 23 + .../expressions/internal/BetweenExprImpl.kt | 14 + .../internal/BooleanFuncExprImpl.kt | 16 + .../internal/ComparisonExprImpl.kt | 15 + .../expressions/internal/ExpressionImpls.kt | 139 ------ .../expressions/internal/InExprImpl.kt | 10 + .../expressions/internal/LiteralExprImpl.kt | 10 + .../expressions/internal/NotExprImpl.kt | 10 + .../expressions/internal/OrExprImpl.kt | 14 + .../internal/ScalarFuncExprImpl.kt | 13 + settings.gradle.kts | 2 +- 27 files changed, 749 insertions(+), 643 deletions(-) create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/AndExpr.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/BetweenExpr.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/ComparisonExpr.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/InExpr.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/NotExpr.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/OrExpr.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/AndExprImpl.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/AttributePathImpl.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/BetweenExprImpl.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/BooleanFuncExprImpl.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ComparisonExprImpl.kt delete mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ExpressionImpls.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/InExprImpl.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/LiteralExprImpl.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/NotExprImpl.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/OrExprImpl.kt create mode 100644 hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ScalarFuncExprImpl.kt diff --git a/hll/dynamodb-mapper/dynamodb-mapper/api/dynamodb-mapper.api b/hll/dynamodb-mapper/dynamodb-mapper/api/dynamodb-mapper.api index d777c1226c1..52dee80cc72 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/api/dynamodb-mapper.api +++ b/hll/dynamodb-mapper/dynamodb-mapper/api/dynamodb-mapper.api @@ -41,6 +41,10 @@ public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/AndExpr$Default public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AndExpr;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; } +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/AndExprKt { + public static final fun AndExpr (Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AndExpr; +} + public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttrPathElement { } @@ -62,6 +66,12 @@ public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath$D public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; } +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePathKt { + public static final fun AttributePath (ILaws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath; + public static final fun AttributePath (Ljava/lang/String;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath; + public static synthetic fun AttributePath$default (Ljava/lang/String;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;ILjava/lang/Object;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath; +} + public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType : java/lang/Enum { public static final field Binary Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType; public static final field BinarySet Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType; @@ -90,6 +100,10 @@ public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/BetweenExpr$Def public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BetweenExpr;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; } +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/BetweenExprKt { + public static final fun BetweenExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BetweenExpr; +} + public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr : aws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression { } @@ -116,6 +130,12 @@ public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; } +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExprKt { + public static final fun BooleanFuncExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr; + public static final fun BooleanFuncExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;[Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr; + public static synthetic fun BooleanFuncExpr$default (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/List;ILjava/lang/Object;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr; +} + public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator : java/lang/Enum { public static final field EQUALS Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator; public static final field GREATER_THAN Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator; @@ -140,6 +160,10 @@ public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/ComparisonExpr$ public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ComparisonExpr;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; } +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/ComparisonExprKt { + public static final fun ComparisonExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ComparisonExpr; +} + public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression { public abstract fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; } @@ -157,43 +181,6 @@ public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/Ex public abstract fun visit (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr;)Ljava/lang/Object; } -public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionsKt { - public static final fun AndExpr (Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AndExpr; - public static final fun AttributePath (ILaws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath; - public static final fun AttributePath (Ljava/lang/String;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath; - public static synthetic fun AttributePath$default (Ljava/lang/String;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;ILjava/lang/Object;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath; - public static final fun BetweenExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BetweenExpr; - public static final fun BooleanFuncExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr; - public static final fun BooleanFuncExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;[Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr; - public static synthetic fun BooleanFuncExpr$default (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFunc;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/List;ILjava/lang/Object;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr; - public static final fun ComparisonExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ComparisonExpr; - public static final fun InExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/InExpr; - public static final fun LiteralExpr (Laws/sdk/kotlin/services/dynamodb/model/AttributeValue;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun LiteralExpr (Ljava/lang/Boolean;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun LiteralExpr (Ljava/lang/Number;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun LiteralExpr (Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun LiteralExpr (Ljava/lang/Void;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun LiteralExpr (Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun LiteralExpr (Ljava/util/Map;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun LiteralExpr ([B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun LiteralExpr-3swpYEE (Lkotlin/UByte;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun LiteralExpr-ADd3fzo (Lkotlin/ULong;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun LiteralExpr-ExVfyTY (Lkotlin/UInt;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun LiteralExpr-ffyZV3s (Lkotlin/UShort;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun LiteralExprSetByteArray (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun LiteralExprSetNumber (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun LiteralExprSetString (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun LiteralExprSetUByte (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun LiteralExprSetUInt (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun LiteralExprSetULong (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun LiteralExprSetUShort (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; - public static final fun NotExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/NotExpr; - public static final fun OrExpr (Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/OrExpr; - public static final fun ScalarFuncExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr; - public static final fun ScalarFuncExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;[Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr; - public static synthetic fun ScalarFuncExpr$default (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/List;ILjava/lang/Object;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr; -} - public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter { public abstract fun and (Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; public abstract fun and ([Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; @@ -410,6 +397,10 @@ public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/InExpr$DefaultI public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/InExpr;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; } +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/InExprKt { + public static final fun InExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;Ljava/util/Collection;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/InExpr; +} + public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr : aws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression { public abstract fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; public abstract fun getValue ()Laws/sdk/kotlin/services/dynamodb/model/AttributeValue; @@ -419,6 +410,28 @@ public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr$Def public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; } +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExprKt { + public static final fun LiteralExpr (Laws/sdk/kotlin/services/dynamodb/model/AttributeValue;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr (Ljava/lang/Boolean;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr (Ljava/lang/Number;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr (Ljava/lang/String;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr (Ljava/lang/Void;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr (Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr (Ljava/util/Map;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr ([B)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr-3swpYEE (Lkotlin/UByte;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr-ADd3fzo (Lkotlin/ULong;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr-ExVfyTY (Lkotlin/UInt;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExpr-ffyZV3s (Lkotlin/UShort;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExprSetByteArray (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExprSetNumber (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExprSetString (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExprSetUByte (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExprSetUInt (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExprSetULong (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; + public static final fun LiteralExprSetUShort (Ljava/util/Set;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr; +} + public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/NotExpr : aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr { public abstract fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; public abstract fun getOperand ()Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr; @@ -428,6 +441,10 @@ public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/NotExpr$Default public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/NotExpr;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; } +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/NotExprKt { + public static final fun NotExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/NotExpr; +} + public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/expressions/OrExpr : aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanExpr { public abstract fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; public abstract fun getOperands ()Ljava/util/List; @@ -437,6 +454,10 @@ public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/OrExpr$DefaultI public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/OrExpr;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; } +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/OrExprKt { + public static final fun OrExpr (Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/OrExpr; +} + public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc : java/lang/Enum { public static final field SIZE Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc; public static fun getEntries ()Lkotlin/enums/EnumEntries; @@ -456,6 +477,12 @@ public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr$ public static fun accept (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ExpressionVisitor;)Ljava/lang/Object; } +public final class aws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExprKt { + public static final fun ScalarFuncExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/List;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr; + public static final fun ScalarFuncExpr (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;[Laws/sdk/kotlin/hll/dynamodbmapper/expressions/Expression;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr; + public static synthetic fun ScalarFuncExpr$default (Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFunc;Laws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath;Ljava/util/List;ILjava/lang/Object;)Laws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr; +} + public abstract interface class aws/sdk/kotlin/hll/dynamodbmapper/items/AttributeDescriptor { public abstract fun getConverter ()Laws/sdk/kotlin/hll/mapping/core/converters/Converter; public abstract fun getGetter ()Lkotlin/jvm/functions/Function1; diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/AndExpr.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/AndExpr.kt new file mode 100644 index 00000000000..92265ad7838 --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/AndExpr.kt @@ -0,0 +1,27 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.AndExprImpl + +/** + * Represents an `AND` expression as described in + * [DynamoDB's **logical evaluations** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.LogicalEvaluations). + * This expression will be true if `(operand[0] && operand[1] && ... && operand[n - 1])`. + */ +public interface AndExpr : BooleanExpr { + /** + * A list of 2 or more [BooleanExpr] conditions which are ANDed together + */ + public val operands: List + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new [AndExpr] with the given [operands] + * @param operands A list of 2 or more [BooleanExpr] conditions which are ANDed together + */ +public fun AndExpr(operands: List): AndExpr = AndExprImpl(operands) diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath.kt new file mode 100644 index 00000000000..e57468ee847 --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributePath.kt @@ -0,0 +1,75 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.AttrPathIndexImpl +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.AttrPathNameImpl +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.AttributePathImpl + +/** + * Represents an element in an [AttributePath] + */ +public sealed interface AttrPathElement { + /** + * Represents the name of a top-level attribute or a key in a map + */ + public interface Name : AttrPathElement { + /** + * The name or key of this element + */ + public val name: String + } + + /** + * Represents an index into a list/set + */ + public interface Index : AttrPathElement { + /** + * The index (starting at `0`) + */ + public val index: Int + } +} + +/** + * Represents an expression that consists of an attribute. Attributes are referenced by attribute paths, analogous to + * [document paths in DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.Attributes.html#Expressions.Attributes.NestedElements.DocumentPathExamples). + * Attribute paths consist of one or more elements, which are either names (e.g., of a top-level attribute or a nested + * key in a map attribute) or indices (i.e., into a list). The first (and often only) element of an attribute path is a + * name. + * + * See [Filter] for more information about creating references to attributes. + */ +public interface AttributePath : Expression { + /** + * The [AttrPathElement] for this path + */ + public val element: AttrPathElement + + /** + * The parent [AttributePath] (if any). If [parent] is `null` then this instance represents a top-level attribute + * and [element] must be a name (not an index). + */ + public val parent: AttributePath? + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new [AttributePath] reference with the given name and optional parent path + * @param name The name or key of this element + * @param parent The parent [AttributePath] (if any) of this element. If [parent] is `null` then this instance + * represents a top-level attribute. + */ +public fun AttributePath(name: String, parent: AttributePath? = null): AttributePath = + AttributePathImpl(AttrPathNameImpl(name), parent) + +/** + * Creates a new [AttributePath] reference with the given index and parent path + * @param index The index (starting at `0`) of this element + * @param parent The parent [AttributePath] of this element + */ +public fun AttributePath(index: Int, parent: AttributePath): AttributePath = + AttributePathImpl(AttrPathIndexImpl(index), parent) diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType.kt index ed361ee56aa..eec2c1b4152 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType.kt +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/AttributeType.kt @@ -56,7 +56,7 @@ public enum class AttributeType(public val abbreviation: kotlin.String) { String("S"), /** - * String set data type, denoted in DynamoDB as `S` + * String set data type, denoted in DynamoDB as `SS` */ StringSet("SS"), } diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/BetweenExpr.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/BetweenExpr.kt new file mode 100644 index 00000000000..bbed7012cbb --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/BetweenExpr.kt @@ -0,0 +1,40 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.BetweenExprImpl + +/** + * Represents a `BETWEEN` expression as described in + * [DynamoDB's **making comparisons** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Comparators). + * This expression will be true if `value >= min && value <= max`. + */ +public interface BetweenExpr : BooleanExpr { + /** + * The value being compared to the [min] and [max] + */ + public val value: Expression + + /** + * The minimum bound for the comparison + */ + public val min: Expression + + /** + * The maximum bound for the comparison + */ + public val max: Expression + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new [BetweenExpr] for the given [value] and range bounded by [min] and [max] + * @param value The value being compared to the [min] and [max] + * @param min The minimum bound for the comparison + * @param max The maximum bound for the comparison + */ +public fun BetweenExpr(value: Expression, min: Expression, max: Expression): BetweenExpr = + BetweenExprImpl(value, min, max) diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr.kt new file mode 100644 index 00000000000..c110c7200f8 --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/BooleanFuncExpr.kt @@ -0,0 +1,54 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.BooleanFuncExprImpl + +/** + * Represents a function expression that yields a boolean result as described in + * [DynamoDB's **function** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) + */ +public interface BooleanFuncExpr : BooleanExpr { + /** + * The specific boolean function to use + */ + public val func: BooleanFunc + + /** + * The attribute path to pass as the function's first argument + */ + public val path: AttributePath + + /** + * Any additional arguments used by the function + */ + public val additionalOperands: List + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new boolean function expression + * @param func The specific boolean function to use + * @param path The attribute path to pass as the function's first argument + * @param additionalOperands Any additional arguments used by the function + */ +public fun BooleanFuncExpr( + func: BooleanFunc, + path: AttributePath, + additionalOperands: List = listOf(), +): BooleanFuncExpr = BooleanFuncExprImpl(func, path, additionalOperands) + +/** + * Creates a new boolean function expression + * @param func The specific boolean function to use + * @param path The attribute path to pass as the function's first argument + * @param additionalOperands Any additional arguments used by the function + */ +public fun BooleanFuncExpr( + func: BooleanFunc, + path: AttributePath, + vararg additionalOperands: Expression, +): BooleanFuncExpr = BooleanFuncExprImpl(func, path, additionalOperands.toList()) diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator.kt index 4565973db1b..d93b5d61093 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator.kt +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Comparator.kt @@ -35,7 +35,7 @@ public enum class Comparator(public val exprString: String) { GREATER_THAN(">"), /** - * A greater-than-or-equal-to comparison, equivalent to `>=` in Kotlin + * A greater-than-or-equal-to comparison, equivalent to `>=` in Kotlin and DynamoDB */ GREATER_THAN_OR_EQUAL(">="), } diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/ComparisonExpr.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/ComparisonExpr.kt new file mode 100644 index 00000000000..7a1ab717bc8 --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/ComparisonExpr.kt @@ -0,0 +1,40 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.ComparisonExprImpl + +/** + * Represents a comparison expression as described in + * [DynamoDB's **making comparisons** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Comparators). + * The specific type of comparison is identified by the [comparator] field. + */ +public interface ComparisonExpr : BooleanExpr { + /** + * The [Comparator] to use in the expression + */ + public val comparator: Comparator + + /** + * The left value being compared + */ + public val left: Expression + + /** + * The right value being compared + */ + public val right: Expression + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new comparison expression + * @param comparator The [Comparator] to use in the expression + * @param left The left value being compared + * @param right The right value being compared + */ +public fun ComparisonExpr(comparator: Comparator, left: Expression, right: Expression): ComparisonExpr = + ComparisonExprImpl(comparator, left, right) diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Expressions.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Expressions.kt index 6d53cedba62..06e0bf0f8e2 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Expressions.kt +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Expressions.kt @@ -4,14 +4,6 @@ */ package aws.sdk.kotlin.hll.dynamodbmapper.expressions -import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.* -import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.AndExprImpl -import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.AttrPathIndexImpl -import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.AttrPathNameImpl -import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.AttributePathImpl -import aws.sdk.kotlin.hll.dynamodbmapper.util.attr -import aws.sdk.kotlin.services.dynamodb.model.AttributeValue - /** * Represents any kind of expression. This is an abstract top-level interface and describes no details about an * expression on its own. Expressions may be of various specific types (e.g., [AttributePath], [ComparisonExpr], @@ -36,451 +28,3 @@ public sealed interface Expression { * declarations. */ public interface BooleanExpr : Expression - -/** - * Represents an element in an [AttributePath] - */ -public sealed interface AttrPathElement { - /** - * Represents the name of a top-level attribute or a key in a map - */ - public interface Name : AttrPathElement { - /** - * The name or key of this element - */ - public val name: String - } - - /** - * Represents an index into a list/set - */ - public interface Index : AttrPathElement { - /** - * The index (starting at `0`) - */ - public val index: Int - } -} - -/** - * Represents an expression that consists of an attribute. Attributes are referenced by attribute paths, analogous to - * [document paths in DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.Attributes.html#Expressions.Attributes.NestedElements.DocumentPathExamples). - * Attribute paths consist of one or more elements, which are either names (e.g., of a top-level attribute or a nested - * key in a map attribute) or indices (i.e., into a list). The first (and often only) element of an attribute path is a - * name. - * - * See [Filter] for more information about creating references to attributes. - */ -public interface AttributePath : Expression { - /** - * The [AttrPathElement] for this path - */ - public val element: AttrPathElement - - /** - * The parent [AttributePath] (if any). If [parent] is `null` then this instance represents a top-level attribute - * and [element] must be a name (not an index). - */ - public val parent: AttributePath? - - override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) -} - -/** - * Creates a new [AttributePath] reference with the given name and optional parent path - * @param name The name or key of this element - * @param parent The parent [AttributePath] (if any) of this element. If [parent] is `null` then this instance - * represents a top-level attribute. - */ -public fun AttributePath(name: String, parent: AttributePath? = null): AttributePath = - AttributePathImpl(AttrPathNameImpl(name), parent) - -/** - * Creates a new [AttributePath] reference with the given index and parent path - * @param index The index (starting at `0`) of this element - * @param parent The parent [AttributePath] of this element - */ -public fun AttributePath(index: Int, parent: AttributePath): AttributePath = - AttributePathImpl(AttrPathIndexImpl(index), parent) - -/** - * Represents an `AND` expression as described in - * [DynamoDB's **logical evaluations** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.LogicalEvaluations). - * This expression will be true if `(operand[0] && operand[1] && ... && operand[n - 1])`. - */ -public interface AndExpr : BooleanExpr { - /** - * A list of 2 or more [BooleanExpr] conditions which are ANDed together - */ - public val operands: List - - override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) -} - -/** - * Creates a new [AndExpr] with the given [operands] - * @param operands A list of 2 or more [BooleanExpr] conditions which are ANDed together - */ -public fun AndExpr(operands: List): AndExpr = AndExprImpl(operands) - -/** - * Represents a `BETWEEN` expression as described in - * [DynamoDB's **making comparisons** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Comparators). - * This expression will be true if `value >= min && value <= max`. - */ -public interface BetweenExpr : BooleanExpr { - /** - * The value being compared to the [min] and [max] - */ - public val value: Expression - - /** - * The minimum bound for the comparison - */ - public val min: Expression - - /** - * The maximum bound for the comparison - */ - public val max: Expression - - override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) -} - -/** - * Creates a new [BetweenExpr] for the given [value] and range bounded by [min] and [max] - * @param value The value being compared to the [min] and [max] - * @param min The minimum bound for the comparison - * @param max The maximum bound for the comparison - */ -public fun BetweenExpr(value: Expression, min: Expression, max: Expression): BetweenExpr = - BetweenExprImpl(value, min, max) - -/** - * Represents a function expression that yields a boolean result as described in - * [DynamoDB's **function** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) - */ -public interface BooleanFuncExpr : BooleanExpr { - /** - * The specific boolean function to use - */ - public val func: BooleanFunc - - /** - * The attribute path to pass as the function's first argument - */ - public val path: AttributePath - - /** - * Any additional arguments used by the function - */ - public val additionalOperands: List - - override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) -} - -/** - * Creates a new boolean function expression - * @param func The specific boolean function to use - * @param path The attribute path to pass as the function's first argument - * @param additionalOperands Any additional arguments used by the function - */ -public fun BooleanFuncExpr( - func: BooleanFunc, - path: AttributePath, - additionalOperands: List = listOf(), -): BooleanFuncExpr = BooleanFuncExprImpl(func, path, additionalOperands) - -/** - * Creates a new boolean function expression - * @param func The specific boolean function to use - * @param path The attribute path to pass as the function's first argument - * @param additionalOperands Any additional arguments used by the function - */ -public fun BooleanFuncExpr( - func: BooleanFunc, - path: AttributePath, - vararg additionalOperands: Expression, -): BooleanFuncExpr = BooleanFuncExprImpl(func, path, additionalOperands.toList()) - -/** - * Represents a comparison expression as described in - * [DynamoDB's **making comparisons** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Comparators). - * The specific type of comparison is identified by the [comparator] field. - */ -public interface ComparisonExpr : BooleanExpr { - /** - * The [Comparator] to use in the expression - */ - public val comparator: Comparator - - /** - * The left value being compared - */ - public val left: Expression - - /** - * The right value being compared - */ - public val right: Expression - - override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) -} - -/** - * Creates a new comparison expression - * @param comparator The [Comparator] to use in the expression - * @param left The left value being compared - * @param right The right value being compared - */ -public fun ComparisonExpr(comparator: Comparator, left: Expression, right: Expression): ComparisonExpr = - ComparisonExprImpl(comparator, left, right) - -/** - * Represents an `IN` expression as described in - * [DynamoDB's **making comparisons** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Comparators). - * This expression will be true if `value in set` (or, equivalently, if `set.contains(value)`). - */ -public interface InExpr : BooleanExpr { - /** - * The value to check for in [set] - */ - public val value: Expression - - /** - * The set of values to compare against [value] - */ - public val set: Collection - - override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) -} - -/** - * Creates a new `IN` expression - * @param value The value to check for in [set] - * @param set The set of values to compare against [value] - */ -public fun InExpr(value: Expression, set: Collection): InExpr = InExprImpl(value, set) - -/** - * Represents an expression that consists of a single literal value - */ -public interface LiteralExpr : Expression { - /** - * The low-level DynamoDB representation of the literal value - */ - public val value: AttributeValue - - override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) -} - -/** - * Creates a new literal expression - * @param value The low-level DynamoDB representation of the literal value - */ -public fun LiteralExpr(value: AttributeValue): LiteralExpr = LiteralExprImpl(value) - -private val NULL_LITERAL = LiteralExpr(attr(null)) - -/** - * Creates a new literal expression - * @param value The literal value which will be converted to an [AttributeValue] - */ -public fun LiteralExpr(value: Boolean?): LiteralExpr = LiteralExpr(attr(value)) - -/** - * Creates a new literal expression - * @param value The literal value which will be converted to an [AttributeValue] - */ -public fun LiteralExpr(value: ByteArray?): LiteralExpr = LiteralExpr(attr(value)) - -/** - * Creates a new literal expression - * @param value The literal value which will be converted to an [AttributeValue] - */ -public fun LiteralExpr(value: List?): LiteralExpr = LiteralExpr(attr(value)) - -/** - * Creates a new literal expression - * @param value The literal value which will be converted to an [AttributeValue] - */ -public fun LiteralExpr(value: Map?): LiteralExpr = LiteralExpr(attr(value)) - -/** - * Creates a new literal expression - * @param value The literal value which will be converted to an [AttributeValue] - */ -@Suppress("UNUSED_PARAMETER") -public fun LiteralExpr(value: Nothing?): LiteralExpr = NULL_LITERAL - -/** - * Creates a new literal expression - * @param value The literal value which will be converted to an [AttributeValue] - */ -public fun LiteralExpr(value: Number?): LiteralExpr = LiteralExpr(attr(value)) - -/** - * Creates a new literal expression - * @param value The literal value which will be converted to an [AttributeValue] - */ -@JvmName("LiteralExprSetByteArray") -public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) - -/** - * Creates a new literal expression - * @param value The literal value which will be converted to an [AttributeValue] - */ -@JvmName("LiteralExprSetNumber") -public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) - -/** - * Creates a new literal expression - * @param value The literal value which will be converted to an [AttributeValue] - */ -@JvmName("LiteralExprSetString") -public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) - -/** - * Creates a new literal expression - * @param value The literal value which will be converted to an [AttributeValue] - */ -@JvmName("LiteralExprSetUByte") -public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) - -/** - * Creates a new literal expression - * @param value The literal value which will be converted to an [AttributeValue] - */ -@JvmName("LiteralExprSetUInt") -public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) - -/** - * Creates a new literal expression - * @param value The literal value which will be converted to an [AttributeValue] - */ -@JvmName("LiteralExprSetULong") -public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) - -/** - * Creates a new literal expression - * @param value The literal value which will be converted to an [AttributeValue] - */ -@JvmName("LiteralExprSetUShort") -public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) - -/** - * Creates a new literal expression - * @param value The literal value which will be converted to an [AttributeValue] - */ -public fun LiteralExpr(value: String?): LiteralExpr = LiteralExpr(attr(value)) - -/** - * Creates a new literal expression - * @param value The literal value which will be converted to an [AttributeValue] - */ -public fun LiteralExpr(value: UByte?): LiteralExpr = LiteralExpr(attr(value)) - -/** - * Creates a new literal expression - * @param value The literal value which will be converted to an [AttributeValue] - */ -public fun LiteralExpr(value: UInt?): LiteralExpr = LiteralExpr(attr(value)) - -/** - * Creates a new literal expression - * @param value The literal value which will be converted to an [AttributeValue] - */ -public fun LiteralExpr(value: ULong?): LiteralExpr = LiteralExpr(attr(value)) - -/** - * Creates a new literal expression - * @param value The literal value which will be converted to an [AttributeValue] - */ -public fun LiteralExpr(value: UShort?): LiteralExpr = LiteralExpr(attr(value)) - -/** - * Represents a `NOT` expression as described in - * [DynamoDB's **logical evaluations** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.LogicalEvaluations). - * This expression will be true if `!operand` (i.e., `operand` evaluates to `false`). - */ -public interface NotExpr : BooleanExpr { - /** - * The condition to negate - */ - public val operand: BooleanExpr - - override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) -} - -/** - * Creates a new `NOT` expression - * @param operand The condition to negate - */ -public fun NotExpr(operand: BooleanExpr): NotExpr = NotExprImpl(operand) - -/** - * Represents an `OR` expression as described in - * [DynamoDB's **logical evaluations** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.LogicalEvaluations). - * This expression will be true if `(operand[0] || operand[1] || ... || operand[n - 1])`. - */ -public interface OrExpr : BooleanExpr { - /** - * A list of 2 or more [BooleanExpr] conditions which are ANDed together - */ - public val operands: List - - override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) -} - -/** - * Creates a new [OrExpr] with the given [operands] - * @param operands A list of 2 or more [BooleanExpr] conditions which are ORed together - */ -public fun OrExpr(operands: List): OrExpr = OrExprImpl(operands) - -/** - * Represents a function expression that yields a non-boolean result as described in - * [DynamoDB's **function** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) - */ -public interface ScalarFuncExpr : BooleanExpr { - /** - * The specific non-boolean function to use - */ - public val func: ScalarFunc - - /** - * The attribute path to pass as the function's first argument - */ - public val path: AttributePath - - /** - * Any additional arguments used by the function - */ - public val additionalOperands: List - - override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) -} - -/** - * Creates a new non-boolean function expression - * @param func The specific non-boolean function to use - * @param path The attribute path to pass as the function's first argument - * @param additionalOperands Any additional arguments used by the function - */ -public fun ScalarFuncExpr( - func: ScalarFunc, - path: AttributePath, - additionalOperands: List = listOf(), -): ScalarFuncExpr = ScalarFuncExprImpl(func, path, additionalOperands) - -/** - * Creates a new non-boolean function expression - * @param func The specific non-boolean function to use - * @param path The attribute path to pass as the function's first argument - * @param additionalOperands Any additional arguments used by the function - */ -public fun ScalarFuncExpr( - func: ScalarFunc, - path: AttributePath, - vararg additionalOperands: Expression, -): ScalarFuncExpr = ScalarFuncExprImpl(func, path, additionalOperands.toList()) diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter.kt index 8a873469e4e..f49162422f8 100644 --- a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter.kt +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/Filter.kt @@ -125,7 +125,7 @@ import aws.sdk.kotlin.hll.dynamodbmapper.util.dynamicAttr * ``` * * This block checks for value of the attribute `foo` equalling `42` and the value of attribute `bar` _not_ equalling - * `42`. This is roughly equivalent to the Kotlin syntax: + * `42`. This is logically equivalent to the Kotlin syntax: * * ```kotlin * (foo == 42 && bar != 42) @@ -151,7 +151,7 @@ import aws.sdk.kotlin.hll.dynamodbmapper.util.dynamicAttr * * The value of attribute `bar` is less than the value of `baz` **–and–** the value of `baz` is greater/equal to `42` * * The value of attribute `qux` is not one of `"ready"`, `"steady"`, or `"go"` * - * This is roughly equivalent to the Kotlin syntax: + * This is logically equivalent to the Kotlin syntax: * * ```kotlin * (foo == "apple") || (bar < baz && baz >= 42) || qux !in setOf("ready", "steady", "go") @@ -161,12 +161,23 @@ import aws.sdk.kotlin.hll.dynamodbmapper.util.dynamicAttr * * Several additional filter expressions are possible via the following methods/properties: * - * * [contains] — checks if a string/list attribute value contains the given value - * * [exists] — checks if _any value_ (including `null`) exists for an attribute - * * [notExists] — checks if no value is present for an attribute (i.e., the attribute is "undefined" for an item) - * * [isOfType] — checks if an attribute value is of the given type - * * [size] — gets the size of an attribute (e.g., number of elements in list/map/set, the length of a string, etc.) - * * [startsWith] — checks if a string attribute value starts with the given value + * * [contains] — Checks if a string/list attribute value contains the given value + * * [exists] — Checks if _any value_ (including `null`) exists for an attribute. The low-level DynamoDB function for + * this is `attribute_exists`. + * * [notExists] — Checks if no value is present for an attribute (i.e., the attribute is "undefined" for an item). The + * low-level DynamoDB function for this is `attribute_not_exists`. + * * [isOfType] — Checks if an attribute value is of the given type. The low-level DynamoDB function for this is + * `attribute_type`. + * * [size] — Gets the size of an attribute (e.g., number of elements in list/map/set, the length of a string, etc.) + * * [startsWith] — Checks if a string attribute value starts with the given value. The low-level DynamoDB function for + * this is `begins_with`. + * + * For example: + * + * ```kotlin + * attr("foo") contains 13 // Checks whether the value of attribute `foo` contains the value `13` + * attr("bar").exists() // Checks whether any value exists for `bar` (including `null`) + * ``` */ public interface Filter { // ATTRIBUTES @@ -649,6 +660,9 @@ public interface Filter { */ public fun AttributePath.isBetween(min: Expression, max: Expression): BooleanExpr + // TODO The following overloads support [ClosedRange] but [OpenEndRange] also exists. DynamoDB expressions don't + // support it directly but we may be able to cheese it with two inequalities ANDed together. + /** * Creates a range expression for verifying this expression is in the given range * @param range The range to check diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/InExpr.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/InExpr.kt new file mode 100644 index 00000000000..ed4f320e4af --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/InExpr.kt @@ -0,0 +1,33 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.InExprImpl + +/** + * Represents an `IN` expression as described in + * [DynamoDB's **making comparisons** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Comparators). + * This expression will be true if `value in set` (or, equivalently, if `set.contains(value)`). + */ +public interface InExpr : BooleanExpr { + /** + * The value to check for in [set] + */ + public val value: Expression + + /** + * The set of values to compare against [value] + */ + public val set: Collection + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new `IN` expression + * @param value The value to check for in [set] + * @param set The set of values to compare against [value] + */ +public fun InExpr(value: Expression, set: Collection): InExpr = InExprImpl(value, set) diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr.kt new file mode 100644 index 00000000000..6dd2854e38a --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/LiteralExpr.kt @@ -0,0 +1,144 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.LiteralExprImpl +import aws.sdk.kotlin.hll.dynamodbmapper.util.attr +import aws.sdk.kotlin.services.dynamodb.model.AttributeValue + +/** + * Represents an expression that consists of a single literal value + */ +public interface LiteralExpr : Expression { + /** + * The low-level DynamoDB representation of the literal value + */ + public val value: AttributeValue + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new literal expression + * @param value The low-level DynamoDB representation of the literal value + */ +public fun LiteralExpr(value: AttributeValue): LiteralExpr = LiteralExprImpl(value) +private val NULL_LITERAL = LiteralExpr(attr(null)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: Boolean?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: ByteArray?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: List?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: Map?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +@Suppress("UNUSED_PARAMETER") +public fun LiteralExpr(value: Nothing?): LiteralExpr = NULL_LITERAL + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: Number?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +@JvmName("LiteralExprSetByteArray") +public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +@JvmName("LiteralExprSetNumber") +public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +@JvmName("LiteralExprSetString") +public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +@JvmName("LiteralExprSetUByte") +public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +@JvmName("LiteralExprSetUInt") +public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +@JvmName("LiteralExprSetULong") +public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +@JvmName("LiteralExprSetUShort") +public fun LiteralExpr(value: Set?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: String?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: UByte?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: UInt?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: ULong?): LiteralExpr = LiteralExpr(attr(value)) + +/** + * Creates a new literal expression + * @param value The literal value which will be converted to an [AttributeValue] + */ +public fun LiteralExpr(value: UShort?): LiteralExpr = LiteralExpr(attr(value)) diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/NotExpr.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/NotExpr.kt new file mode 100644 index 00000000000..c0591e2ae2c --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/NotExpr.kt @@ -0,0 +1,27 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.NotExprImpl + +/** + * Represents a `NOT` expression as described in + * [DynamoDB's **logical evaluations** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.LogicalEvaluations). + * This expression will be true if `!operand` (i.e., `operand` evaluates to `false`). + */ +public interface NotExpr : BooleanExpr { + /** + * The condition to negate + */ + public val operand: BooleanExpr + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new `NOT` expression + * @param operand The condition to negate + */ +public fun NotExpr(operand: BooleanExpr): NotExpr = NotExprImpl(operand) diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/OrExpr.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/OrExpr.kt new file mode 100644 index 00000000000..6192e4d90b3 --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/OrExpr.kt @@ -0,0 +1,27 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.OrExprImpl + +/** + * Represents an `OR` expression as described in + * [DynamoDB's **logical evaluations** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.LogicalEvaluations). + * This expression will be true if `(operand[0] || operand[1] || ... || operand[n - 1])`. + */ +public interface OrExpr : BooleanExpr { + /** + * A list of 2 or more [BooleanExpr] conditions which are ANDed together + */ + public val operands: List + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new [OrExpr] with the given [operands] + * @param operands A list of 2 or more [BooleanExpr] conditions which are ORed together + */ +public fun OrExpr(operands: List): OrExpr = OrExprImpl(operands) diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr.kt new file mode 100644 index 00000000000..c835078916b --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/ScalarFuncExpr.kt @@ -0,0 +1,54 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal.ScalarFuncExprImpl + +/** + * Represents a function expression that yields a non-boolean result as described in + * [DynamoDB's **function** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) + */ +public interface ScalarFuncExpr : BooleanExpr { + /** + * The specific non-boolean function to use + */ + public val func: ScalarFunc + + /** + * The attribute path to pass as the function's first argument + */ + public val path: AttributePath + + /** + * Any additional arguments used by the function + */ + public val additionalOperands: List + + override fun accept(visitor: ExpressionVisitor): T = visitor.visit(this) +} + +/** + * Creates a new non-boolean function expression + * @param func The specific non-boolean function to use + * @param path The attribute path to pass as the function's first argument + * @param additionalOperands Any additional arguments used by the function + */ +public fun ScalarFuncExpr( + func: ScalarFunc, + path: AttributePath, + additionalOperands: List = listOf(), +): ScalarFuncExpr = ScalarFuncExprImpl(func, path, additionalOperands) + +/** + * Creates a new non-boolean function expression + * @param func The specific non-boolean function to use + * @param path The attribute path to pass as the function's first argument + * @param additionalOperands Any additional arguments used by the function + */ +public fun ScalarFuncExpr( + func: ScalarFunc, + path: AttributePath, + vararg additionalOperands: Expression, +): ScalarFuncExpr = ScalarFuncExprImpl(func, path, additionalOperands.toList()) diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/AndExprImpl.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/AndExprImpl.kt new file mode 100644 index 00000000000..a190d854265 --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/AndExprImpl.kt @@ -0,0 +1,14 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.AndExpr +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.BooleanExpr + +internal data class AndExprImpl(override val operands: List) : AndExpr { + init { + require(operands.size > 1) { "AND operations require two or more operands" } + } +} diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/AttributePathImpl.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/AttributePathImpl.kt new file mode 100644 index 00000000000..c1cbbec9643 --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/AttributePathImpl.kt @@ -0,0 +1,23 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.AttrPathElement +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.AttributePath + +internal data class AttrPathNameImpl(override val name: String) : AttrPathElement.Name + +internal data class AttrPathIndexImpl(override val index: Int) : AttrPathElement.Index + +internal data class AttributePathImpl( + override val element: AttrPathElement, + override val parent: AttributePath? = null, +) : AttributePath { + init { + require(element is AttrPathElement.Name || parent != null) { + "Top-level attribute paths must be names (not indices)" + } + } +} diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/BetweenExprImpl.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/BetweenExprImpl.kt new file mode 100644 index 00000000000..af5b9f4e2b4 --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/BetweenExprImpl.kt @@ -0,0 +1,14 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.BetweenExpr +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.Expression + +internal data class BetweenExprImpl( + override val value: Expression, + override val min: Expression, + override val max: Expression, +) : BetweenExpr diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/BooleanFuncExprImpl.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/BooleanFuncExprImpl.kt new file mode 100644 index 00000000000..2799ac5e14e --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/BooleanFuncExprImpl.kt @@ -0,0 +1,16 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.AttributePath +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.BooleanFunc +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.BooleanFuncExpr +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.Expression + +internal data class BooleanFuncExprImpl( + override val func: BooleanFunc, + override val path: AttributePath, + override val additionalOperands: List = listOf(), +) : BooleanFuncExpr diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ComparisonExprImpl.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ComparisonExprImpl.kt new file mode 100644 index 00000000000..4cfbc0c6fb6 --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ComparisonExprImpl.kt @@ -0,0 +1,15 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.Comparator +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.ComparisonExpr +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.Expression + +internal data class ComparisonExprImpl( + override val comparator: Comparator, + override val left: Expression, + override val right: Expression, +) : ComparisonExpr diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ExpressionImpls.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ExpressionImpls.kt deleted file mode 100644 index bc18d76c91b..00000000000 --- a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ExpressionImpls.kt +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ -package aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal - -import aws.sdk.kotlin.hll.dynamodbmapper.expressions.* -import aws.sdk.kotlin.hll.dynamodbmapper.expressions.LiteralExpr -import aws.sdk.kotlin.services.dynamodb.model.AttributeValue - -/** - * Represents the name of a top-level attribute or a key in a map - * @param name The name or key - */ -internal data class AttrPathNameImpl(override val name: String) : AttrPathElement.Name - -/** - * Represents an index into a list/set - * @param index The index (starting at `0`) - */ -internal data class AttrPathIndexImpl(override val index: Int) : AttrPathElement.Index - -/** - * Represents an expression that consists of an attribute path - * @param element The [AttrPathElement] for this path - * @param parent The parent [AttributePath] (if any). If [parent] is `null` then this instance represents a top-level - * attribute and [element] must be a name (not an index). Defaults to `null`. - */ -internal data class AttributePathImpl( - override val element: AttrPathElement, - override val parent: AttributePath? = null, -) : AttributePath { - init { - require(element is AttrPathElement.Name || parent != null) { - "Top-level attribute paths must be names (not indices)" - } - } -} - -/** - * Represents an `AND` expression as described in - * [DynamoDB's **logical evaluations** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.LogicalEvaluations). - * This expression will be true if `(operand[0] && operand[1] && ... && operand[n - 1])`. - * @param operands A list of 2 or more [BooleanExpr] conditions which are ANDed together - */ -internal data class AndExprImpl(override val operands: List) : AndExpr { - init { - require(operands.size > 1) { "AND operations require two or more operands" } - } -} - -/** - * Represents a `BETWEEN` expression as described in - * [DynamoDB's **making comparisons** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Comparators). - * This expression will be true if `value >= min && value <= max`. - * @param value The value being compared to the [min] and [max] - * @param min The minimum bound for the comparison - * @param max The maximum bound for the comparison - */ -internal data class BetweenExprImpl( - override val value: Expression, - override val min: Expression, - override val max: Expression, -) : BetweenExpr - -/** - * Represents a function expression that yields a boolean result as described in - * [DynamoDB's **function** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) - * @param func The specific boolean function to use - * @param path The attribute path to pass as the function's first argument - * @param additionalOperands Any additional arguments used by the function - */ -internal data class BooleanFuncExprImpl( - override val func: BooleanFunc, - override val path: AttributePath, - override val additionalOperands: List = listOf(), -) : BooleanFuncExpr - -/** - * Represents a comparison expression as described in - * [DynamoDB's **making comparisons** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Comparators). - * The specific type of comparison is identified by the [comparator] field. - * @param comparator The [Comparator] to use in the expression - * @param left The left value being compared - * @param right The right value being compared - */ -internal data class ComparisonExprImpl( - override val comparator: Comparator, - override val left: Expression, - override val right: Expression, -) : ComparisonExpr - -/** - * Represents an `IN` expression as described in - * [DynamoDB's **making comparisons** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Comparators). - * This expression will be true if `value in set` (or, equivalently, if `set.contains(value)`). - * @param value The value to check for in [set] - * @param set The set of values to compare against [value] - */ -internal data class InExprImpl(override val value: Expression, override val set: Collection) : InExpr - -/** - * Represents an expression that consists of a single literal value - * @param value The low-level DynamoDB representation of the literal value - */ -internal data class LiteralExprImpl(override val value: AttributeValue) : LiteralExpr - -/** - * Represents a `NOT` expression as described in - * [DynamoDB's **logical evaluations** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.LogicalEvaluations). - * This expression will be true if `!operand` (i.e., `operand` evaluates to `false`). - * @param operand The condition to negate - */ -internal data class NotExprImpl(override val operand: BooleanExpr) : NotExpr - -/** - * Represents an `OR` expression as described in - * [DynamoDB's **logical evaluations** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.LogicalEvaluations). - * This expression will be true if `(operand[0] || operand[1] || ... || operand[n - 1])`. - * @param operands A list of 2 or more [BooleanExpr] conditions which are ORed together - */ -internal data class OrExprImpl(override val operands: List) : OrExpr { - init { - require(operands.size > 1) { "OR operations require two or more operands" } - } -} - -/** - * Represents a function expression that yields a non-boolean result as described in - * [DynamoDB's **function** documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) - * @param func The specific boolean function to use - * @param path The attribute path to pass as the function's first argument - * @param additionalOperands Any additional arguments used by the function - */ -internal data class ScalarFuncExprImpl( - override val func: ScalarFunc, - override val path: AttributePath, - override val additionalOperands: List = listOf(), -) : ScalarFuncExpr diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/InExprImpl.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/InExprImpl.kt new file mode 100644 index 00000000000..e48dbe1a06c --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/InExprImpl.kt @@ -0,0 +1,10 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.Expression +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.InExpr + +internal data class InExprImpl(override val value: Expression, override val set: Collection) : InExpr diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/LiteralExprImpl.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/LiteralExprImpl.kt new file mode 100644 index 00000000000..97236f665a9 --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/LiteralExprImpl.kt @@ -0,0 +1,10 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.LiteralExpr +import aws.sdk.kotlin.services.dynamodb.model.AttributeValue + +internal data class LiteralExprImpl(override val value: AttributeValue) : LiteralExpr diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/NotExprImpl.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/NotExprImpl.kt new file mode 100644 index 00000000000..815c4c03e5a --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/NotExprImpl.kt @@ -0,0 +1,10 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.BooleanExpr +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.NotExpr + +internal data class NotExprImpl(override val operand: BooleanExpr) : NotExpr diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/OrExprImpl.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/OrExprImpl.kt new file mode 100644 index 00000000000..e2c7d474648 --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/OrExprImpl.kt @@ -0,0 +1,14 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.BooleanExpr +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.OrExpr + +internal data class OrExprImpl(override val operands: List) : OrExpr { + init { + require(operands.size > 1) { "OR operations require two or more operands" } + } +} diff --git a/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ScalarFuncExprImpl.kt b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ScalarFuncExprImpl.kt new file mode 100644 index 00000000000..189d86806cd --- /dev/null +++ b/hll/dynamodb-mapper/dynamodb-mapper/common/src/aws/sdk/kotlin/hll/dynamodbmapper/expressions/internal/ScalarFuncExprImpl.kt @@ -0,0 +1,13 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.hll.dynamodbmapper.expressions.internal + +import aws.sdk.kotlin.hll.dynamodbmapper.expressions.* + +internal data class ScalarFuncExprImpl( + override val func: ScalarFunc, + override val path: AttributePath, + override val additionalOperands: List = listOf(), +) : ScalarFuncExpr diff --git a/settings.gradle.kts b/settings.gradle.kts index a48c72b988c..49237132653 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -75,7 +75,7 @@ if ("dynamodb".isBootstrappedService) { include(":hll:dynamodb-mapper:dynamodb-mapper-annotations") include(":hll:dynamodb-mapper:tests:dynamodb-mapper-annotation-processor-test") include(":hll:dynamodb-mapper:dynamodb-mapper-schema-generator-plugin") - // include(":hll:dynamodb-mapper:tests:dynamodb-mapper-schema-generator-plugin-test") + include(":hll:dynamodb-mapper:tests:dynamodb-mapper-schema-generator-plugin-test") } else { logger.warn(":services:dynamodb is not bootstrapped, skipping :hll:dynamodb-mapper and subprojects") }