From 6890e7d0914c755a3b1584661e62d3cb2fffb504 Mon Sep 17 00:00:00 2001 From: Jan Sigrist Date: Wed, 14 Aug 2024 14:59:04 +0200 Subject: [PATCH 01/15] DOPE-242: feature use index Added interface IBucket. This Interface is used everywhere you can use a normal Bucket (UnaliasedBucket/AliasedBucket) and the UseIndex and UseKeys. --- .../main/kotlin/ch/ergon/dope/QueryBuilder.kt | 6 +- .../dope/resolvable/clause/IDeleteClause.kt | 14 +- .../dope/resolvable/clause/ISelectClause.kt | 37 +-- .../dope/resolvable/clause/IUpdateClause.kt | 13 +- .../resolvable/clause/model/DeleteClause.kt | 4 +- .../resolvable/clause/model/JoinClause.kt | 27 +- .../resolvable/clause/model/UpdateClause.kt | 4 +- .../resolvable/clause/model/UseKeysClause.kt | 96 ------- .../resolvable/clause/model/WhereClause.kt | 8 +- .../fromable/AliasedSelectClause.kt | 10 +- .../ergon/dope/resolvable/fromable/Bucket.kt | 2 +- .../dope/resolvable/fromable/Fromable.kt | 2 + .../dope/resolvable/fromable/UseIndex.kt | 71 +++++ .../ergon/dope/resolvable/fromable/UseKeys.kt | 50 ++++ .../ch/ergon/dope/buildTest/JoinClauseTest.kt | 6 +- .../ch/ergon/dope/buildTest/SubQueryTest.kt | 5 +- .../ch/ergon/dope/buildTest/UpdateTest.kt | 20 +- .../{UseClauseTest.kt => UseKeysTest.kt} | 187 ++++++------- .../resolvable/clause/UseKeysClauseTest.kt | 197 -------------- .../ergon/dope/resolvable/fromable/UseTest.kt | 247 ++++++++++++++++++ .../dope/extension/clause/DeleteClause.kt | 7 +- .../dope/extension/clause/SelectClause.kt | 6 +- .../dope/extension/clause/UpdateClause.kt | 32 +-- .../ch/ergon/dope/extension/fromable/Use.kt | 11 + .../extensions/clause/DeleteClauseTest.kt | 25 -- .../extensions/clause/SelectClauseTest.kt | 24 -- .../extensions/clause/UpdateClauseTest.kt | 24 -- .../ergon/dope/extensions/fromable/UseTest.kt | 45 ++++ 28 files changed, 574 insertions(+), 606 deletions(-) delete mode 100644 core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UseKeysClause.kt create mode 100644 core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt create mode 100644 core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt rename core/src/test/kotlin/ch/ergon/dope/buildTest/{UseClauseTest.kt => UseKeysTest.kt} (62%) delete mode 100644 core/src/test/kotlin/ch/ergon/dope/resolvable/clause/UseKeysClauseTest.kt create mode 100644 core/src/test/kotlin/ch/ergon/dope/resolvable/fromable/UseTest.kt create mode 100644 crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/fromable/Use.kt create mode 100644 crystal-map-connector/src/test/kotlin/ch/ergon/dope/extensions/fromable/UseTest.kt diff --git a/core/src/main/kotlin/ch/ergon/dope/QueryBuilder.kt b/core/src/main/kotlin/ch/ergon/dope/QueryBuilder.kt index 6a50c5b1..ac7d8260 100644 --- a/core/src/main/kotlin/ch/ergon/dope/QueryBuilder.kt +++ b/core/src/main/kotlin/ch/ergon/dope/QueryBuilder.kt @@ -8,8 +8,8 @@ import ch.ergon.dope.resolvable.clause.model.UpdateClause import ch.ergon.dope.resolvable.expression.AsteriskExpression import ch.ergon.dope.resolvable.expression.Expression import ch.ergon.dope.resolvable.expression.SingleExpression -import ch.ergon.dope.resolvable.fromable.Bucket import ch.ergon.dope.resolvable.fromable.Fromable +import ch.ergon.dope.resolvable.fromable.IBucket class QueryBuilder { fun select(expression: Expression, vararg expressions: Expression) = SelectClause(expression, *expressions) @@ -22,7 +22,7 @@ class QueryBuilder { fun selectFrom(fromable: Fromable) = SelectClause(AsteriskExpression()).from(fromable) - fun deleteFrom(bucket: Bucket) = DeleteClause(bucket) + fun deleteFrom(bucket: IBucket) = DeleteClause(bucket) - fun update(bucket: Bucket) = UpdateClause(bucket) + fun update(bucket: IBucket) = UpdateClause(bucket) } diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/IDeleteClause.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/IDeleteClause.kt index fe216d19..fa1d83e5 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/IDeleteClause.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/IDeleteClause.kt @@ -3,15 +3,12 @@ package ch.ergon.dope.resolvable.clause import ch.ergon.dope.resolvable.clause.model.DeleteLimitClause import ch.ergon.dope.resolvable.clause.model.DeleteOffsetClause import ch.ergon.dope.resolvable.clause.model.DeleteReturningClause -import ch.ergon.dope.resolvable.clause.model.DeleteUseKeys.Companion.DeleteUseKeysClause import ch.ergon.dope.resolvable.clause.model.DeleteWhereClause import ch.ergon.dope.resolvable.expression.TypeExpression import ch.ergon.dope.resolvable.expression.unaliased.type.Field import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType -import ch.ergon.dope.validtype.ArrayType import ch.ergon.dope.validtype.BooleanType import ch.ergon.dope.validtype.NumberType -import ch.ergon.dope.validtype.StringType import ch.ergon.dope.validtype.ValidType interface IDeleteReturningClause : Clause @@ -30,15 +27,6 @@ interface IDeleteWhereClause : IDeleteLimitClause { fun limit(number: Number) = limit(number.toDopeType()) } -interface IDeleteUseKeysClause : IDeleteWhereClause { +interface IDeleteClause : IDeleteWhereClause { fun where(booleanExpression: TypeExpression) = DeleteWhereClause(booleanExpression, this) } - -interface IDeleteClause : IDeleteUseKeysClause { - fun useKeys(key: TypeExpression) = DeleteUseKeysClause(key, this) - - // JvmName annotation in interfaces is currently not supported. https://youtrack.jetbrains.com/issue/KT-20068 - @Suppress("INAPPLICABLE_JVM_NAME") - @JvmName("useKeysArray") - fun useKeys(key: TypeExpression>) = DeleteUseKeysClause(key, this) -} diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/ISelectClause.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/ISelectClause.kt index e3c2f98d..93bbec4a 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/ISelectClause.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/ISelectClause.kt @@ -11,7 +11,6 @@ import ch.ergon.dope.resolvable.clause.model.SelectLimitClause import ch.ergon.dope.resolvable.clause.model.SelectOffsetClause import ch.ergon.dope.resolvable.clause.model.SelectOrderByClause import ch.ergon.dope.resolvable.clause.model.SelectOrderByTypeClause -import ch.ergon.dope.resolvable.clause.model.SelectUseKeys.Companion.SelectUseKeysClause import ch.ergon.dope.resolvable.clause.model.SelectWhereClause import ch.ergon.dope.resolvable.clause.model.StandardJoinClause import ch.ergon.dope.resolvable.clause.model.UnnestClause @@ -22,6 +21,7 @@ import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType import ch.ergon.dope.resolvable.fromable.AliasedSelectClause import ch.ergon.dope.resolvable.fromable.Bucket import ch.ergon.dope.resolvable.fromable.Fromable +import ch.ergon.dope.resolvable.fromable.IBucket import ch.ergon.dope.validtype.ArrayType import ch.ergon.dope.validtype.BooleanType import ch.ergon.dope.validtype.NumberType @@ -49,33 +49,26 @@ interface ISelectWhereClause : ISelectGroupByClause { fun groupBy(field: Field, vararg fields: Field) = GroupByClause(field, *fields, parentClause = this) } -interface ISelectUseKeysClause : ISelectWhereClause { +interface ISelectFromClause : ISelectWhereClause { fun where(whereExpression: TypeExpression) = SelectWhereClause(whereExpression, this) } -interface ISelectFromClause : ISelectUseKeysClause { - fun useKeys(key: TypeExpression) = SelectUseKeysClause(key, this) - - // JvmName annotation in interfaces is currently not supported. https://youtrack.jetbrains.com/issue/KT-20068 - @Suppress("INAPPLICABLE_JVM_NAME") - @JvmName("useKeysArray") - fun useKeys(keys: TypeExpression>) = SelectUseKeysClause(keys, this) -} - interface ISelectJoinClause : ISelectFromClause { - fun join(bucket: Bucket, onCondition: TypeExpression) = StandardJoinClause(bucket, onCondition, this) - fun join(bucket: Bucket, onKeys: Field) = StandardJoinClause(bucket, onKeys, this) - fun join(bucket: Bucket, onKey: Field, forBucket: Bucket) = StandardJoinClause(bucket, onKey, forBucket, this) + fun join(bucket: IBucket, onCondition: TypeExpression) = StandardJoinClause(bucket, onCondition, this) + fun join(bucket: IBucket, onKeys: Field) = StandardJoinClause(bucket, onKeys, this) + fun join(bucket: IBucket, onKey: Field, forBucket: Bucket) = StandardJoinClause(bucket, onKey, forBucket, this) + + fun innerJoin(bucket: IBucket, onCondition: TypeExpression) = InnerJoinClause(bucket, onCondition, this) + fun innerJoin(bucket: IBucket, onKeys: Field) = InnerJoinClause(bucket, onKeys, this) + fun innerJoin(bucket: IBucket, onKey: Field, forBucket: Bucket) = InnerJoinClause(bucket, onKey, forBucket, this) - fun innerJoin(bucket: Bucket, onCondition: TypeExpression) = InnerJoinClause(bucket, onCondition, this) - fun innerJoin(bucket: Bucket, onKeys: Field) = InnerJoinClause(bucket, onKeys, this) - fun innerJoin(bucket: Bucket, onKey: Field, forBucket: Bucket) = InnerJoinClause(bucket, onKey, forBucket, this) + fun leftJoin(bucket: IBucket, onCondition: TypeExpression) = LeftJoinClause(bucket, onCondition, this) + fun leftJoin(bucket: IBucket, onKeys: Field) = LeftJoinClause(bucket, onKeys, this) + fun leftJoin(bucket: IBucket, onKey: Field, forBucket: Bucket) = LeftJoinClause(bucket, onKey, forBucket, this) - fun leftJoin(bucket: Bucket, onCondition: TypeExpression) = LeftJoinClause(bucket, onCondition, this) - fun leftJoin(bucket: Bucket, onKeys: Field) = LeftJoinClause(bucket, onKeys, this) - fun leftJoin(bucket: Bucket, onKey: Field, forBucket: Bucket) = LeftJoinClause(bucket, onKey, forBucket, this) + fun rightJoin(bucket: IBucket, onCondition: TypeExpression) = RightJoinClause(bucket, onCondition, this) - fun rightJoin(bucket: Bucket, onCondition: TypeExpression) = RightJoinClause(bucket, onCondition, this) + fun alias(alias: String) = AliasedSelectClause(alias, this) } interface ISelectUnnestClause : ISelectJoinClause { @@ -85,6 +78,4 @@ interface ISelectUnnestClause : ISelectJoinClause { interface ISelectClause : ISelectFromClause { fun from(fromable: Fromable) = FromClause(fromable, this) - - fun alias(alias: String) = AliasedSelectClause(alias, this) } diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/IUpdateClause.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/IUpdateClause.kt index f8d1f4cf..dadaffc3 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/IUpdateClause.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/IUpdateClause.kt @@ -4,13 +4,11 @@ import ch.ergon.dope.resolvable.clause.model.SetClause import ch.ergon.dope.resolvable.clause.model.UnsetClause import ch.ergon.dope.resolvable.clause.model.UpdateLimitClause import ch.ergon.dope.resolvable.clause.model.UpdateReturningClause -import ch.ergon.dope.resolvable.clause.model.UpdateUseKeys.Companion.UpdateUseKeysClause import ch.ergon.dope.resolvable.clause.model.UpdateWhereClause import ch.ergon.dope.resolvable.clause.model.to import ch.ergon.dope.resolvable.expression.TypeExpression import ch.ergon.dope.resolvable.expression.unaliased.type.Field import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType -import ch.ergon.dope.validtype.ArrayType import ch.ergon.dope.validtype.BooleanType import ch.ergon.dope.validtype.NumberType import ch.ergon.dope.validtype.StringType @@ -36,18 +34,9 @@ interface IUpdateSetClause : IUpdateUnsetClause { fun unset(field: Field) = UnsetClause(field, parentClause = this) } -interface IUpdateUseKeysClause : IUpdateSetClause { +interface IUpdateClause : IUpdateSetClause { fun set(field: Field, value: TypeExpression) = SetClause(field.to(value), parentClause = this) fun set(field: Field, value: Number) = SetClause(field.to(value.toDopeType()), parentClause = this) fun set(field: Field, value: String) = SetClause(field.to(value.toDopeType()), parentClause = this) fun set(field: Field, value: Boolean) = SetClause(field.to(value.toDopeType()), parentClause = this) } - -interface IUpdateClause : IUpdateUseKeysClause { - fun useKeys(key: TypeExpression) = UpdateUseKeysClause(key, this) - - // JvmName annotation in interfaces is currently not supported. https://youtrack.jetbrains.com/issue/KT-20068 - @Suppress("INAPPLICABLE_JVM_NAME") - @JvmName("useKeysArray") - fun useKeys(key: TypeExpression>) = UpdateUseKeysClause(key, this) -} diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/DeleteClause.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/DeleteClause.kt index 982fb955..d538d6a5 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/DeleteClause.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/DeleteClause.kt @@ -2,9 +2,9 @@ package ch.ergon.dope.resolvable.clause.model import ch.ergon.dope.DopeQuery import ch.ergon.dope.resolvable.clause.IDeleteClause -import ch.ergon.dope.resolvable.fromable.Bucket +import ch.ergon.dope.resolvable.fromable.IBucket -class DeleteClause(private val bucket: Bucket) : IDeleteClause { +class DeleteClause(private val bucket: IBucket) : IDeleteClause { override fun toDopeQuery(): DopeQuery { val bucketDopeQuery = bucket.toDopeQuery() return DopeQuery( diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/JoinClause.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/JoinClause.kt index 2b8425bf..e61364be 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/JoinClause.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/JoinClause.kt @@ -10,6 +10,7 @@ import ch.ergon.dope.resolvable.clause.model.JoinType.RIGHT_JOIN import ch.ergon.dope.resolvable.expression.TypeExpression import ch.ergon.dope.resolvable.expression.unaliased.type.Field import ch.ergon.dope.resolvable.fromable.Bucket +import ch.ergon.dope.resolvable.fromable.IBucket import ch.ergon.dope.validtype.BooleanType import ch.ergon.dope.validtype.ValidType @@ -23,7 +24,7 @@ private enum class JoinType(val type: String) { sealed class SelectJoinClause : ISelectJoinClause { private val dopeQuery: DopeQuery - constructor(joinType: JoinType, bucket: Bucket, onCondition: TypeExpression, parentClause: ISelectFromClause) { + constructor(joinType: JoinType, bucket: IBucket, onCondition: TypeExpression, parentClause: ISelectFromClause) { val parentDopeQuery = parentClause.toDopeQuery() val bucketDopeQuery = bucket.toDopeQuery() val onConditionDopeQuery = onCondition.toDopeQuery() @@ -34,7 +35,7 @@ sealed class SelectJoinClause : ISelectJoinClause { ) } - constructor(joinType: JoinType, bucket: Bucket, onKeys: Field, parentClause: ISelectFromClause) { + constructor(joinType: JoinType, bucket: IBucket, onKeys: Field, parentClause: ISelectFromClause) { val parentDopeQuery = parentClause.toDopeQuery() val bucketDopeQuery = bucket.toDopeQuery() val keyDopeQuery = onKeys.toDopeQuery() @@ -45,7 +46,7 @@ sealed class SelectJoinClause : ISelectJoinClause { ) } - constructor(joinType: JoinType, bucket: Bucket, onKey: Field, forBucket: Bucket, parentClause: ISelectFromClause) { + constructor(joinType: JoinType, bucket: IBucket, onKey: Field, forBucket: Bucket, parentClause: ISelectFromClause) { val parentDopeQuery = parentClause.toDopeQuery() val bucketDopeQuery = bucket.toDopeQuery() val keyDopeQuery = onKey.toDopeQuery() @@ -61,37 +62,37 @@ sealed class SelectJoinClause : ISelectJoinClause { } class StandardJoinClause : SelectJoinClause { - constructor(bucket: Bucket, onCondition: TypeExpression, parentClause: ISelectFromClause) : + constructor(bucket: IBucket, onCondition: TypeExpression, parentClause: ISelectFromClause) : super(JOIN, bucket, onCondition, parentClause) - constructor(bucket: Bucket, onKeys: Field, parentClause: ISelectFromClause) : + constructor(bucket: IBucket, onKeys: Field, parentClause: ISelectFromClause) : super(JOIN, bucket, onKeys, parentClause) - constructor(bucket: Bucket, onKey: Field, forBucket: Bucket, parentClause: ISelectFromClause) : + constructor(bucket: IBucket, onKey: Field, forBucket: Bucket, parentClause: ISelectFromClause) : super(JOIN, bucket, onKey, forBucket, parentClause) } class LeftJoinClause : SelectJoinClause { - constructor(bucket: Bucket, onCondition: TypeExpression, parentClause: ISelectFromClause) : + constructor(bucket: IBucket, onCondition: TypeExpression, parentClause: ISelectFromClause) : super(LEFT_JOIN, bucket, onCondition, parentClause) - constructor(bucket: Bucket, onKeys: Field, parentClause: ISelectFromClause) : + constructor(bucket: IBucket, onKeys: Field, parentClause: ISelectFromClause) : super(LEFT_JOIN, bucket, onKeys, parentClause) - constructor(bucket: Bucket, onKey: Field, forBucket: Bucket, parentClause: ISelectFromClause) : + constructor(bucket: IBucket, onKey: Field, forBucket: Bucket, parentClause: ISelectFromClause) : super(LEFT_JOIN, bucket, onKey, forBucket, parentClause) } class InnerJoinClause : SelectJoinClause { - constructor(bucket: Bucket, onCondition: TypeExpression, parentClause: ISelectFromClause) : + constructor(bucket: IBucket, onCondition: TypeExpression, parentClause: ISelectFromClause) : super(INNER_JOIN, bucket, onCondition, parentClause) - constructor(bucket: Bucket, onKeys: Field, parentClause: ISelectFromClause) : + constructor(bucket: IBucket, onKeys: Field, parentClause: ISelectFromClause) : super(INNER_JOIN, bucket, onKeys, parentClause) - constructor(bucket: Bucket, onKey: Field, forBucket: Bucket, parentClause: ISelectFromClause) : + constructor(bucket: IBucket, onKey: Field, forBucket: Bucket, parentClause: ISelectFromClause) : super(INNER_JOIN, bucket, onKey, forBucket, parentClause) } -class RightJoinClause(bucket: Bucket, onCondition: TypeExpression, parentClause: ISelectFromClause) : +class RightJoinClause(bucket: IBucket, onCondition: TypeExpression, parentClause: ISelectFromClause) : SelectJoinClause(RIGHT_JOIN, bucket, onCondition, parentClause) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UpdateClause.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UpdateClause.kt index a4e178c1..89f4c20d 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UpdateClause.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UpdateClause.kt @@ -2,9 +2,9 @@ package ch.ergon.dope.resolvable.clause.model import ch.ergon.dope.DopeQuery import ch.ergon.dope.resolvable.clause.IUpdateClause -import ch.ergon.dope.resolvable.fromable.Bucket +import ch.ergon.dope.resolvable.fromable.IBucket -class UpdateClause(private val bucket: Bucket) : IUpdateClause { +class UpdateClause(private val bucket: IBucket) : IUpdateClause { override fun toDopeQuery(): DopeQuery { val bucketDopeQuery = bucket.toDopeQuery() return DopeQuery( diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UseKeysClause.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UseKeysClause.kt deleted file mode 100644 index cdd84b5f..00000000 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UseKeysClause.kt +++ /dev/null @@ -1,96 +0,0 @@ -package ch.ergon.dope.resolvable.clause.model - -import ch.ergon.dope.DopeQuery -import ch.ergon.dope.resolvable.clause.IDeleteClause -import ch.ergon.dope.resolvable.clause.IDeleteUseKeysClause -import ch.ergon.dope.resolvable.clause.ISelectFromClause -import ch.ergon.dope.resolvable.clause.ISelectUseKeysClause -import ch.ergon.dope.resolvable.clause.IUpdateClause -import ch.ergon.dope.resolvable.clause.IUpdateUseKeysClause -import ch.ergon.dope.resolvable.expression.TypeExpression -import ch.ergon.dope.resolvable.formatToQueryStringWithSymbol -import ch.ergon.dope.validtype.ArrayType -import ch.ergon.dope.validtype.StringType -import ch.ergon.dope.validtype.ValidType - -private const val USE_KEYS = "USE KEYS" - -class SelectUseKeys private constructor( - private val useKeys: TypeExpression, - private val parentClause: ISelectFromClause, -) : ISelectUseKeysClause { - companion object { - @JvmName("selectSingleUseKeysClauseConstructor") - fun SelectUseKeysClause(key: TypeExpression, parentClause: ISelectFromClause) = - SelectUseKeys(key, parentClause) - - @JvmName("selectMultipleUseKeysClauseConstructor") - fun SelectUseKeysClause(keys: TypeExpression>, parentClause: ISelectFromClause) = - SelectUseKeys(keys, parentClause) - } - - override fun toDopeQuery(): DopeQuery { - val parentDopeQuery = parentClause.toDopeQuery() - val keysDopeQuery = useKeys.toDopeQuery() - return DopeQuery( - queryString = formatToQueryStringWithSymbol(parentDopeQuery.queryString, USE_KEYS, keysDopeQuery.queryString), - parameters = parentDopeQuery.parameters + keysDopeQuery.parameters, - ) - } -} - -class DeleteUseKeys private constructor( - private val useKeys: TypeExpression, - private val parentClause: IDeleteClause, -) : IDeleteUseKeysClause { - companion object { - @JvmName("deleteSingleUseKeysClauseConstructor") - fun DeleteUseKeysClause(key: TypeExpression, parentClause: IDeleteClause) = - DeleteUseKeys(key, parentClause) - - @JvmName("deleteMultipleUseKeysClauseConstructor") - fun DeleteUseKeysClause(keys: TypeExpression>, parentClause: IDeleteClause) = - DeleteUseKeys(keys, parentClause) - } - - override fun toDopeQuery(): DopeQuery { - val parentDopeQuery = parentClause.toDopeQuery() - val keysDopeQuery = useKeys.toDopeQuery() - return DopeQuery( - queryString = formatToQueryStringWithSymbol(parentDopeQuery.queryString, USE_KEYS, keysDopeQuery.queryString), - parameters = parentDopeQuery.parameters + keysDopeQuery.parameters, - ) - } -} - -class UpdateUseKeys : IUpdateUseKeysClause { - private lateinit var useKeys: TypeExpression - private lateinit var parentClause: IUpdateClause - - companion object { - @JvmName("updateSingleUseKeysClauseConstructor") - fun UpdateUseKeysClause(key: TypeExpression, parentClause: IUpdateClause): UpdateUseKeys { - val instance = UpdateUseKeys() - instance.useKeys = key - instance.parentClause = parentClause - return instance - } - - @JvmName("updateMultipleUseKeysClauseConstructor") - fun UpdateUseKeysClause(keys: TypeExpression>, parentClause: IUpdateClause): UpdateUseKeys { - val instance = UpdateUseKeys() - instance.useKeys = keys - instance.parentClause = parentClause - return instance - } - } - - override fun toDopeQuery(): DopeQuery { - val parentDopeQuery = parentClause.toDopeQuery() - val keysDopeQuery = useKeys.toDopeQuery() - return DopeQuery( - queryString = formatToQueryStringWithSymbol(parentDopeQuery.queryString, USE_KEYS, keysDopeQuery.queryString), - parameters = parentDopeQuery.parameters + keysDopeQuery.parameters, - ) - } -} diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/WhereClause.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/WhereClause.kt index 5a841c52..c4eb30ef 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/WhereClause.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/WhereClause.kt @@ -2,9 +2,9 @@ package ch.ergon.dope.resolvable.clause.model import ch.ergon.dope.DopeQuery import ch.ergon.dope.resolvable.clause.Clause -import ch.ergon.dope.resolvable.clause.IDeleteUseKeysClause +import ch.ergon.dope.resolvable.clause.IDeleteClause import ch.ergon.dope.resolvable.clause.IDeleteWhereClause -import ch.ergon.dope.resolvable.clause.ISelectUseKeysClause +import ch.ergon.dope.resolvable.clause.ISelectFromClause import ch.ergon.dope.resolvable.clause.ISelectWhereClause import ch.ergon.dope.resolvable.clause.IUpdateUnsetClause import ch.ergon.dope.resolvable.clause.IUpdateWhereClause @@ -26,10 +26,10 @@ sealed class WhereClause( } } -class SelectWhereClause(whereExpression: TypeExpression, parentClause: ISelectUseKeysClause) : +class SelectWhereClause(whereExpression: TypeExpression, parentClause: ISelectFromClause) : ISelectWhereClause, WhereClause(whereExpression, parentClause) -class DeleteWhereClause(whereExpression: TypeExpression, parentClause: IDeleteUseKeysClause) : +class DeleteWhereClause(whereExpression: TypeExpression, parentClause: IDeleteClause) : IDeleteWhereClause, WhereClause(whereExpression, parentClause) class UpdateWhereClause(whereExpression: TypeExpression, parentClause: IUpdateUnsetClause) : diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/AliasedSelectClause.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/AliasedSelectClause.kt index 45c3075e..67534b8b 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/AliasedSelectClause.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/AliasedSelectClause.kt @@ -1,14 +1,14 @@ package ch.ergon.dope.resolvable.fromable import ch.ergon.dope.DopeQuery -import ch.ergon.dope.resolvable.clause.ISelectClause +import ch.ergon.dope.resolvable.clause.ISelectJoinClause -class AliasedSelectClause(private val alias: String, private val selectClause: ISelectClause) : Fromable { +class AliasedSelectClause(private val alias: String, private val parentClause: ISelectJoinClause) : Fromable { override fun toDopeQuery(): DopeQuery { - val selectClauseDopeQuery = selectClause.toDopeQuery() + val parentClauseDopeQuery = parentClause.toDopeQuery() return DopeQuery( - queryString = "(${selectClauseDopeQuery.queryString}) AS `$alias`", - parameters = selectClauseDopeQuery.parameters, + queryString = "(${parentClauseDopeQuery.queryString}) AS `$alias`", + parameters = parentClauseDopeQuery.parameters, ) } } diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Bucket.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Bucket.kt index ba2ebdfb..754ea504 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Bucket.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Bucket.kt @@ -3,7 +3,7 @@ package ch.ergon.dope.resolvable.fromable import ch.ergon.dope.DopeQuery import ch.ergon.dope.resolvable.expression.AsteriskExpression -sealed class Bucket(open val name: String) : Fromable { +sealed class Bucket(open val name: String) : IBucket { override fun toDopeQuery() = DopeQuery("`$name`", emptyMap()) } diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Fromable.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Fromable.kt index caf011a8..057cf8c7 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Fromable.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Fromable.kt @@ -3,3 +3,5 @@ package ch.ergon.dope.resolvable.fromable import ch.ergon.dope.resolvable.Resolvable interface Fromable : Resolvable + +interface IBucket : Fromable diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt new file mode 100644 index 00000000..733838e4 --- /dev/null +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt @@ -0,0 +1,71 @@ +package ch.ergon.dope.resolvable.fromable + +import ch.ergon.dope.DopeQuery +import ch.ergon.dope.resolvable.Resolvable +import ch.ergon.dope.resolvable.expression.TypeExpression +import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType +import ch.ergon.dope.resolvable.formatToQueryStringWithSymbol +import ch.ergon.dope.validtype.StringType + +private const val USE_INDEX = "USE INDEX" + +enum class IndexType(val type: String) { + USING_GSI("USING GSI"), + USING_FTS("USING FTS"), +} + +class IndexReference : Resolvable { + private val indexName: TypeExpression? + private val indexType: IndexType? + + constructor(indexName: TypeExpression, indexType: IndexType) { + this.indexName = indexName + this.indexType = indexType + } + + constructor(indexName: TypeExpression) { + this.indexName = indexName + this.indexType = null + } + + constructor(indexName: String) { + this.indexName = indexName.toDopeType() + this.indexType = null + } + + constructor(indexType: IndexType) { + this.indexName = null + this.indexType = indexType + } + + override fun toDopeQuery(): DopeQuery { + val fromableDopeQuery = indexName?.toDopeQuery() + val queryString = buildString { + if (fromableDopeQuery != null) { + append(fromableDopeQuery.queryString) + } + if (indexType != null) { + if (isNotEmpty()) append(" ") + append(indexType.type) + } + } + return DopeQuery(queryString, fromableDopeQuery?.parameters.orEmpty()) + } +} + +class UseIndex( + private vararg val indexReference: IndexReference, + private val bucket: Bucket, +) : IBucket { + override fun toDopeQuery(): DopeQuery { + val bucketDopeQuery = bucket.toDopeQuery() + val indexReferenceDopeQueries = indexReference.map { it.toDopeQuery() } + val indexReferences = indexReferenceDopeQueries.joinToString(", ", prefix = "(", postfix = ")") { it.queryString } + return DopeQuery( + queryString = formatToQueryStringWithSymbol(bucketDopeQuery.queryString, USE_INDEX, indexReferences), + parameters = bucketDopeQuery.parameters + indexReferenceDopeQueries.fold(emptyMap()) { indexReferenceParameters, field -> + indexReferenceParameters + field.parameters + }, + ) + } +} diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt new file mode 100644 index 00000000..b136dc9c --- /dev/null +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt @@ -0,0 +1,50 @@ +package ch.ergon.dope.resolvable.fromable + +import ch.ergon.dope.DopeQuery +import ch.ergon.dope.resolvable.expression.TypeExpression +import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType +import ch.ergon.dope.resolvable.formatToQueryStringWithSymbol +import ch.ergon.dope.resolvable.fromable.UseKeysClass.Companion.UseKeys +import ch.ergon.dope.validtype.ArrayType +import ch.ergon.dope.validtype.StringType +import ch.ergon.dope.validtype.ValidType + +private const val USE_KEYS = "USE KEYS" + +class UseKeysClass private constructor( + private val useKeys: TypeExpression, + private val bucket: Bucket, +) : IBucket { + companion object { + @JvmName("selectSingleUseKeysClauseConstructor") + fun UseKeys(key: TypeExpression, bucket: Bucket) = + UseKeysClass(key, bucket) + + @JvmName("selectMultipleUseKeysClauseConstructor") + fun UseKeys(keys: TypeExpression>, bucket: Bucket) = + UseKeysClass(keys, bucket) + } + + override fun toDopeQuery(): DopeQuery { + val bucketDopeQuery = bucket.toDopeQuery() + val keysDopeQuery = useKeys.toDopeQuery() + return DopeQuery( + queryString = formatToQueryStringWithSymbol(bucketDopeQuery.queryString, USE_KEYS, keysDopeQuery.queryString), + parameters = bucketDopeQuery.parameters + keysDopeQuery.parameters, + ) + } +} + +fun Bucket.useKeys(key: TypeExpression) = UseKeys(key, this) + +fun Bucket.useKeys(key: String) = useKeys(key.toDopeType()) + +@JvmName("useKeysArray") +fun Bucket.useKeys(keys: TypeExpression>) = UseKeys(keys, this) + +fun Bucket.useKeys(keys: Collection>) = useKeys(keys.toDopeType()) + +fun Bucket.useKeys(firstKey: String, secondKey: String, vararg additionalKeys: String) = + useKeys(listOf(firstKey.toDopeType(), secondKey.toDopeType(), *additionalKeys.map { it.toDopeType() }.toTypedArray()).toDopeType()) + +fun Bucket.useIndex(vararg indexReference: IndexReference) = UseIndex(*indexReference, bucket = this) diff --git a/core/src/test/kotlin/ch/ergon/dope/buildTest/JoinClauseTest.kt b/core/src/test/kotlin/ch/ergon/dope/buildTest/JoinClauseTest.kt index fae23ba2..bc951867 100644 --- a/core/src/test/kotlin/ch/ergon/dope/buildTest/JoinClauseTest.kt +++ b/core/src/test/kotlin/ch/ergon/dope/buildTest/JoinClauseTest.kt @@ -11,6 +11,7 @@ import ch.ergon.dope.resolvable.expression.unaliased.type.logical.and import ch.ergon.dope.resolvable.expression.unaliased.type.meta.meta import ch.ergon.dope.resolvable.expression.unaliased.type.relational.isEqualTo import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType +import ch.ergon.dope.resolvable.fromable.useIndex import org.junit.jupiter.api.Assertions.assertEquals import kotlin.test.BeforeTest import kotlin.test.Test @@ -53,12 +54,13 @@ class JoinClauseTest { @Test fun `Should support left join`() { val expected = - "SELECT * FROM `route` LEFT JOIN `airline` ON `route`.`airlineid` = META(`airline`).`id` WHERE `route`.`sourceairport` = \"SFO\"" + "SELECT * FROM `route` USE INDEX () LEFT JOIN `airline` ON `route`.`airlineid` = META(`airline`).`id` " + + "WHERE `route`.`sourceairport` = \"SFO\"" val actual = create .selectAsterisk() .from( - route, + route.useIndex(), ).leftJoin( airline, onCondition = someStringField("airlineid", route).isEqualTo( diff --git a/core/src/test/kotlin/ch/ergon/dope/buildTest/SubQueryTest.kt b/core/src/test/kotlin/ch/ergon/dope/buildTest/SubQueryTest.kt index 294bf83d..9966a4ce 100644 --- a/core/src/test/kotlin/ch/ergon/dope/buildTest/SubQueryTest.kt +++ b/core/src/test/kotlin/ch/ergon/dope/buildTest/SubQueryTest.kt @@ -1,6 +1,7 @@ package ch.ergon.dope.buildTest import ch.ergon.dope.QueryBuilder +import ch.ergon.dope.helper.someBucket import ch.ergon.dope.helper.someStringField import junit.framework.TestCase.assertEquals import kotlin.test.BeforeTest @@ -16,11 +17,11 @@ class SubQueryTest { @Test fun `should support sub select in from`() { - val expected = "SELECT `stringField` FROM (SELECT *) AS `asdf`" + val expected = "SELECT `stringField` FROM (SELECT * FROM `someBucket`) AS `asdf`" val actual: String = create .select(someStringField()) - .from(create.selectAsterisk().alias("asdf")) + .from(create.selectAsterisk().from(someBucket()).alias("asdf")) .build().queryString assertEquals(expected, actual) diff --git a/core/src/test/kotlin/ch/ergon/dope/buildTest/UpdateTest.kt b/core/src/test/kotlin/ch/ergon/dope/buildTest/UpdateTest.kt index d5494669..333cfe60 100644 --- a/core/src/test/kotlin/ch/ergon/dope/buildTest/UpdateTest.kt +++ b/core/src/test/kotlin/ch/ergon/dope/buildTest/UpdateTest.kt @@ -5,12 +5,12 @@ import ch.ergon.dope.helper.ParameterDependentTest import ch.ergon.dope.helper.someBooleanField import ch.ergon.dope.helper.someBucket import ch.ergon.dope.helper.someNumberField -import ch.ergon.dope.helper.someString import ch.ergon.dope.helper.someStringField import ch.ergon.dope.resolvable.expression.unaliased.type.arithmetic.add import ch.ergon.dope.resolvable.expression.unaliased.type.meta.meta import ch.ergon.dope.resolvable.expression.unaliased.type.relational.isEqualTo import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType +import ch.ergon.dope.resolvable.fromable.useKeys import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertEquals @@ -35,20 +35,6 @@ class UpdateTest : ParameterDependentTest { assertEquals(expected, actual) } - @Test - fun `should support update clause with use keys`() { - val expected = "UPDATE `someBucket` USE KEYS \"someString\"" - - val actual = create - .update( - someBucket(), - ).useKeys( - someString().toDopeType(), - ).build().queryString - - assertEquals(expected, actual) - } - @Test fun `should support update clause with set`() { val expected = "UPDATE `someBucket` SET META().`expiration` = 10, `stringField` = \"test\"" @@ -139,9 +125,7 @@ class UpdateTest : ParameterDependentTest { val actual = create .update( - bucket, - ).useKeys( - "keyString".toDopeType(), + bucket.useKeys("keyString"), ).set( someNumberField("setThisNumberField"), 1.toDopeType(), diff --git a/core/src/test/kotlin/ch/ergon/dope/buildTest/UseClauseTest.kt b/core/src/test/kotlin/ch/ergon/dope/buildTest/UseKeysTest.kt similarity index 62% rename from core/src/test/kotlin/ch/ergon/dope/buildTest/UseClauseTest.kt rename to core/src/test/kotlin/ch/ergon/dope/buildTest/UseKeysTest.kt index ba5b845b..48cf06a1 100644 --- a/core/src/test/kotlin/ch/ergon/dope/buildTest/UseClauseTest.kt +++ b/core/src/test/kotlin/ch/ergon/dope/buildTest/UseKeysTest.kt @@ -2,17 +2,18 @@ package ch.ergon.dope.buildTest import ch.ergon.dope.QueryBuilder import ch.ergon.dope.helper.someBucket -import ch.ergon.dope.helper.someNumberField import ch.ergon.dope.helper.someStringArrayField import ch.ergon.dope.helper.someStringField -import ch.ergon.dope.resolvable.expression.unaliased.type.relational.isEqualTo import ch.ergon.dope.resolvable.expression.unaliased.type.stringfunction.concat import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType +import ch.ergon.dope.resolvable.fromable.IndexReference +import ch.ergon.dope.resolvable.fromable.useIndex +import ch.ergon.dope.resolvable.fromable.useKeys import junit.framework.TestCase.assertEquals import kotlin.test.BeforeTest import kotlin.test.Test -class UseClauseTest { +class UseKeysTest { private lateinit var create: QueryBuilder @BeforeTest @@ -27,10 +28,7 @@ class UseClauseTest { val actual: String = create .selectAsterisk() .from( - someBucket(), - ) - .useKeys( - "someId".toDopeType(), + someBucket().useKeys("someId"), ) .build().queryString @@ -44,10 +42,7 @@ class UseClauseTest { val actual: String = create .selectAsterisk() .from( - someBucket(), - ) - .useKeys( - someStringField(), + someBucket().useKeys(someStringField()), ) .build().queryString @@ -61,11 +56,11 @@ class UseClauseTest { val actual: String = create .selectAsterisk() .from( - someBucket(), + someBucket().useKeys( + listOf("someId".toDopeType(), "anotherId".toDopeType()).toDopeType(), + ), ) - .useKeys( - listOf("someId".toDopeType(), "anotherId".toDopeType()).toDopeType(), - ).build().queryString + .build().queryString assertEquals(expected, actual) } @@ -77,30 +72,11 @@ class UseClauseTest { val actual: String = create .selectAsterisk() .from( - someBucket(), - ) - .useKeys( - someStringArrayField(), - ).build().queryString - - assertEquals(expected, actual) - } - - @Test - fun `should support use keys clause with where clause`() { - val expected = "SELECT * FROM `someBucket` USE KEYS \"someId\" WHERE `numberField` = 1" - - val actual: String = create - .selectAsterisk() - .from( - someBucket(), - ) - .useKeys( - "someId".toDopeType(), + someBucket().useKeys( + someStringArrayField(), + ), ) - .where( - someNumberField().isEqualTo(1), - ).build().queryString + .build().queryString assertEquals(expected, actual) } @@ -112,10 +88,9 @@ class UseClauseTest { val actual: String = create .selectAsterisk() .from( - someBucket(), - ) - .useKeys( - concat("some", "Id"), + someBucket().useKeys( + concat("some", "Id"), + ), ) .build().queryString @@ -128,10 +103,9 @@ class UseClauseTest { val actual: String = create .deleteFrom( - someBucket(), - ) - .useKeys( - "someId".toDopeType(), + someBucket().useKeys( + "someId", + ), ) .build().queryString @@ -144,10 +118,9 @@ class UseClauseTest { val actual: String = create .deleteFrom( - someBucket(), - ) - .useKeys( - someStringField(), + someBucket().useKeys( + someStringField(), + ), ) .build().queryString @@ -160,11 +133,11 @@ class UseClauseTest { val actual: String = create .deleteFrom( - someBucket(), + someBucket().useKeys( + listOf("someId".toDopeType(), "anotherId".toDopeType()).toDopeType(), + ), ) - .useKeys( - listOf("someId".toDopeType(), "anotherId".toDopeType()).toDopeType(), - ).build().queryString + .build().queryString assertEquals(expected, actual) } @@ -175,29 +148,11 @@ class UseClauseTest { val actual: String = create .deleteFrom( - someBucket(), - ) - .useKeys( - someStringArrayField(), - ).build().queryString - - assertEquals(expected, actual) - } - - @Test - fun `should support delete use keys clause with where clause`() { - val expected = "DELETE FROM `someBucket` USE KEYS \"someId\" WHERE `numberField` = 1" - - val actual: String = create - .deleteFrom( - someBucket(), - ) - .useKeys( - "someId".toDopeType(), + someBucket().useKeys( + someStringArrayField(), + ), ) - .where( - someNumberField().isEqualTo(1), - ).build().queryString + .build().queryString assertEquals(expected, actual) } @@ -208,11 +163,11 @@ class UseClauseTest { val actual: String = create .deleteFrom( - someBucket(), + someBucket().useKeys( + concat("some", "Id"), + ), ) - .useKeys( - concat("some", "Id"), - ).build().queryString + .build().queryString assertEquals(expected, actual) } @@ -223,10 +178,9 @@ class UseClauseTest { val actual: String = create .update( - someBucket(), - ) - .useKeys( - "someId".toDopeType(), + someBucket().useKeys( + "someId", + ), ) .build().queryString @@ -239,10 +193,9 @@ class UseClauseTest { val actual: String = create .update( - someBucket(), - ) - .useKeys( - someStringField(), + someBucket().useKeys( + someStringField(), + ), ) .build().queryString @@ -255,11 +208,11 @@ class UseClauseTest { val actual: String = create .update( - someBucket(), + someBucket().useKeys( + listOf("someId".toDopeType(), "anotherId".toDopeType()).toDopeType(), + ), ) - .useKeys( - listOf("someId".toDopeType(), "anotherId".toDopeType()).toDopeType(), - ).build().queryString + .build().queryString assertEquals(expected, actual) } @@ -270,44 +223,56 @@ class UseClauseTest { val actual: String = create .update( - someBucket(), + someBucket().useKeys( + someStringArrayField(), + ), ) - .useKeys( - someStringArrayField(), - ).build().queryString + .build().queryString assertEquals(expected, actual) } @Test - fun `should support update use keys clause with where clause`() { - val expected = "UPDATE `someBucket` USE KEYS \"someId\" WHERE `numberField` = 1" + fun `should support update use keys clause with string function`() { + val expected = "UPDATE `someBucket` USE KEYS CONCAT(\"some\", \"Id\")" val actual: String = create .update( - someBucket(), + someBucket().useKeys( + concat("some", "Id"), + ), ) - .useKeys( - "someId".toDopeType(), + .build().queryString + + assertEquals(expected, actual) + } + + @Test + fun `should support select use index clause`() { + val expected = "SELECT * FROM `someBucket` USE INDEX ()" + + val actual: String = create + .selectAsterisk() + .from( + someBucket().useIndex(), ) - .where( - someNumberField().isEqualTo(1), - ).build().queryString + .build().queryString assertEquals(expected, actual) } @Test - fun `should support update use keys clause with string function`() { - val expected = "UPDATE `someBucket` USE KEYS CONCAT(\"some\", \"Id\")" + fun `should support select use index clause with string function`() { + val expected = "SELECT * FROM `someBucket` USE INDEX (CONCAT(\"some\", \"Id\"))" val actual: String = create - .update( - someBucket(), + .selectAsterisk() + .from( + someBucket().useIndex( + IndexReference(concat("some", "Id")), + ), ) - .useKeys( - concat("some", "Id"), - ).build().queryString + .build().queryString assertEquals(expected, actual) } diff --git a/core/src/test/kotlin/ch/ergon/dope/resolvable/clause/UseKeysClauseTest.kt b/core/src/test/kotlin/ch/ergon/dope/resolvable/clause/UseKeysClauseTest.kt deleted file mode 100644 index a5876588..00000000 --- a/core/src/test/kotlin/ch/ergon/dope/resolvable/clause/UseKeysClauseTest.kt +++ /dev/null @@ -1,197 +0,0 @@ -package ch.ergon.dope.resolvable.clause - -import ch.ergon.dope.DopeQuery -import ch.ergon.dope.helper.ParameterDependentTest -import ch.ergon.dope.helper.someDeleteClause -import ch.ergon.dope.helper.someSelectClause -import ch.ergon.dope.helper.someString -import ch.ergon.dope.helper.someUpdateClause -import ch.ergon.dope.resolvable.clause.model.DeleteUseKeys.Companion.DeleteUseKeysClause -import ch.ergon.dope.resolvable.clause.model.SelectUseKeys.Companion.SelectUseKeysClause -import ch.ergon.dope.resolvable.clause.model.UpdateUseKeys.Companion.UpdateUseKeysClause -import ch.ergon.dope.resolvable.expression.unaliased.type.asParameter -import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType -import kotlin.test.Test -import kotlin.test.assertEquals - -class UseKeysClauseTest : ParameterDependentTest { - @Test - fun `should support select single use keys`() { - val expected = DopeQuery( - "SELECT * USE KEYS \"someString\"", - emptyMap(), - ) - val underTest = SelectUseKeysClause( - "someString".toDopeType(), - someSelectClause(), - ) - - val actual = underTest.toDopeQuery() - - assertEquals(expected, actual) - } - - @Test - fun `should support select array use keys`() { - val expected = DopeQuery( - "SELECT * USE KEYS [\"someString\", \"anotherString\"]", - emptyMap(), - ) - val underTest = SelectUseKeysClause( - listOf("someString".toDopeType(), "anotherString".toDopeType()).toDopeType(), - someSelectClause(), - ) - - val actual = underTest.toDopeQuery() - - assertEquals(expected, actual) - } - - @Test - fun `should support select use keys with parameter`() { - val parameterValue = someString() - val expected = DopeQuery( - "SELECT * USE KEYS $1", - mapOf("$1" to parameterValue), - ) - val underTest = SelectUseKeysClause( - parameterValue.asParameter(), - someSelectClause(), - ) - - val actual = underTest.toDopeQuery() - - assertEquals(expected, actual) - } - - @Test - fun `should support select use keys extension`() { - val useKeysString = someString().toDopeType() - val parentClause = someSelectClause() - val expected = SelectUseKeysClause(useKeysString, parentClause = parentClause) - - val actual = parentClause.useKeys(useKeysString) - - assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) - } - - @Test - fun `should support delete single use keys`() { - val expected = DopeQuery( - "DELETE FROM `someBucket` USE KEYS \"someString\"", - emptyMap(), - ) - val underTest = DeleteUseKeysClause( - "someString".toDopeType(), - someDeleteClause(), - ) - - val actual = underTest.toDopeQuery() - - assertEquals(expected, actual) - } - - @Test - fun `should support delete array use keys`() { - val expected = DopeQuery( - "DELETE FROM `someBucket` USE KEYS [\"someString\", \"anotherString\"]", - emptyMap(), - ) - val underTest = DeleteUseKeysClause( - listOf("someString".toDopeType(), "anotherString".toDopeType()).toDopeType(), - someDeleteClause(), - ) - - val actual = underTest.toDopeQuery() - - assertEquals(expected, actual) - } - - @Test - fun `should support delete use keys with parameter`() { - val parameterValue = someString() - val expected = DopeQuery( - "DELETE FROM `someBucket` USE KEYS $1", - mapOf("$1" to parameterValue), - ) - val underTest = DeleteUseKeysClause( - parameterValue.asParameter(), - someDeleteClause(), - ) - - val actual = underTest.toDopeQuery() - - assertEquals(expected, actual) - } - - @Test - fun `should support delete use keys extension`() { - val useKeysString = someString().toDopeType() - val parentClause = someDeleteClause() - val expected = DeleteUseKeysClause(useKeysString, parentClause = parentClause) - - val actual = parentClause.useKeys(useKeysString) - - assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) - } - - @Test - fun `should support update single use keys`() { - val expected = DopeQuery( - "UPDATE `someBucket` USE KEYS \"someString\"", - emptyMap(), - ) - val underTest = UpdateUseKeysClause( - "someString".toDopeType(), - someUpdateClause(), - ) - - val actual = underTest.toDopeQuery() - - assertEquals(expected, actual) - } - - @Test - fun `should support update array use keys`() { - val expected = DopeQuery( - "UPDATE `someBucket` USE KEYS [\"someString\", \"anotherString\"]", - emptyMap(), - ) - val underTest = UpdateUseKeysClause( - listOf("someString".toDopeType(), "anotherString".toDopeType()).toDopeType(), - someUpdateClause(), - ) - - val actual = underTest.toDopeQuery() - - assertEquals(expected, actual) - } - - @Test - fun `should support update use keys with parameter`() { - val parameterValue = someString() - val expected = DopeQuery( - "UPDATE `someBucket` USE KEYS $1", - mapOf("$1" to parameterValue), - ) - val underTest = UpdateUseKeysClause( - parameterValue.asParameter(), - someUpdateClause(), - ) - - val actual = underTest.toDopeQuery() - - assertEquals(expected, actual) - } - - @Test - fun `should support update use keys extension`() { - val useKeysString = someString().toDopeType() - val parentClause = someUpdateClause() - val expected = UpdateUseKeysClause(useKeysString, parentClause = parentClause) - - val actual = parentClause.useKeys(useKeysString) - - assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) - } -} diff --git a/core/src/test/kotlin/ch/ergon/dope/resolvable/fromable/UseTest.kt b/core/src/test/kotlin/ch/ergon/dope/resolvable/fromable/UseTest.kt new file mode 100644 index 00000000..1b0fede7 --- /dev/null +++ b/core/src/test/kotlin/ch/ergon/dope/resolvable/fromable/UseTest.kt @@ -0,0 +1,247 @@ +package ch.ergon.dope.resolvable.fromable + +import ch.ergon.dope.DopeQuery +import ch.ergon.dope.helper.ParameterDependentTest +import ch.ergon.dope.helper.someBucket +import ch.ergon.dope.helper.someString +import ch.ergon.dope.helper.someStringField +import ch.ergon.dope.resolvable.expression.unaliased.type.asParameter +import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType +import ch.ergon.dope.resolvable.fromable.IndexType.USING_FTS +import ch.ergon.dope.resolvable.fromable.IndexType.USING_GSI +import ch.ergon.dope.resolvable.fromable.UseKeysClass.Companion.UseKeys +import kotlin.test.Test +import kotlin.test.assertEquals + +class UseTest : ParameterDependentTest { + @Test + fun `should support empty use index`() { + val expected = DopeQuery( + "`someBucket` USE INDEX ()", + emptyMap(), + ) + val underTest = UseIndex(bucket = someBucket()) + + val actual = underTest.toDopeQuery() + + assertEquals(expected, actual) + } + + @Test + fun `should support single use index with string name`() { + val expected = DopeQuery( + "`someBucket` USE INDEX (\"index\")", + emptyMap(), + ) + val underTest = UseIndex( + IndexReference("index"), + bucket = someBucket(), + ) + + val actual = underTest.toDopeQuery() + + assertEquals(expected, actual) + } + + @Test + fun `should support single use index with type name`() { + val expected = DopeQuery( + "`someBucket` USE INDEX (`index`)", + emptyMap(), + ) + val underTest = UseIndex( + IndexReference(someStringField("index")), + bucket = someBucket(), + ) + + val actual = underTest.toDopeQuery() + + assertEquals(expected, actual) + } + + @Test + fun `should support single use index with name and type`() { + val expected = DopeQuery( + "`someBucket` USE INDEX (`index` USING GSI)", + emptyMap(), + ) + val underTest = UseIndex( + IndexReference(someStringField("index"), USING_GSI), + bucket = someBucket(), + ) + + val actual = underTest.toDopeQuery() + + assertEquals(expected, actual) + } + + @Test + fun `should support multiple use index with name and type mixed`() { + val expected = DopeQuery( + "`someBucket` USE INDEX (`index` USING GSI, USING FTS, `secondIndex`)", + emptyMap(), + ) + val underTest = UseIndex( + IndexReference(someStringField("index"), USING_GSI), + IndexReference(USING_FTS), + IndexReference(someStringField("secondIndex")), + bucket = someBucket(), + ) + + val actual = underTest.toDopeQuery() + + assertEquals(expected, actual) + } + + @Test + fun `should support single use index with parameter`() { + val expected = DopeQuery( + "`someBucket` USE INDEX ($1)", + mapOf("$1" to "index"), + ) + val underTest = UseIndex( + IndexReference("index".asParameter()), + bucket = someBucket(), + ) + + val actual = underTest.toDopeQuery() + + assertEquals(expected, actual) + } + + @Test + fun `should support single use index with parameter with type`() { + val expected = DopeQuery( + "`someBucket` USE INDEX ($1 USING FTS)", + mapOf("$1" to "index"), + ) + val underTest = UseIndex( + IndexReference("index".asParameter(), USING_FTS), + bucket = someBucket(), + ) + + val actual = underTest.toDopeQuery() + + assertEquals(expected, actual) + } + + @Test + fun `should support use index extension function`() { + val bucket = someBucket() + val expected = UseIndex(bucket = bucket) + + val actual = bucket.useIndex() + + assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) + } + + @Test + fun `should support use index extension function with single index reference`() { + val indexReference = IndexReference("index") + val bucket = someBucket() + val expected = UseIndex(indexReference, bucket = bucket) + + val actual = bucket.useIndex(indexReference) + + assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) + } + + @Test + fun `should support use index extension function with multiple index references`() { + val firstIndexReference = IndexReference(USING_FTS) + val secondIndexReference = IndexReference("index") + val bucket = someBucket() + val expected = UseIndex(firstIndexReference, secondIndexReference, bucket = bucket) + + val actual = bucket.useIndex(firstIndexReference, secondIndexReference) + + assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) + } + + @Test + fun `should support select single use keys`() { + val expected = DopeQuery( + "`someBucket` USE KEYS \"someString\"", + emptyMap(), + ) + val underTest = UseKeys( + "someString".toDopeType(), + someBucket(), + ) + + val actual = underTest.toDopeQuery() + + assertEquals(expected, actual) + } + + @Test + fun `should support select array use keys`() { + val expected = DopeQuery( + "`someBucket` USE KEYS [\"someString\", \"anotherString\"]", + emptyMap(), + ) + val underTest = UseKeys( + listOf("someString".toDopeType(), "anotherString".toDopeType()).toDopeType(), + someBucket(), + ) + + val actual = underTest.toDopeQuery() + + assertEquals(expected, actual) + } + + @Test + fun `should support use keys with parameter`() { + val parameterValue = someString() + val expected = DopeQuery( + "`someBucket` USE KEYS $1", + mapOf("$1" to parameterValue), + ) + val underTest = UseKeys( + parameterValue.asParameter(), + someBucket(), + ) + + val actual = underTest.toDopeQuery() + + assertEquals(expected, actual) + } + + @Test + fun `should support use keys extension`() { + val useKeysString = someString().toDopeType() + val bucket = someBucket() + val expected = UseKeys(useKeysString, bucket = bucket) + + val actual = bucket.useKeys(useKeysString) + + assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) + } + + @Test + fun `should support use keys extension with collection`() { + val useKeysString = listOf(someString().toDopeType()) + val bucket = someBucket() + val expected = UseKeys(useKeysString.toDopeType(), bucket = bucket) + + val actual = bucket.useKeys(useKeysString) + + assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) + } + + @Test + fun `should support use keys extension with strings`() { + val useKeysString1 = someString() + val useKeysString2 = someString() + val useKeysString3 = someString() + val bucket = someBucket() + val expected = UseKeys( + listOf(useKeysString1.toDopeType(), useKeysString2.toDopeType(), useKeysString3.toDopeType()).toDopeType(), + bucket = bucket, + ) + + val actual = bucket.useKeys(useKeysString1, useKeysString2, useKeysString3) + + assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) + } +} diff --git a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/DeleteClause.kt b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/DeleteClause.kt index 1907f55e..ad0d3d3e 100644 --- a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/DeleteClause.kt +++ b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/DeleteClause.kt @@ -3,11 +3,9 @@ package ch.ergon.dope.extension.clause import ch.ergon.dope.resolvable.clause.IDeleteClause import ch.ergon.dope.resolvable.clause.IDeleteLimitClause import ch.ergon.dope.resolvable.clause.IDeleteOffsetClause -import ch.ergon.dope.resolvable.clause.IDeleteUseKeysClause import ch.ergon.dope.resolvable.clause.IDeleteWhereClause import ch.ergon.dope.toDopeType import com.schwarz.crystalapi.schema.CMField -import com.schwarz.crystalapi.schema.CMList import com.schwarz.crystalapi.schema.CMType fun IDeleteOffsetClause.returning(field: CMType, vararg fields: CMType) = @@ -17,7 +15,4 @@ fun IDeleteLimitClause.offset(numberExpression: CMField) = offset(number fun IDeleteWhereClause.limit(numberExpression: CMField) = limit(numberExpression.toDopeType()) -fun IDeleteUseKeysClause.where(booleanExpression: CMField) = where(booleanExpression.toDopeType()) - -fun IDeleteClause.useKeys(useKeys: CMField) = useKeys(useKeys.toDopeType()) -fun IDeleteClause.useKeys(useKeys: CMList) = useKeys(useKeys.toDopeType()) +fun IDeleteClause.where(booleanExpression: CMField) = where(booleanExpression.toDopeType()) diff --git a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/SelectClause.kt b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/SelectClause.kt index cfc1c43e..0e5db8b4 100644 --- a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/SelectClause.kt +++ b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/SelectClause.kt @@ -6,7 +6,6 @@ import ch.ergon.dope.resolvable.clause.ISelectJoinClause import ch.ergon.dope.resolvable.clause.ISelectLimitClause import ch.ergon.dope.resolvable.clause.ISelectOrderByClause import ch.ergon.dope.resolvable.clause.ISelectUnnestClause -import ch.ergon.dope.resolvable.clause.ISelectUseKeysClause import ch.ergon.dope.resolvable.clause.ISelectWhereClause import ch.ergon.dope.resolvable.clause.model.OrderByType import ch.ergon.dope.resolvable.fromable.Bucket @@ -27,10 +26,7 @@ fun ISelectGroupByClause.orderBy(stringField: CMField, orderByType: Orde fun ISelectWhereClause.groupBy(field: CMType, vararg fields: CMType) = groupBy(field.toDopeType(), *fields.map { it.toDopeType() }.toTypedArray()) -fun ISelectUseKeysClause.where(whereExpression: CMField) = where(whereExpression.toDopeType()) - -fun ISelectFromClause.useKeys(useKeys: CMField) = useKeys(useKeys.toDopeType()) -fun ISelectFromClause.useKeys(useKeys: CMList) = useKeys(useKeys.toDopeType()) +fun ISelectFromClause.where(whereExpression: CMField) = where(whereExpression.toDopeType()) fun ISelectJoinClause.join(bucket: Bucket, onKeys: CMField) = join(bucket, onKeys.toDopeType()) fun ISelectJoinClause.join(bucket: Bucket, onKey: CMField, forBucket: Bucket) = join(bucket, onKey.toDopeType(), forBucket) diff --git a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/UpdateClause.kt b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/UpdateClause.kt index 9a4daec7..05fe4df4 100644 --- a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/UpdateClause.kt +++ b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/UpdateClause.kt @@ -4,7 +4,6 @@ import ch.ergon.dope.resolvable.clause.IUpdateClause import ch.ergon.dope.resolvable.clause.IUpdateLimitClause import ch.ergon.dope.resolvable.clause.IUpdateSetClause import ch.ergon.dope.resolvable.clause.IUpdateUnsetClause -import ch.ergon.dope.resolvable.clause.IUpdateUseKeysClause import ch.ergon.dope.resolvable.clause.IUpdateWhereClause import ch.ergon.dope.resolvable.clause.model.SetClause import ch.ergon.dope.resolvable.clause.model.UnsetClause @@ -45,7 +44,7 @@ fun SetClause.set( ) = this.set(field.toDopeType(), value.toDopeType()) @JvmName("setCMStringFieldToCMStringField") -fun IUpdateUseKeysClause.set( +fun IUpdateClause.set( field: CMField, value: CMField, ) = set(field.toDopeType(), value.toDopeType()) @@ -57,7 +56,7 @@ fun SetClause.set( ) = this.set(field.toDopeType(), value.toDopeType()) @JvmName("setCMBooleanFieldToCMBooleanField") -fun IUpdateUseKeysClause.set( +fun IUpdateClause.set( field: CMField, value: CMField, ) = set(field.toDopeType(), value.toDopeType()) @@ -69,7 +68,7 @@ fun SetClause.set( ) = this.set(field.toDopeType(), value.toDopeType()) @JvmName("setCMNumberListToCMNumberList") -fun IUpdateUseKeysClause.set( +fun IUpdateClause.set( field: CMList, value: CMList, ) = set(field.toDopeType(), value.toDopeType()) @@ -81,7 +80,7 @@ fun SetClause.set( ) = this.set(field.toDopeType(), value.toDopeType()) @JvmName("setCMStringListToCMStringList") -fun IUpdateUseKeysClause.set( +fun IUpdateClause.set( field: CMList, value: CMList, ) = set(field.toDopeType(), value.toDopeType()) @@ -93,7 +92,7 @@ fun SetClause.set( ) = this.set(field.toDopeType(), value.toDopeType()) @JvmName("setCMBooleanListToCMBooleanList") -fun IUpdateUseKeysClause.set( +fun IUpdateClause.set( field: CMList, value: CMList, ) = set(field.toDopeType(), value.toDopeType()) @@ -105,7 +104,7 @@ fun SetClause.set( ) = this.set(field.toDopeType(), value.toDopeType()) @JvmName("setCMNumberFieldToNumberTypeExpression") -fun IUpdateUseKeysClause.set( +fun IUpdateClause.set( field: CMField, value: TypeExpression, ) = set(field.toDopeType(), value) @@ -117,7 +116,7 @@ fun SetClause.set( ) = this.set(field.toDopeType(), value) @JvmName("setCMStringFieldToStringTypeExpression") -fun IUpdateUseKeysClause.set( +fun IUpdateClause.set( field: CMField, value: TypeExpression, ) = set(field.toDopeType(), value) @@ -129,7 +128,7 @@ fun SetClause.set( ) = this.set(field.toDopeType(), value) @JvmName("setCMBooleanFieldToBooleanTypeExpression") -fun IUpdateUseKeysClause.set( +fun IUpdateClause.set( field: CMField, value: TypeExpression, ) = set(field.toDopeType(), value) @@ -141,7 +140,7 @@ fun SetClause.set( ) = this.set(field.toDopeType(), value) @JvmName("setCMNumberListToNumberArrayTypeExpression") -fun IUpdateUseKeysClause.set( +fun IUpdateClause.set( field: CMList, value: TypeExpression>, ) = set(field.toDopeType(), value) @@ -153,7 +152,7 @@ fun SetClause.set( ) = this.set(field.toDopeType(), value) @JvmName("setCMStringListToStringArrayTypeExpression") -fun IUpdateUseKeysClause.set( +fun IUpdateClause.set( field: CMList, value: TypeExpression>, ) = set(field.toDopeType(), value) @@ -165,7 +164,7 @@ fun SetClause.set( ) = this.set(field.toDopeType(), value) @JvmName("setCMBooleanListToBooleanArrayTypeExpression") -fun IUpdateUseKeysClause.set( +fun IUpdateClause.set( field: CMList, value: TypeExpression>, ) = set(field.toDopeType(), value) @@ -177,7 +176,7 @@ fun SetClause.set( ) = this.set(field.toDopeType(), value) @JvmName("setCMNumberFieldToNumber") -fun IUpdateUseKeysClause.set( +fun IUpdateClause.set( field: CMField, value: Number, ) = set(field.toDopeType(), value) @@ -189,7 +188,7 @@ fun SetClause.set( ) = this.set(field.toDopeType(), value) @JvmName("setCMStringFieldToString") -fun IUpdateUseKeysClause.set( +fun IUpdateClause.set( field: CMField, value: String, ) = set(field.toDopeType(), value) @@ -201,7 +200,7 @@ fun SetClause.set( ) = this.set(field.toDopeType(), value) @JvmName("setCMBooleanFieldToBoolean") -fun IUpdateUseKeysClause.set( +fun IUpdateClause.set( field: CMField, value: Boolean, ) = set(field.toDopeType(), value) @@ -211,6 +210,3 @@ fun SetClause.set( field: CMField, value: Boolean, ) = this.set(field.toDopeType(), value) - -fun IUpdateClause.useKeys(useKeys: CMField) = useKeys(useKeys.toDopeType()) -fun IUpdateClause.useKeys(useKeys: CMList) = useKeys(useKeys.toDopeType()) diff --git a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/fromable/Use.kt b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/fromable/Use.kt new file mode 100644 index 00000000..9ecb3b3c --- /dev/null +++ b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/fromable/Use.kt @@ -0,0 +1,11 @@ +package ch.ergon.dope.extension.fromable + +import ch.ergon.dope.resolvable.fromable.Bucket +import ch.ergon.dope.resolvable.fromable.useKeys +import ch.ergon.dope.toDopeType +import com.schwarz.crystalapi.schema.CMField +import com.schwarz.crystalapi.schema.CMList + +fun Bucket.useKeys(useKeys: CMField) = useKeys(useKeys.toDopeType()) + +fun Bucket.useKeys(useKeys: CMList) = useKeys(useKeys.toDopeType()) diff --git a/crystal-map-connector/src/test/kotlin/ch/ergon/dope/extensions/clause/DeleteClauseTest.kt b/crystal-map-connector/src/test/kotlin/ch/ergon/dope/extensions/clause/DeleteClauseTest.kt index ecd2fe66..e22db88a 100644 --- a/crystal-map-connector/src/test/kotlin/ch/ergon/dope/extensions/clause/DeleteClauseTest.kt +++ b/crystal-map-connector/src/test/kotlin/ch/ergon/dope/extensions/clause/DeleteClauseTest.kt @@ -3,46 +3,21 @@ package ch.ergon.dope.extensions.clause import ch.ergon.dope.extension.clause.limit import ch.ergon.dope.extension.clause.offset import ch.ergon.dope.extension.clause.returning -import ch.ergon.dope.extension.clause.useKeys import ch.ergon.dope.extension.clause.where import ch.ergon.dope.helper.someCMBooleanField import ch.ergon.dope.helper.someCMNumberField import ch.ergon.dope.helper.someCMNumberList import ch.ergon.dope.helper.someCMStringField -import ch.ergon.dope.helper.someCMStringList import ch.ergon.dope.helper.someDelete import ch.ergon.dope.resolvable.clause.model.DeleteLimitClause import ch.ergon.dope.resolvable.clause.model.DeleteOffsetClause import ch.ergon.dope.resolvable.clause.model.DeleteReturningClause -import ch.ergon.dope.resolvable.clause.model.DeleteUseKeys.Companion.DeleteUseKeysClause import ch.ergon.dope.resolvable.clause.model.DeleteWhereClause import ch.ergon.dope.toDopeType import kotlin.test.Test import kotlin.test.assertEquals class DeleteClauseTest { - @Test - fun `should support delete single use keys with CM`() { - val useKeys = someCMStringField() - val parentClause = someDelete() - val expected = DeleteUseKeysClause(useKeys.toDopeType(), parentClause) - - val actual = parentClause.useKeys(useKeys) - - assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) - } - - @Test - fun `should support delete list use keys with CM`() { - val useKeys = someCMStringList() - val parentClause = someDelete() - val expected = DeleteUseKeysClause(useKeys.toDopeType(), parentClause) - - val actual = parentClause.useKeys(useKeys) - - assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) - } - @Test fun `should support delete where with CM`() { val field = someCMBooleanField() diff --git a/crystal-map-connector/src/test/kotlin/ch/ergon/dope/extensions/clause/SelectClauseTest.kt b/crystal-map-connector/src/test/kotlin/ch/ergon/dope/extensions/clause/SelectClauseTest.kt index 02bd9773..7bc65af2 100644 --- a/crystal-map-connector/src/test/kotlin/ch/ergon/dope/extensions/clause/SelectClauseTest.kt +++ b/crystal-map-connector/src/test/kotlin/ch/ergon/dope/extensions/clause/SelectClauseTest.kt @@ -8,7 +8,6 @@ import ch.ergon.dope.extension.clause.limit import ch.ergon.dope.extension.clause.offset import ch.ergon.dope.extension.clause.orderBy import ch.ergon.dope.extension.clause.unnest -import ch.ergon.dope.extension.clause.useKeys import ch.ergon.dope.extension.clause.where import ch.ergon.dope.helper.someBucket import ch.ergon.dope.helper.someCMBooleanField @@ -27,7 +26,6 @@ import ch.ergon.dope.resolvable.clause.model.SelectLimitClause import ch.ergon.dope.resolvable.clause.model.SelectOffsetClause import ch.ergon.dope.resolvable.clause.model.SelectOrderByClause import ch.ergon.dope.resolvable.clause.model.SelectOrderByTypeClause -import ch.ergon.dope.resolvable.clause.model.SelectUseKeys.Companion.SelectUseKeysClause import ch.ergon.dope.resolvable.clause.model.SelectWhereClause import ch.ergon.dope.resolvable.clause.model.StandardJoinClause import ch.ergon.dope.resolvable.clause.model.UnnestClause @@ -36,28 +34,6 @@ import kotlin.test.Test import kotlin.test.assertEquals class SelectClauseTest { - @Test - fun `should support select single use keys with CM`() { - val useKeys = someCMStringField() - val parentClause = someSelect() - val expected = SelectUseKeysClause(useKeys.toDopeType(), parentClause) - - val actual = parentClause.useKeys(useKeys) - - assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) - } - - @Test - fun `should support select list use keys with CM`() { - val useKeys = someCMStringList() - val parentClause = someSelect() - val expected = SelectUseKeysClause(useKeys.toDopeType(), parentClause) - - val actual = parentClause.useKeys(useKeys) - - assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) - } - @Test fun `should support select where with CM`() { val field = someCMBooleanField() diff --git a/crystal-map-connector/src/test/kotlin/ch/ergon/dope/extensions/clause/UpdateClauseTest.kt b/crystal-map-connector/src/test/kotlin/ch/ergon/dope/extensions/clause/UpdateClauseTest.kt index 18e175cd..af26fa56 100644 --- a/crystal-map-connector/src/test/kotlin/ch/ergon/dope/extensions/clause/UpdateClauseTest.kt +++ b/crystal-map-connector/src/test/kotlin/ch/ergon/dope/extensions/clause/UpdateClauseTest.kt @@ -4,7 +4,6 @@ import ch.ergon.dope.extension.clause.limit import ch.ergon.dope.extension.clause.returning import ch.ergon.dope.extension.clause.set import ch.ergon.dope.extension.clause.unset -import ch.ergon.dope.extension.clause.useKeys import ch.ergon.dope.extension.clause.where import ch.ergon.dope.helper.someBoolean import ch.ergon.dope.helper.someCMBooleanField @@ -20,7 +19,6 @@ import ch.ergon.dope.resolvable.clause.model.SetClause import ch.ergon.dope.resolvable.clause.model.UnsetClause import ch.ergon.dope.resolvable.clause.model.UpdateLimitClause import ch.ergon.dope.resolvable.clause.model.UpdateReturningClause -import ch.ergon.dope.resolvable.clause.model.UpdateUseKeys.Companion.UpdateUseKeysClause import ch.ergon.dope.resolvable.clause.model.UpdateWhereClause import ch.ergon.dope.resolvable.clause.model.to import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType @@ -29,28 +27,6 @@ import kotlin.test.Test import kotlin.test.assertEquals class UpdateClauseTest { - @Test - fun `should support update single use keys with CM`() { - val useKeys = someCMStringField() - val parentClause = someUpdate() - val expected = UpdateUseKeysClause(useKeys.toDopeType(), parentClause) - - val actual = parentClause.useKeys(useKeys) - - assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) - } - - @Test - fun `should support update list use keys with CM`() { - val useKeys = someCMStringList() - val parentClause = someUpdate() - val expected = UpdateUseKeysClause(useKeys.toDopeType(), parentClause) - - val actual = parentClause.useKeys(useKeys) - - assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) - } - @Test fun `should support update set CMField number to CMField number`() { val field = someCMNumberField() diff --git a/crystal-map-connector/src/test/kotlin/ch/ergon/dope/extensions/fromable/UseTest.kt b/crystal-map-connector/src/test/kotlin/ch/ergon/dope/extensions/fromable/UseTest.kt new file mode 100644 index 00000000..d53fc2bd --- /dev/null +++ b/crystal-map-connector/src/test/kotlin/ch/ergon/dope/extensions/fromable/UseTest.kt @@ -0,0 +1,45 @@ +package ch.ergon.dope.extensions.fromable + +import ch.ergon.dope.extension.fromable.useKeys +import ch.ergon.dope.helper.someBucket +import ch.ergon.dope.helper.someCMStringField +import ch.ergon.dope.helper.someCMStringList +import ch.ergon.dope.resolvable.fromable.UseKeysClass.Companion.UseKeys +import ch.ergon.dope.toDopeType +import kotlin.test.Test +import kotlin.test.assertEquals + +class UseTest { + @Test + fun `should support single use keys with CM`() { + val useKeys = someCMStringField() + val bucket = someBucket() + val expected = UseKeys(useKeys.toDopeType(), bucket) + + val actual = bucket.useKeys(useKeys) + + assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) + } + + @Test + fun `should support single use keys with CM on aliased bucket`() { + val useKeys = someCMStringField() + val bucket = someBucket().alias("asdf") + val expected = UseKeys(useKeys.toDopeType(), bucket) + + val actual = bucket.useKeys(useKeys) + + assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) + } + + @Test + fun `should support single multiple keys with CM`() { + val useKeys = someCMStringList() + val bucket = someBucket() + val expected = UseKeys(useKeys.toDopeType(), bucket) + + val actual = bucket.useKeys(useKeys) + + assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) + } +} From d23cc03ed655b9fde7493ebb5e7e7292ac77a50a Mon Sep 17 00:00:00 2001 From: Jan Sigrist Date: Wed, 21 Aug 2024 16:11:21 +0200 Subject: [PATCH 02/15] DOPE-242: move function to its class --- .../main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt | 2 ++ .../main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt index 733838e4..3bd4be9b 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt @@ -69,3 +69,5 @@ class UseIndex( ) } } + +fun Bucket.useIndex(vararg indexReference: IndexReference) = UseIndex(*indexReference, bucket = this) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt index b136dc9c..0b526a33 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt @@ -46,5 +46,3 @@ fun Bucket.useKeys(keys: Collection>) = useKeys(keys. fun Bucket.useKeys(firstKey: String, secondKey: String, vararg additionalKeys: String) = useKeys(listOf(firstKey.toDopeType(), secondKey.toDopeType(), *additionalKeys.map { it.toDopeType() }.toTypedArray()).toDopeType()) - -fun Bucket.useIndex(vararg indexReference: IndexReference) = UseIndex(*indexReference, bucket = this) From b7dac5db7325cc32a6721e5b606d3615c7115d9c Mon Sep 17 00:00:00 2001 From: Jan Sigrist Date: Wed, 21 Aug 2024 16:21:04 +0200 Subject: [PATCH 03/15] DOPE-242: added interface Updatable --- core/src/main/kotlin/ch/ergon/dope/QueryBuilder.kt | 3 ++- .../ch/ergon/dope/resolvable/clause/model/UpdateClause.kt | 4 ++-- .../main/kotlin/ch/ergon/dope/resolvable/fromable/Bucket.kt | 2 +- .../main/kotlin/ch/ergon/dope/resolvable/fromable/Fromable.kt | 2 ++ .../main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/core/src/main/kotlin/ch/ergon/dope/QueryBuilder.kt b/core/src/main/kotlin/ch/ergon/dope/QueryBuilder.kt index ac7d8260..49f8cb3c 100644 --- a/core/src/main/kotlin/ch/ergon/dope/QueryBuilder.kt +++ b/core/src/main/kotlin/ch/ergon/dope/QueryBuilder.kt @@ -10,6 +10,7 @@ import ch.ergon.dope.resolvable.expression.Expression import ch.ergon.dope.resolvable.expression.SingleExpression import ch.ergon.dope.resolvable.fromable.Fromable import ch.ergon.dope.resolvable.fromable.IBucket +import ch.ergon.dope.resolvable.fromable.Updatable class QueryBuilder { fun select(expression: Expression, vararg expressions: Expression) = SelectClause(expression, *expressions) @@ -24,5 +25,5 @@ class QueryBuilder { fun deleteFrom(bucket: IBucket) = DeleteClause(bucket) - fun update(bucket: IBucket) = UpdateClause(bucket) + fun update(bucket: Updatable) = UpdateClause(bucket) } diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UpdateClause.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UpdateClause.kt index 89f4c20d..7fcd732d 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UpdateClause.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UpdateClause.kt @@ -2,9 +2,9 @@ package ch.ergon.dope.resolvable.clause.model import ch.ergon.dope.DopeQuery import ch.ergon.dope.resolvable.clause.IUpdateClause -import ch.ergon.dope.resolvable.fromable.IBucket +import ch.ergon.dope.resolvable.fromable.Updatable -class UpdateClause(private val bucket: IBucket) : IUpdateClause { +class UpdateClause(private val bucket: Updatable) : IUpdateClause { override fun toDopeQuery(): DopeQuery { val bucketDopeQuery = bucket.toDopeQuery() return DopeQuery( diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Bucket.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Bucket.kt index 754ea504..ef62f8c6 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Bucket.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Bucket.kt @@ -3,7 +3,7 @@ package ch.ergon.dope.resolvable.fromable import ch.ergon.dope.DopeQuery import ch.ergon.dope.resolvable.expression.AsteriskExpression -sealed class Bucket(open val name: String) : IBucket { +sealed class Bucket(open val name: String) : Updatable { override fun toDopeQuery() = DopeQuery("`$name`", emptyMap()) } diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Fromable.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Fromable.kt index 057cf8c7..460f8a0a 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Fromable.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Fromable.kt @@ -5,3 +5,5 @@ import ch.ergon.dope.resolvable.Resolvable interface Fromable : Resolvable interface IBucket : Fromable + +interface Updatable : IBucket diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt index 0b526a33..55389f84 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt @@ -14,7 +14,7 @@ private const val USE_KEYS = "USE KEYS" class UseKeysClass private constructor( private val useKeys: TypeExpression, private val bucket: Bucket, -) : IBucket { +) : Updatable { companion object { @JvmName("selectSingleUseKeysClauseConstructor") fun UseKeys(key: TypeExpression, bucket: Bucket) = From b44697b25053a65250983cb8360ad51de39810d7 Mon Sep 17 00:00:00 2001 From: Jan Sigrist Date: Wed, 21 Aug 2024 16:33:29 +0200 Subject: [PATCH 04/15] DOPE-242: renaming --- .../kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt | 8 ++++---- .../ergon/dope/buildTest/{UseKeysTest.kt => UseTest.kt} | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) rename core/src/test/kotlin/ch/ergon/dope/buildTest/{UseKeysTest.kt => UseTest.kt} (99%) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt index 3bd4be9b..5f91bc86 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt @@ -39,17 +39,17 @@ class IndexReference : Resolvable { } override fun toDopeQuery(): DopeQuery { - val fromableDopeQuery = indexName?.toDopeQuery() + val indexNameDopeQuery = indexName?.toDopeQuery() val queryString = buildString { - if (fromableDopeQuery != null) { - append(fromableDopeQuery.queryString) + if (indexNameDopeQuery != null) { + append(indexNameDopeQuery.queryString) } if (indexType != null) { if (isNotEmpty()) append(" ") append(indexType.type) } } - return DopeQuery(queryString, fromableDopeQuery?.parameters.orEmpty()) + return DopeQuery(queryString, indexNameDopeQuery?.parameters.orEmpty()) } } diff --git a/core/src/test/kotlin/ch/ergon/dope/buildTest/UseKeysTest.kt b/core/src/test/kotlin/ch/ergon/dope/buildTest/UseTest.kt similarity index 99% rename from core/src/test/kotlin/ch/ergon/dope/buildTest/UseKeysTest.kt rename to core/src/test/kotlin/ch/ergon/dope/buildTest/UseTest.kt index 48cf06a1..6a3c8c51 100644 --- a/core/src/test/kotlin/ch/ergon/dope/buildTest/UseKeysTest.kt +++ b/core/src/test/kotlin/ch/ergon/dope/buildTest/UseTest.kt @@ -13,7 +13,7 @@ import junit.framework.TestCase.assertEquals import kotlin.test.BeforeTest import kotlin.test.Test -class UseKeysTest { +class UseTest { private lateinit var create: QueryBuilder @BeforeTest From 8a001d37a7f7670f5fd783b4d0923c35b25509e0 Mon Sep 17 00:00:00 2001 From: Jan Sigrist Date: Wed, 21 Aug 2024 16:36:12 +0200 Subject: [PATCH 05/15] DOPE-242: use IBucket instead of Bucket in join extensions --- .../ch/ergon/dope/extension/clause/SelectClause.kt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/SelectClause.kt b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/SelectClause.kt index 0e5db8b4..56117765 100644 --- a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/SelectClause.kt +++ b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/SelectClause.kt @@ -9,6 +9,7 @@ import ch.ergon.dope.resolvable.clause.ISelectUnnestClause import ch.ergon.dope.resolvable.clause.ISelectWhereClause import ch.ergon.dope.resolvable.clause.model.OrderByType import ch.ergon.dope.resolvable.fromable.Bucket +import ch.ergon.dope.resolvable.fromable.IBucket import ch.ergon.dope.toDopeType import com.schwarz.crystalapi.schema.CMField import com.schwarz.crystalapi.schema.CMList @@ -28,14 +29,14 @@ fun ISelectWhereClause.groupBy(field: CMType, vararg fields: CMType) = fun ISelectFromClause.where(whereExpression: CMField) = where(whereExpression.toDopeType()) -fun ISelectJoinClause.join(bucket: Bucket, onKeys: CMField) = join(bucket, onKeys.toDopeType()) -fun ISelectJoinClause.join(bucket: Bucket, onKey: CMField, forBucket: Bucket) = join(bucket, onKey.toDopeType(), forBucket) +fun ISelectJoinClause.join(bucket: IBucket, onKeys: CMField) = join(bucket, onKeys.toDopeType()) +fun ISelectJoinClause.join(bucket: IBucket, onKey: CMField, forBucket: Bucket) = join(bucket, onKey.toDopeType(), forBucket) -fun ISelectJoinClause.innerJoin(bucket: Bucket, onKeys: CMField) = innerJoin(bucket, onKeys.toDopeType()) -fun ISelectJoinClause.innerJoin(bucket: Bucket, onKey: CMField, forBucket: Bucket) = innerJoin(bucket, onKey.toDopeType(), forBucket) +fun ISelectJoinClause.innerJoin(bucket: IBucket, onKeys: CMField) = innerJoin(bucket, onKeys.toDopeType()) +fun ISelectJoinClause.innerJoin(bucket: IBucket, onKey: CMField, forBucket: Bucket) = innerJoin(bucket, onKey.toDopeType(), forBucket) -fun ISelectJoinClause.leftJoin(bucket: Bucket, onKeys: CMField) = leftJoin(bucket, onKeys.toDopeType()) -fun ISelectJoinClause.leftJoin(bucket: Bucket, onKey: CMField, forBucket: Bucket) = leftJoin(bucket, onKey.toDopeType(), forBucket) +fun ISelectJoinClause.leftJoin(bucket: IBucket, onKeys: CMField) = leftJoin(bucket, onKeys.toDopeType()) +fun ISelectJoinClause.leftJoin(bucket: IBucket, onKey: CMField, forBucket: Bucket) = leftJoin(bucket, onKey.toDopeType(), forBucket) @JvmName("unnestString") fun ISelectUnnestClause.unnest(arrayField: CMList) = unnest(arrayField.toDopeType()) From 14fe0e8c3c1d3cb79ac7ceba6a06f89692159a4e Mon Sep 17 00:00:00 2001 From: Jan Sigrist Date: Thu, 22 Aug 2024 13:12:13 +0200 Subject: [PATCH 06/15] DOPE-242: changed IndexReference and made bucket first argument --- .../dope/resolvable/fromable/UseIndex.kt | 25 ++----- .../kotlin/ch/ergon/dope/buildTest/UseTest.kt | 17 ----- .../ergon/dope/resolvable/fromable/UseTest.kt | 75 ++++--------------- 3 files changed, 21 insertions(+), 96 deletions(-) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt index 5f91bc86..8a840a5a 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt @@ -2,10 +2,7 @@ package ch.ergon.dope.resolvable.fromable import ch.ergon.dope.DopeQuery import ch.ergon.dope.resolvable.Resolvable -import ch.ergon.dope.resolvable.expression.TypeExpression -import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType import ch.ergon.dope.resolvable.formatToQueryStringWithSymbol -import ch.ergon.dope.validtype.StringType private const val USE_INDEX = "USE INDEX" @@ -15,21 +12,16 @@ enum class IndexType(val type: String) { } class IndexReference : Resolvable { - private val indexName: TypeExpression? + private val indexName: String? private val indexType: IndexType? - constructor(indexName: TypeExpression, indexType: IndexType) { + constructor(indexName: String, indexType: IndexType) { this.indexName = indexName this.indexType = indexType } - constructor(indexName: TypeExpression) { - this.indexName = indexName - this.indexType = null - } - constructor(indexName: String) { - this.indexName = indexName.toDopeType() + this.indexName = indexName this.indexType = null } @@ -39,23 +31,22 @@ class IndexReference : Resolvable { } override fun toDopeQuery(): DopeQuery { - val indexNameDopeQuery = indexName?.toDopeQuery() val queryString = buildString { - if (indexNameDopeQuery != null) { - append(indexNameDopeQuery.queryString) + if (indexName != null) { + append("`$indexName`") } if (indexType != null) { if (isNotEmpty()) append(" ") append(indexType.type) } } - return DopeQuery(queryString, indexNameDopeQuery?.parameters.orEmpty()) + return DopeQuery(queryString, emptyMap()) } } class UseIndex( - private vararg val indexReference: IndexReference, private val bucket: Bucket, + private vararg val indexReference: IndexReference, ) : IBucket { override fun toDopeQuery(): DopeQuery { val bucketDopeQuery = bucket.toDopeQuery() @@ -70,4 +61,4 @@ class UseIndex( } } -fun Bucket.useIndex(vararg indexReference: IndexReference) = UseIndex(*indexReference, bucket = this) +fun Bucket.useIndex(vararg indexReference: IndexReference) = UseIndex(this, *indexReference) diff --git a/core/src/test/kotlin/ch/ergon/dope/buildTest/UseTest.kt b/core/src/test/kotlin/ch/ergon/dope/buildTest/UseTest.kt index 6a3c8c51..fc93a8d7 100644 --- a/core/src/test/kotlin/ch/ergon/dope/buildTest/UseTest.kt +++ b/core/src/test/kotlin/ch/ergon/dope/buildTest/UseTest.kt @@ -6,7 +6,6 @@ import ch.ergon.dope.helper.someStringArrayField import ch.ergon.dope.helper.someStringField import ch.ergon.dope.resolvable.expression.unaliased.type.stringfunction.concat import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType -import ch.ergon.dope.resolvable.fromable.IndexReference import ch.ergon.dope.resolvable.fromable.useIndex import ch.ergon.dope.resolvable.fromable.useKeys import junit.framework.TestCase.assertEquals @@ -260,20 +259,4 @@ class UseTest { assertEquals(expected, actual) } - - @Test - fun `should support select use index clause with string function`() { - val expected = "SELECT * FROM `someBucket` USE INDEX (CONCAT(\"some\", \"Id\"))" - - val actual: String = create - .selectAsterisk() - .from( - someBucket().useIndex( - IndexReference(concat("some", "Id")), - ), - ) - .build().queryString - - assertEquals(expected, actual) - } } diff --git a/core/src/test/kotlin/ch/ergon/dope/resolvable/fromable/UseTest.kt b/core/src/test/kotlin/ch/ergon/dope/resolvable/fromable/UseTest.kt index 1b0fede7..f85ca781 100644 --- a/core/src/test/kotlin/ch/ergon/dope/resolvable/fromable/UseTest.kt +++ b/core/src/test/kotlin/ch/ergon/dope/resolvable/fromable/UseTest.kt @@ -4,7 +4,6 @@ import ch.ergon.dope.DopeQuery import ch.ergon.dope.helper.ParameterDependentTest import ch.ergon.dope.helper.someBucket import ch.ergon.dope.helper.someString -import ch.ergon.dope.helper.someStringField import ch.ergon.dope.resolvable.expression.unaliased.type.asParameter import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType import ch.ergon.dope.resolvable.fromable.IndexType.USING_FTS @@ -20,7 +19,7 @@ class UseTest : ParameterDependentTest { "`someBucket` USE INDEX ()", emptyMap(), ) - val underTest = UseIndex(bucket = someBucket()) + val underTest = UseIndex(someBucket()) val actual = underTest.toDopeQuery() @@ -29,45 +28,13 @@ class UseTest : ParameterDependentTest { @Test fun `should support single use index with string name`() { - val expected = DopeQuery( - "`someBucket` USE INDEX (\"index\")", - emptyMap(), - ) - val underTest = UseIndex( - IndexReference("index"), - bucket = someBucket(), - ) - - val actual = underTest.toDopeQuery() - - assertEquals(expected, actual) - } - - @Test - fun `should support single use index with type name`() { val expected = DopeQuery( "`someBucket` USE INDEX (`index`)", emptyMap(), ) val underTest = UseIndex( - IndexReference(someStringField("index")), - bucket = someBucket(), - ) - - val actual = underTest.toDopeQuery() - - assertEquals(expected, actual) - } - - @Test - fun `should support single use index with name and type`() { - val expected = DopeQuery( - "`someBucket` USE INDEX (`index` USING GSI)", - emptyMap(), - ) - val underTest = UseIndex( - IndexReference(someStringField("index"), USING_GSI), - bucket = someBucket(), + someBucket(), + IndexReference("index"), ) val actual = underTest.toDopeQuery() @@ -82,10 +49,10 @@ class UseTest : ParameterDependentTest { emptyMap(), ) val underTest = UseIndex( - IndexReference(someStringField("index"), USING_GSI), + someBucket(), + IndexReference("index", USING_GSI), IndexReference(USING_FTS), - IndexReference(someStringField("secondIndex")), - bucket = someBucket(), + IndexReference("secondIndex"), ) val actual = underTest.toDopeQuery() @@ -96,28 +63,12 @@ class UseTest : ParameterDependentTest { @Test fun `should support single use index with parameter`() { val expected = DopeQuery( - "`someBucket` USE INDEX ($1)", - mapOf("$1" to "index"), - ) - val underTest = UseIndex( - IndexReference("index".asParameter()), - bucket = someBucket(), - ) - - val actual = underTest.toDopeQuery() - - assertEquals(expected, actual) - } - - @Test - fun `should support single use index with parameter with type`() { - val expected = DopeQuery( - "`someBucket` USE INDEX ($1 USING FTS)", - mapOf("$1" to "index"), + "`someBucket` USE INDEX (`index`)", + emptyMap(), ) val underTest = UseIndex( - IndexReference("index".asParameter(), USING_FTS), - bucket = someBucket(), + someBucket(), + IndexReference("index"), ) val actual = underTest.toDopeQuery() @@ -128,7 +79,7 @@ class UseTest : ParameterDependentTest { @Test fun `should support use index extension function`() { val bucket = someBucket() - val expected = UseIndex(bucket = bucket) + val expected = UseIndex(bucket) val actual = bucket.useIndex() @@ -139,7 +90,7 @@ class UseTest : ParameterDependentTest { fun `should support use index extension function with single index reference`() { val indexReference = IndexReference("index") val bucket = someBucket() - val expected = UseIndex(indexReference, bucket = bucket) + val expected = UseIndex(bucket, indexReference) val actual = bucket.useIndex(indexReference) @@ -151,7 +102,7 @@ class UseTest : ParameterDependentTest { val firstIndexReference = IndexReference(USING_FTS) val secondIndexReference = IndexReference("index") val bucket = someBucket() - val expected = UseIndex(firstIndexReference, secondIndexReference, bucket = bucket) + val expected = UseIndex(bucket, firstIndexReference, secondIndexReference) val actual = bucket.useIndex(firstIndexReference, secondIndexReference) From ea4d1ce7da013e661627a4f9eb296fc662040e2b Mon Sep 17 00:00:00 2001 From: Jan Sigrist Date: Thu, 22 Aug 2024 14:39:12 +0200 Subject: [PATCH 07/15] DOPE-242: added extension functions to call multiple use index after each other --- .../dope/resolvable/fromable/UseIndex.kt | 41 ++++++------ .../kotlin/ch/ergon/dope/buildTest/UseTest.kt | 6 +- .../ergon/dope/resolvable/fromable/UseTest.kt | 63 +++++++++++++++---- 3 files changed, 75 insertions(+), 35 deletions(-) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt index 8a840a5a..e6b15492 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt @@ -3,6 +3,8 @@ package ch.ergon.dope.resolvable.fromable import ch.ergon.dope.DopeQuery import ch.ergon.dope.resolvable.Resolvable import ch.ergon.dope.resolvable.formatToQueryStringWithSymbol +import ch.ergon.dope.resolvable.fromable.IndexType.USING_FTS +import ch.ergon.dope.resolvable.fromable.IndexType.USING_GSI private const val USE_INDEX = "USE INDEX" @@ -11,25 +13,10 @@ enum class IndexType(val type: String) { USING_FTS("USING FTS"), } -class IndexReference : Resolvable { - private val indexName: String? - private val indexType: IndexType? - - constructor(indexName: String, indexType: IndexType) { - this.indexName = indexName - this.indexType = indexType - } - - constructor(indexName: String) { - this.indexName = indexName - this.indexType = null - } - - constructor(indexType: IndexType) { - this.indexName = null - this.indexType = indexType - } - +class IndexReference( + private val indexName: String? = null, + private val indexType: IndexType? = null, +) : Resolvable { override fun toDopeQuery(): DopeQuery { val queryString = buildString { if (indexName != null) { @@ -45,8 +32,8 @@ class IndexReference : Resolvable { } class UseIndex( - private val bucket: Bucket, - private vararg val indexReference: IndexReference, + val bucket: Bucket, + vararg val indexReference: IndexReference, ) : IBucket { override fun toDopeQuery(): DopeQuery { val bucketDopeQuery = bucket.toDopeQuery() @@ -61,4 +48,14 @@ class UseIndex( } } -fun Bucket.useIndex(vararg indexReference: IndexReference) = UseIndex(this, *indexReference) +fun UseIndex.useIndex(indexName: String) = UseIndex(bucket, *indexReference, IndexReference(indexName)) + +fun UseIndex.useGsiIndex(indexName: String? = null) = UseIndex(bucket, *indexReference, IndexReference(indexName, USING_GSI)) + +fun UseIndex.useFtsIndex(indexName: String? = null) = UseIndex(bucket, *indexReference, IndexReference(indexName, USING_FTS)) + +fun Bucket.useIndex(indexName: String? = null) = UseIndex(this, IndexReference(indexName)) + +fun Bucket.useGsiIndex(indexName: String? = null) = UseIndex(this, IndexReference(indexName, USING_GSI)) + +fun Bucket.useFtsIndex(indexName: String? = null) = UseIndex(this, IndexReference(indexName, USING_FTS)) diff --git a/core/src/test/kotlin/ch/ergon/dope/buildTest/UseTest.kt b/core/src/test/kotlin/ch/ergon/dope/buildTest/UseTest.kt index fc93a8d7..1f3b6742 100644 --- a/core/src/test/kotlin/ch/ergon/dope/buildTest/UseTest.kt +++ b/core/src/test/kotlin/ch/ergon/dope/buildTest/UseTest.kt @@ -6,6 +6,8 @@ import ch.ergon.dope.helper.someStringArrayField import ch.ergon.dope.helper.someStringField import ch.ergon.dope.resolvable.expression.unaliased.type.stringfunction.concat import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType +import ch.ergon.dope.resolvable.fromable.useFtsIndex +import ch.ergon.dope.resolvable.fromable.useGsiIndex import ch.ergon.dope.resolvable.fromable.useIndex import ch.ergon.dope.resolvable.fromable.useKeys import junit.framework.TestCase.assertEquals @@ -248,12 +250,12 @@ class UseTest { @Test fun `should support select use index clause`() { - val expected = "SELECT * FROM `someBucket` USE INDEX ()" + val expected = "SELECT * FROM `someBucket` USE INDEX (`someIndex` USING FTS, `otherIndex`, `index3` USING GSI)" val actual: String = create .selectAsterisk() .from( - someBucket().useIndex(), + someBucket().useFtsIndex("someIndex").useIndex("otherIndex").useGsiIndex("index3"), ) .build().queryString diff --git a/core/src/test/kotlin/ch/ergon/dope/resolvable/fromable/UseTest.kt b/core/src/test/kotlin/ch/ergon/dope/resolvable/fromable/UseTest.kt index f85ca781..2cd0bf20 100644 --- a/core/src/test/kotlin/ch/ergon/dope/resolvable/fromable/UseTest.kt +++ b/core/src/test/kotlin/ch/ergon/dope/resolvable/fromable/UseTest.kt @@ -51,7 +51,7 @@ class UseTest : ParameterDependentTest { val underTest = UseIndex( someBucket(), IndexReference("index", USING_GSI), - IndexReference(USING_FTS), + IndexReference(indexType = USING_FTS), IndexReference("secondIndex"), ) @@ -77,7 +77,7 @@ class UseTest : ParameterDependentTest { } @Test - fun `should support use index extension function`() { + fun `should support use index extension function without index name`() { val bucket = someBucket() val expected = UseIndex(bucket) @@ -87,24 +87,65 @@ class UseTest : ParameterDependentTest { } @Test - fun `should support use index extension function with single index reference`() { - val indexReference = IndexReference("index") + fun `should support use index extension function`() { + val indexName = "index" + val bucket = someBucket() + val expected = UseIndex(bucket, IndexReference(indexName)) + + val actual = bucket.useIndex(indexName) + + assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) + } + + @Test + fun `should support use gsi index extension function`() { + val indexName = "index" + val bucket = someBucket() + val expected = UseIndex(bucket, IndexReference(indexName, USING_GSI)) + + val actual = bucket.useGsiIndex(indexName) + + assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) + } + + @Test + fun `should support use fts index extension function`() { + val indexName = "index" + val bucket = someBucket() + val expected = UseIndex(bucket, IndexReference(indexName, USING_FTS)) + + val actual = bucket.useFtsIndex(indexName) + + assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) + } + + @Test + fun `should support multiple use index extension function`() { + val indexName = "index" + val indexName2 = "index" val bucket = someBucket() - val expected = UseIndex(bucket, indexReference) + val expected = UseIndex(bucket, IndexReference(indexName), IndexReference(indexName2)) - val actual = bucket.useIndex(indexReference) + val actual = bucket.useIndex(indexName).useIndex(indexName2) assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) } @Test - fun `should support use index extension function with multiple index references`() { - val firstIndexReference = IndexReference(USING_FTS) - val secondIndexReference = IndexReference("index") + fun `should support multiple different use index extension function`() { + val indexName = "index" + val indexName2 = "index" val bucket = someBucket() - val expected = UseIndex(bucket, firstIndexReference, secondIndexReference) + val expected = UseIndex( + bucket, + IndexReference(indexName, USING_GSI), + IndexReference(indexName2), + IndexReference(indexType = USING_FTS), + IndexReference(indexType = USING_GSI), + ) - val actual = bucket.useIndex(firstIndexReference, secondIndexReference) + val actual = bucket.useGsiIndex(indexName).useIndex(indexName2).useFtsIndex().useGsiIndex() + println(actual.toDopeQuery()) assertEquals(expected.toDopeQuery(), actual.toDopeQuery()) } From 8a46b957adad12a42fede075af3fb7973d4d98d6 Mon Sep 17 00:00:00 2001 From: Jan Sigrist Date: Thu, 22 Aug 2024 15:11:31 +0200 Subject: [PATCH 08/15] DOPE-242: extracted joinToString into QueryStringBuilder function --- .../dope/resolvable/QueryStringBuilder.kt | 9 +++++++++ .../expression/unaliased/type/Primitive.kt | 3 ++- .../type/stringfunction/TokensExpression.kt | 3 ++- .../ergon/dope/resolvable/fromable/UseIndex.kt | 8 ++++++-- .../resolvable/operator/FunctionOperator.kt | 18 ++++++------------ 5 files changed, 25 insertions(+), 16 deletions(-) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/QueryStringBuilder.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/QueryStringBuilder.kt index 3599bd2b..8f20eae2 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/QueryStringBuilder.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/QueryStringBuilder.kt @@ -1,5 +1,7 @@ package ch.ergon.dope.resolvable +import ch.ergon.dope.DopeQuery + fun formatToQueryString(left: String, vararg right: String) = "$left ${right.joinToString()}" @@ -10,6 +12,7 @@ fun formatToQueryStringWithSeparator(symbol: String, separator: String, vararg a "$symbol$separator${argument.joinToString(separator = ", ")}" fun formatToQueryStringWithBrackets(left: String, symbol: String, right: String) = "($left $symbol $right)" + fun formatToQueryStringWithBrackets(symbol: String, vararg argument: String) = "$symbol(${argument.joinToString(separator = ", ")})" @@ -19,3 +22,9 @@ fun formatPathToQueryString(name: String, path: String) = } else { "`$path`.`$name`" } + +fun formatStringListToQueryStringWithBrackets(dopeQueries: List, seperator: String = ", ", prefix: String = "(", postfix: String = ")") = + dopeQueries.joinToString(seperator, prefix, postfix) + +fun formatListToQueryStringWithBrackets(dopeQueries: List, seperator: String = ", ", prefix: String = "(", postfix: String = ")") = + dopeQueries.joinToString(seperator, prefix, postfix) { it.queryString } diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/Primitive.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/Primitive.kt index f03034ff..3cfc9f55 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/Primitive.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/Primitive.kt @@ -2,6 +2,7 @@ package ch.ergon.dope.resolvable.expression.unaliased.type import ch.ergon.dope.DopeQuery import ch.ergon.dope.resolvable.expression.TypeExpression +import ch.ergon.dope.resolvable.formatListToQueryStringWithBrackets import ch.ergon.dope.validtype.ArrayType import ch.ergon.dope.validtype.BooleanType import ch.ergon.dope.validtype.MissingType @@ -55,7 +56,7 @@ class ArrayPrimitive(collection: Collection { collection.map { it.toDopeQuery() }.let { dopeQueries -> DopeQuery( - queryString = dopeQueries.joinToString(", ", prefix = "[", postfix = "]") { it.queryString }, + queryString = formatListToQueryStringWithBrackets(dopeQueries, prefix = "[", postfix = "]"), parameters = dopeQueries.fold(emptyMap()) { parameters, dopeQueryElement -> parameters + dopeQueryElement.parameters }, ) } diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/stringfunction/TokensExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/stringfunction/TokensExpression.kt index efeb6c29..4363cdad 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/stringfunction/TokensExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/stringfunction/TokensExpression.kt @@ -3,6 +3,7 @@ package ch.ergon.dope.resolvable.expression.unaliased.type.stringfunction import ch.ergon.dope.DopeQuery import ch.ergon.dope.resolvable.expression.TypeExpression import ch.ergon.dope.resolvable.expression.unaliased.type.stringfunction.factory.CustomTokenOptions +import ch.ergon.dope.resolvable.formatStringListToQueryStringWithBrackets import ch.ergon.dope.resolvable.operator.FunctionOperator import ch.ergon.dope.validtype.StringType @@ -18,7 +19,7 @@ class TokensExpression( return DopeQuery( queryString = toFunctionQueryString( symbol = "TOKENS", - inStr.joinToString(prefix = "[\"", postfix = "\"]"), + formatStringListToQueryStringWithBrackets(inStr, prefix = "[\"", postfix = "\"]"), optDopeQuery.queryString, ), parameters = optDopeQuery.parameters, diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt index e6b15492..a1d1ad1f 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt @@ -2,6 +2,7 @@ package ch.ergon.dope.resolvable.fromable import ch.ergon.dope.DopeQuery import ch.ergon.dope.resolvable.Resolvable +import ch.ergon.dope.resolvable.formatListToQueryStringWithBrackets import ch.ergon.dope.resolvable.formatToQueryStringWithSymbol import ch.ergon.dope.resolvable.fromable.IndexType.USING_FTS import ch.ergon.dope.resolvable.fromable.IndexType.USING_GSI @@ -38,9 +39,12 @@ class UseIndex( override fun toDopeQuery(): DopeQuery { val bucketDopeQuery = bucket.toDopeQuery() val indexReferenceDopeQueries = indexReference.map { it.toDopeQuery() } - val indexReferences = indexReferenceDopeQueries.joinToString(", ", prefix = "(", postfix = ")") { it.queryString } return DopeQuery( - queryString = formatToQueryStringWithSymbol(bucketDopeQuery.queryString, USE_INDEX, indexReferences), + queryString = formatToQueryStringWithSymbol( + bucketDopeQuery.queryString, + USE_INDEX, + formatListToQueryStringWithBrackets(indexReferenceDopeQueries, ", ", "(", ")"), + ), parameters = bucketDopeQuery.parameters + indexReferenceDopeQueries.fold(emptyMap()) { indexReferenceParameters, field -> indexReferenceParameters + field.parameters }, diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/operator/FunctionOperator.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/operator/FunctionOperator.kt index b3c75203..4995ae66 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/operator/FunctionOperator.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/operator/FunctionOperator.kt @@ -2,21 +2,15 @@ package ch.ergon.dope.resolvable.operator import ch.ergon.dope.DopeQuery import ch.ergon.dope.resolvable.expression.unaliased.aggregator.AggregateQuantifier +import ch.ergon.dope.resolvable.formatListToQueryStringWithBrackets +import ch.ergon.dope.resolvable.formatStringListToQueryStringWithBrackets interface FunctionOperator { - fun toFunctionQueryString(symbol: String, vararg arguments: DopeQuery?) = arguments.filterNotNull().joinToString( - ", ", - prefix = "$symbol(", - postfix = ")", - ) { - it.queryString - } + fun toFunctionQueryString(symbol: String, vararg arguments: DopeQuery?) = + formatListToQueryStringWithBrackets(arguments.filterNotNull(), prefix = "$symbol(") - fun toFunctionQueryString(symbol: String, vararg arguments: String) = arguments.joinToString( - ", ", - prefix = "$symbol(", - postfix = ")", - ) + fun toFunctionQueryString(symbol: String, vararg arguments: String) = + formatStringListToQueryStringWithBrackets(arguments.toList(), prefix = "$symbol(") fun toFunctionQueryString(symbol: String, quantifier: AggregateQuantifier?, argument: String) = quantifier?.let { From 34047211f2548b20e5d21ebdff51dfd30a602211 Mon Sep 17 00:00:00 2001 From: Jan Sigrist Date: Fri, 23 Aug 2024 09:22:19 +0200 Subject: [PATCH 09/15] DOPE-242: renaming jvmName --- .../main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt index 55389f84..203aae6f 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt @@ -16,11 +16,11 @@ class UseKeysClass private constructor( private val bucket: Bucket, ) : Updatable { companion object { - @JvmName("selectSingleUseKeysClauseConstructor") + @JvmName("singleUseKeysClauseConstructor") fun UseKeys(key: TypeExpression, bucket: Bucket) = UseKeysClass(key, bucket) - @JvmName("selectMultipleUseKeysClauseConstructor") + @JvmName("multipleUseKeysClauseConstructor") fun UseKeys(keys: TypeExpression>, bucket: Bucket) = UseKeysClass(keys, bucket) } From 2c5da187d80b3aa000ed7495b5ab2c891c565abd Mon Sep 17 00:00:00 2001 From: Jan Sigrist Date: Tue, 27 Aug 2024 12:55:45 +0200 Subject: [PATCH 10/15] DOPE-242: add format function for index reference --- .../ch/ergon/dope/resolvable/QueryStringBuilder.kt | 11 +++++++++++ .../ch/ergon/dope/resolvable/fromable/UseIndex.kt | 14 ++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/QueryStringBuilder.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/QueryStringBuilder.kt index 8f20eae2..a4d29b18 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/QueryStringBuilder.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/QueryStringBuilder.kt @@ -28,3 +28,14 @@ fun formatStringListToQueryStringWithBrackets(dopeQueries: List, seperat fun formatListToQueryStringWithBrackets(dopeQueries: List, seperator: String = ", ", prefix: String = "(", postfix: String = ")") = dopeQueries.joinToString(seperator, prefix, postfix) { it.queryString } + +fun formatIndexToQueryString(indexName: String?, indexType: String?) = + buildString { + if (indexName != null) { + append("`$indexName`") + } + if (indexType != null) { + if (isNotEmpty()) append(" ") + append(indexType) + } + } diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt index a1d1ad1f..2a2633fa 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt @@ -2,6 +2,7 @@ package ch.ergon.dope.resolvable.fromable import ch.ergon.dope.DopeQuery import ch.ergon.dope.resolvable.Resolvable +import ch.ergon.dope.resolvable.formatIndexToQueryString import ch.ergon.dope.resolvable.formatListToQueryStringWithBrackets import ch.ergon.dope.resolvable.formatToQueryStringWithSymbol import ch.ergon.dope.resolvable.fromable.IndexType.USING_FTS @@ -18,18 +19,7 @@ class IndexReference( private val indexName: String? = null, private val indexType: IndexType? = null, ) : Resolvable { - override fun toDopeQuery(): DopeQuery { - val queryString = buildString { - if (indexName != null) { - append("`$indexName`") - } - if (indexType != null) { - if (isNotEmpty()) append(" ") - append(indexType.type) - } - } - return DopeQuery(queryString, emptyMap()) - } + override fun toDopeQuery() = DopeQuery(formatIndexToQueryString(indexName, indexType?.type), emptyMap()) } class UseIndex( From e6965fe13bf30092e26c79a819578304f2b90eb9 Mon Sep 17 00:00:00 2001 From: Jan Sigrist Date: Tue, 27 Aug 2024 13:31:13 +0200 Subject: [PATCH 11/15] DOPE-242: added interface structure --- .../main/kotlin/ch/ergon/dope/QueryBuilder.kt | 6 +- .../dope/resolvable/clause/ISelectClause.kt | 22 +++---- .../resolvable/clause/model/DeleteClause.kt | 6 +- .../resolvable/clause/model/JoinClause.kt | 62 +++++++++---------- .../ergon/dope/resolvable/fromable/Bucket.kt | 2 +- .../dope/resolvable/fromable/Fromable.kt | 6 +- .../dope/resolvable/fromable/UseIndex.kt | 2 +- .../ergon/dope/resolvable/fromable/UseKeys.kt | 2 +- .../dope/extension/clause/SelectClause.kt | 16 ++--- 9 files changed, 64 insertions(+), 60 deletions(-) diff --git a/core/src/main/kotlin/ch/ergon/dope/QueryBuilder.kt b/core/src/main/kotlin/ch/ergon/dope/QueryBuilder.kt index 49f8cb3c..eb923176 100644 --- a/core/src/main/kotlin/ch/ergon/dope/QueryBuilder.kt +++ b/core/src/main/kotlin/ch/ergon/dope/QueryBuilder.kt @@ -8,8 +8,8 @@ import ch.ergon.dope.resolvable.clause.model.UpdateClause import ch.ergon.dope.resolvable.expression.AsteriskExpression import ch.ergon.dope.resolvable.expression.Expression import ch.ergon.dope.resolvable.expression.SingleExpression +import ch.ergon.dope.resolvable.fromable.Deletable import ch.ergon.dope.resolvable.fromable.Fromable -import ch.ergon.dope.resolvable.fromable.IBucket import ch.ergon.dope.resolvable.fromable.Updatable class QueryBuilder { @@ -23,7 +23,7 @@ class QueryBuilder { fun selectFrom(fromable: Fromable) = SelectClause(AsteriskExpression()).from(fromable) - fun deleteFrom(bucket: IBucket) = DeleteClause(bucket) + fun deleteFrom(deletable: Deletable) = DeleteClause(deletable) - fun update(bucket: Updatable) = UpdateClause(bucket) + fun update(updatable: Updatable) = UpdateClause(updatable) } diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/ISelectClause.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/ISelectClause.kt index 93bbec4a..f2b4b424 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/ISelectClause.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/ISelectClause.kt @@ -21,7 +21,7 @@ import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType import ch.ergon.dope.resolvable.fromable.AliasedSelectClause import ch.ergon.dope.resolvable.fromable.Bucket import ch.ergon.dope.resolvable.fromable.Fromable -import ch.ergon.dope.resolvable.fromable.IBucket +import ch.ergon.dope.resolvable.fromable.Joinable import ch.ergon.dope.validtype.ArrayType import ch.ergon.dope.validtype.BooleanType import ch.ergon.dope.validtype.NumberType @@ -54,19 +54,19 @@ interface ISelectFromClause : ISelectWhereClause { } interface ISelectJoinClause : ISelectFromClause { - fun join(bucket: IBucket, onCondition: TypeExpression) = StandardJoinClause(bucket, onCondition, this) - fun join(bucket: IBucket, onKeys: Field) = StandardJoinClause(bucket, onKeys, this) - fun join(bucket: IBucket, onKey: Field, forBucket: Bucket) = StandardJoinClause(bucket, onKey, forBucket, this) + fun join(joinable: Joinable, onCondition: TypeExpression) = StandardJoinClause(joinable, onCondition, this) + fun join(joinable: Joinable, onKeys: Field) = StandardJoinClause(joinable, onKeys, this) + fun join(joinable: Joinable, onKey: Field, forBucket: Bucket) = StandardJoinClause(joinable, onKey, forBucket, this) - fun innerJoin(bucket: IBucket, onCondition: TypeExpression) = InnerJoinClause(bucket, onCondition, this) - fun innerJoin(bucket: IBucket, onKeys: Field) = InnerJoinClause(bucket, onKeys, this) - fun innerJoin(bucket: IBucket, onKey: Field, forBucket: Bucket) = InnerJoinClause(bucket, onKey, forBucket, this) + fun innerJoin(joinable: Joinable, onCondition: TypeExpression) = InnerJoinClause(joinable, onCondition, this) + fun innerJoin(joinable: Joinable, onKeys: Field) = InnerJoinClause(joinable, onKeys, this) + fun innerJoin(joinable: Joinable, onKey: Field, forBucket: Bucket) = InnerJoinClause(joinable, onKey, forBucket, this) - fun leftJoin(bucket: IBucket, onCondition: TypeExpression) = LeftJoinClause(bucket, onCondition, this) - fun leftJoin(bucket: IBucket, onKeys: Field) = LeftJoinClause(bucket, onKeys, this) - fun leftJoin(bucket: IBucket, onKey: Field, forBucket: Bucket) = LeftJoinClause(bucket, onKey, forBucket, this) + fun leftJoin(joinable: Joinable, onCondition: TypeExpression) = LeftJoinClause(joinable, onCondition, this) + fun leftJoin(joinable: Joinable, onKeys: Field) = LeftJoinClause(joinable, onKeys, this) + fun leftJoin(joinable: Joinable, onKey: Field, forBucket: Bucket) = LeftJoinClause(joinable, onKey, forBucket, this) - fun rightJoin(bucket: IBucket, onCondition: TypeExpression) = RightJoinClause(bucket, onCondition, this) + fun rightJoin(joinable: Joinable, onCondition: TypeExpression) = RightJoinClause(joinable, onCondition, this) fun alias(alias: String) = AliasedSelectClause(alias, this) } diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/DeleteClause.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/DeleteClause.kt index d538d6a5..fe9feb42 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/DeleteClause.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/DeleteClause.kt @@ -2,11 +2,11 @@ package ch.ergon.dope.resolvable.clause.model import ch.ergon.dope.DopeQuery import ch.ergon.dope.resolvable.clause.IDeleteClause -import ch.ergon.dope.resolvable.fromable.IBucket +import ch.ergon.dope.resolvable.fromable.Deletable -class DeleteClause(private val bucket: IBucket) : IDeleteClause { +class DeleteClause(private val deletable: Deletable) : IDeleteClause { override fun toDopeQuery(): DopeQuery { - val bucketDopeQuery = bucket.toDopeQuery() + val bucketDopeQuery = deletable.toDopeQuery() return DopeQuery( queryString = "DELETE FROM ${bucketDopeQuery.queryString}", parameters = bucketDopeQuery.parameters, diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/JoinClause.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/JoinClause.kt index 14236321..35af61a5 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/JoinClause.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/JoinClause.kt @@ -13,7 +13,7 @@ import ch.ergon.dope.resolvable.clause.model.OnType.ON_KEY_FOR import ch.ergon.dope.resolvable.expression.TypeExpression import ch.ergon.dope.resolvable.expression.unaliased.type.Field import ch.ergon.dope.resolvable.fromable.Bucket -import ch.ergon.dope.resolvable.fromable.IBucket +import ch.ergon.dope.resolvable.fromable.Joinable import ch.ergon.dope.validtype.BooleanType import ch.ergon.dope.validtype.ValidType @@ -32,7 +32,7 @@ private enum class OnType { sealed class SelectJoinClause : ISelectJoinClause { private val joinType: JoinType - private val bucket: IBucket + private val joinable: Joinable private val onCondition: TypeExpression? private val onKeys: Field? private val onKey: Field? @@ -40,10 +40,10 @@ sealed class SelectJoinClause : ISelectJoinClause { private val parentClause: ISelectFromClause private val onType: OnType - constructor(joinType: JoinType, bucket: IBucket, onCondition: TypeExpression, parentClause: ISelectFromClause) { + constructor(joinType: JoinType, joinable: Joinable, onCondition: TypeExpression, parentClause: ISelectFromClause) { this.onType = ON this.joinType = joinType - this.bucket = bucket + this.joinable = joinable this.onCondition = onCondition this.parentClause = parentClause this.onKeys = null @@ -51,10 +51,10 @@ sealed class SelectJoinClause : ISelectJoinClause { this.forBucket = null } - constructor(joinType: JoinType, bucket: IBucket, onKeys: Field, parentClause: ISelectFromClause) { + constructor(joinType: JoinType, joinable: Joinable, onKeys: Field, parentClause: ISelectFromClause) { this.onType = ON_KEYS this.joinType = joinType - this.bucket = bucket + this.joinable = joinable this.onKeys = onKeys this.parentClause = parentClause this.onCondition = null @@ -62,10 +62,10 @@ sealed class SelectJoinClause : ISelectJoinClause { this.forBucket = null } - constructor(joinType: JoinType, bucket: IBucket, onKey: Field, forBucket: Bucket, parentClause: ISelectFromClause) { + constructor(joinType: JoinType, joinable: Joinable, onKey: Field, forBucket: Bucket, parentClause: ISelectFromClause) { this.onType = ON_KEY_FOR this.joinType = joinType - this.bucket = bucket + this.joinable = joinable this.onKey = onKey this.forBucket = forBucket this.parentClause = parentClause @@ -75,9 +75,9 @@ sealed class SelectJoinClause : ISelectJoinClause { override fun toDopeQuery(): DopeQuery { val parentDopeQuery = parentClause.toDopeQuery() - val bucketDopeQuery = bucket.toDopeQuery() - val joinQueryString = "${parentDopeQuery.queryString} ${joinType.type} ${bucketDopeQuery.queryString}" - val joinParameters = parentDopeQuery.parameters + bucketDopeQuery.parameters + val joinableDopeQuery = joinable.toDopeQuery() + val joinQueryString = "${parentDopeQuery.queryString} ${joinType.type} ${joinableDopeQuery.queryString}" + val joinParameters = parentDopeQuery.parameters + joinableDopeQuery.parameters return when (onType) { ON -> { @@ -110,37 +110,37 @@ sealed class SelectJoinClause : ISelectJoinClause { } class StandardJoinClause : SelectJoinClause { - constructor(bucket: IBucket, onCondition: TypeExpression, parentClause: ISelectFromClause) : - super(JOIN, bucket, onCondition, parentClause) + constructor(joinable: Joinable, onCondition: TypeExpression, parentClause: ISelectFromClause) : + super(JOIN, joinable, onCondition, parentClause) - constructor(bucket: IBucket, onKeys: Field, parentClause: ISelectFromClause) : - super(JOIN, bucket, onKeys, parentClause) + constructor(joinable: Joinable, onKeys: Field, parentClause: ISelectFromClause) : + super(JOIN, joinable, onKeys, parentClause) - constructor(bucket: IBucket, onKey: Field, forBucket: Bucket, parentClause: ISelectFromClause) : - super(JOIN, bucket, onKey, forBucket, parentClause) + constructor(joinable: Joinable, onKey: Field, forBucket: Bucket, parentClause: ISelectFromClause) : + super(JOIN, joinable, onKey, forBucket, parentClause) } class LeftJoinClause : SelectJoinClause { - constructor(bucket: IBucket, onCondition: TypeExpression, parentClause: ISelectFromClause) : - super(LEFT_JOIN, bucket, onCondition, parentClause) + constructor(joinable: Joinable, onCondition: TypeExpression, parentClause: ISelectFromClause) : + super(LEFT_JOIN, joinable, onCondition, parentClause) - constructor(bucket: IBucket, onKeys: Field, parentClause: ISelectFromClause) : - super(LEFT_JOIN, bucket, onKeys, parentClause) + constructor(joinable: Joinable, onKeys: Field, parentClause: ISelectFromClause) : + super(LEFT_JOIN, joinable, onKeys, parentClause) - constructor(bucket: IBucket, onKey: Field, forBucket: Bucket, parentClause: ISelectFromClause) : - super(LEFT_JOIN, bucket, onKey, forBucket, parentClause) + constructor(joinable: Joinable, onKey: Field, forBucket: Bucket, parentClause: ISelectFromClause) : + super(LEFT_JOIN, joinable, onKey, forBucket, parentClause) } class InnerJoinClause : SelectJoinClause { - constructor(bucket: IBucket, onCondition: TypeExpression, parentClause: ISelectFromClause) : - super(INNER_JOIN, bucket, onCondition, parentClause) + constructor(joinable: Joinable, onCondition: TypeExpression, parentClause: ISelectFromClause) : + super(INNER_JOIN, joinable, onCondition, parentClause) - constructor(bucket: IBucket, onKeys: Field, parentClause: ISelectFromClause) : - super(INNER_JOIN, bucket, onKeys, parentClause) + constructor(joinable: Joinable, onKeys: Field, parentClause: ISelectFromClause) : + super(INNER_JOIN, joinable, onKeys, parentClause) - constructor(bucket: IBucket, onKey: Field, forBucket: Bucket, parentClause: ISelectFromClause) : - super(INNER_JOIN, bucket, onKey, forBucket, parentClause) + constructor(joinable: Joinable, onKey: Field, forBucket: Bucket, parentClause: ISelectFromClause) : + super(INNER_JOIN, joinable, onKey, forBucket, parentClause) } -class RightJoinClause(bucket: IBucket, onCondition: TypeExpression, parentClause: ISelectFromClause) : - SelectJoinClause(RIGHT_JOIN, bucket, onCondition, parentClause) +class RightJoinClause(joinable: Joinable, onCondition: TypeExpression, parentClause: ISelectFromClause) : + SelectJoinClause(RIGHT_JOIN, joinable, onCondition, parentClause) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Bucket.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Bucket.kt index ef62f8c6..150f94da 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Bucket.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Bucket.kt @@ -3,7 +3,7 @@ package ch.ergon.dope.resolvable.fromable import ch.ergon.dope.DopeQuery import ch.ergon.dope.resolvable.expression.AsteriskExpression -sealed class Bucket(open val name: String) : Updatable { +sealed class Bucket(open val name: String) : Fromable, Joinable, Deletable, Updatable { override fun toDopeQuery() = DopeQuery("`$name`", emptyMap()) } diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Fromable.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Fromable.kt index 460f8a0a..0804a053 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Fromable.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/Fromable.kt @@ -4,6 +4,8 @@ import ch.ergon.dope.resolvable.Resolvable interface Fromable : Resolvable -interface IBucket : Fromable +interface Joinable : Resolvable -interface Updatable : IBucket +interface Deletable : Resolvable + +interface Updatable : Resolvable diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt index 2a2633fa..ed2e77e0 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt @@ -25,7 +25,7 @@ class IndexReference( class UseIndex( val bucket: Bucket, vararg val indexReference: IndexReference, -) : IBucket { +) : Joinable, Deletable, Fromable { override fun toDopeQuery(): DopeQuery { val bucketDopeQuery = bucket.toDopeQuery() val indexReferenceDopeQueries = indexReference.map { it.toDopeQuery() } diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt index 203aae6f..e6c528c9 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt @@ -14,7 +14,7 @@ private const val USE_KEYS = "USE KEYS" class UseKeysClass private constructor( private val useKeys: TypeExpression, private val bucket: Bucket, -) : Updatable { +) : Joinable, Deletable, Updatable, Fromable { companion object { @JvmName("singleUseKeysClauseConstructor") fun UseKeys(key: TypeExpression, bucket: Bucket) = diff --git a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/SelectClause.kt b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/SelectClause.kt index 56117765..7972c370 100644 --- a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/SelectClause.kt +++ b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/SelectClause.kt @@ -9,7 +9,7 @@ import ch.ergon.dope.resolvable.clause.ISelectUnnestClause import ch.ergon.dope.resolvable.clause.ISelectWhereClause import ch.ergon.dope.resolvable.clause.model.OrderByType import ch.ergon.dope.resolvable.fromable.Bucket -import ch.ergon.dope.resolvable.fromable.IBucket +import ch.ergon.dope.resolvable.fromable.Joinable import ch.ergon.dope.toDopeType import com.schwarz.crystalapi.schema.CMField import com.schwarz.crystalapi.schema.CMList @@ -29,14 +29,16 @@ fun ISelectWhereClause.groupBy(field: CMType, vararg fields: CMType) = fun ISelectFromClause.where(whereExpression: CMField) = where(whereExpression.toDopeType()) -fun ISelectJoinClause.join(bucket: IBucket, onKeys: CMField) = join(bucket, onKeys.toDopeType()) -fun ISelectJoinClause.join(bucket: IBucket, onKey: CMField, forBucket: Bucket) = join(bucket, onKey.toDopeType(), forBucket) +fun ISelectJoinClause.join(joinable: Joinable, onKeys: CMField) = join(joinable, onKeys.toDopeType()) +fun ISelectJoinClause.join(joinable: Joinable, onKey: CMField, forBucket: Bucket) = join(joinable, onKey.toDopeType(), forBucket) -fun ISelectJoinClause.innerJoin(bucket: IBucket, onKeys: CMField) = innerJoin(bucket, onKeys.toDopeType()) -fun ISelectJoinClause.innerJoin(bucket: IBucket, onKey: CMField, forBucket: Bucket) = innerJoin(bucket, onKey.toDopeType(), forBucket) +fun ISelectJoinClause.innerJoin(joinable: Joinable, onKeys: CMField) = innerJoin(joinable, onKeys.toDopeType()) +fun ISelectJoinClause.innerJoin(joinable: Joinable, onKey: CMField, forBucket: Bucket) = + innerJoin(joinable, onKey.toDopeType(), forBucket) -fun ISelectJoinClause.leftJoin(bucket: IBucket, onKeys: CMField) = leftJoin(bucket, onKeys.toDopeType()) -fun ISelectJoinClause.leftJoin(bucket: IBucket, onKey: CMField, forBucket: Bucket) = leftJoin(bucket, onKey.toDopeType(), forBucket) +fun ISelectJoinClause.leftJoin(joinable: Joinable, onKeys: CMField) = leftJoin(joinable, onKeys.toDopeType()) +fun ISelectJoinClause.leftJoin(joinable: Joinable, onKey: CMField, forBucket: Bucket) = + leftJoin(joinable, onKey.toDopeType(), forBucket) @JvmName("unnestString") fun ISelectUnnestClause.unnest(arrayField: CMList) = unnest(arrayField.toDopeType()) From e948e31ef3507d4a9d9ddf655e8b9cd31057316b Mon Sep 17 00:00:00 2001 From: Jan Sigrist Date: Thu, 29 Aug 2024 08:48:48 +0200 Subject: [PATCH 12/15] DOPE-242: simplified string builder --- .../ch/ergon/dope/resolvable/QueryStringBuilder.kt | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/QueryStringBuilder.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/QueryStringBuilder.kt index a4d29b18..cad6dc5d 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/QueryStringBuilder.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/QueryStringBuilder.kt @@ -30,12 +30,4 @@ fun formatListToQueryStringWithBrackets(dopeQueries: List, seperator: dopeQueries.joinToString(seperator, prefix, postfix) { it.queryString } fun formatIndexToQueryString(indexName: String?, indexType: String?) = - buildString { - if (indexName != null) { - append("`$indexName`") - } - if (indexType != null) { - if (isNotEmpty()) append(" ") - append(indexType) - } - } + listOfNotNull(indexName?.let { "`$it`" }, indexType).joinToString(separator = " ") From bb34382bb85211e4525f2afe8b6e3f8a3c98563b Mon Sep 17 00:00:00 2001 From: Jan Sigrist Date: Thu, 29 Aug 2024 08:50:08 +0200 Subject: [PATCH 13/15] DOPE-242: added named parameters --- .../main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt index 514b31c9..f78c039e 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseIndex.kt @@ -34,7 +34,7 @@ class UseIndex( queryString = formatToQueryStringWithSymbol( bucketDopeQuery.queryString, USE_INDEX, - formatListToQueryStringWithBrackets(indexReferenceDopeQueries, ", ", "(", ")"), + formatListToQueryStringWithBrackets(indexReferenceDopeQueries, seperator = ", ", prefix = "(", postfix = ")"), ), parameters = bucketDopeQuery.parameters + indexReferenceDopeQueries.fold(emptyMap()) { indexReferenceParameters, field -> indexReferenceParameters + field.parameters From 13aacb355d7ce4e2f24229a0cfee1e5cb7d5bb85 Mon Sep 17 00:00:00 2001 From: Jan Sigrist Date: Thu, 29 Aug 2024 08:53:02 +0200 Subject: [PATCH 14/15] DOPE-242: remove unnecessary print --- .../src/test/kotlin/ch/ergon/dope/resolvable/fromable/UseTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/test/kotlin/ch/ergon/dope/resolvable/fromable/UseTest.kt b/core/src/test/kotlin/ch/ergon/dope/resolvable/fromable/UseTest.kt index d80e50ac..9938debb 100644 --- a/core/src/test/kotlin/ch/ergon/dope/resolvable/fromable/UseTest.kt +++ b/core/src/test/kotlin/ch/ergon/dope/resolvable/fromable/UseTest.kt @@ -148,7 +148,6 @@ class UseTest : ManagerDependentTest { ) val actual = bucket.useGsiIndex(indexName).useIndex(indexName2).useFtsIndex().useGsiIndex() - println(actual.toDopeQuery(manager)) assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager)) } From 7ace9943fa6bdeca705e2ab50561a93dc3a374b7 Mon Sep 17 00:00:00 2001 From: Jan Sigrist Date: Wed, 18 Sep 2024 09:09:41 +0200 Subject: [PATCH 15/15] DOPE-242: fix merge --- .../ch/ergon/dope/resolvable/clause/model/UpdateClause.kt | 6 +++--- .../kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt | 5 ++++- .../kotlin/ch/ergon/dope/extension/clause/UpdateClause.kt | 6 +++--- .../main/kotlin/ch/ergon/dope/extension/fromable/Use.kt | 8 ++++---- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UpdateClause.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UpdateClause.kt index f764d156..83542e4f 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UpdateClause.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UpdateClause.kt @@ -8,13 +8,13 @@ import ch.ergon.dope.resolvable.fromable.Updatable class UpdateClause(private val updatable: Updatable) : IUpdateClause { override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { - val resolvableDopeQuery = when (updatable) { + val updatableDopeQuery = when (updatable) { is AliasedBucket -> updatable.asBucketDefinition().toDopeQuery(manager) else -> updatable.toDopeQuery(manager) } return DopeQuery( - queryString = "UPDATE ${resolvableDopeQuery.queryString}", - parameters = resolvableDopeQuery.parameters, + queryString = "UPDATE ${updatableDopeQuery.queryString}", + parameters = updatableDopeQuery.parameters, ) } } diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt index 22f1d414..8d7ce221 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/fromable/UseKeys.kt @@ -27,7 +27,10 @@ class UseKeysClass private constructor( } override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { - val bucketDopeQuery = bucket.toDopeQuery(manager) + val bucketDopeQuery = when (bucket) { + is AliasedBucket -> bucket.asBucketDefinition().toDopeQuery(manager) + else -> bucket.toDopeQuery(manager) + } val keysDopeQuery = useKeys.toDopeQuery(manager) return DopeQuery( queryString = formatToQueryStringWithSymbol(bucketDopeQuery.queryString, USE_KEYS, keysDopeQuery.queryString), diff --git a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/UpdateClause.kt b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/UpdateClause.kt index 3d4d0051..3853f42c 100644 --- a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/UpdateClause.kt +++ b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/clause/UpdateClause.kt @@ -189,7 +189,7 @@ fun SetClause.set( ) = set(field.toDopeType(), value) @JvmName("setCMConverterNumberFieldToNumber") -fun IUpdateUseKeysClause.set( +fun IUpdateClause.set( field: CMConverterField, value: Convertable, ) = set(field.toDopeType(), field.toDopeType(value)) @@ -213,7 +213,7 @@ fun SetClause.set( ) = set(field.toDopeType(), value) @JvmName("setCMConverterStringFieldToNumber") -fun IUpdateUseKeysClause.set( +fun IUpdateClause.set( field: CMConverterField, value: Convertable, ) = set(field.toDopeType(), field.toDopeType(value)) @@ -237,7 +237,7 @@ fun SetClause.set( ) = set(field.toDopeType(), value) @JvmName("setCMConverterBooleanFieldToNumber") -fun IUpdateUseKeysClause.set( +fun IUpdateClause.set( field: CMConverterField, value: Convertable, ) = set(field.toDopeType(), field.toDopeType(value)) diff --git a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/fromable/Use.kt b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/fromable/Use.kt index 9ecb3b3c..d70bd899 100644 --- a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/fromable/Use.kt +++ b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/fromable/Use.kt @@ -3,9 +3,9 @@ package ch.ergon.dope.extension.fromable import ch.ergon.dope.resolvable.fromable.Bucket import ch.ergon.dope.resolvable.fromable.useKeys import ch.ergon.dope.toDopeType -import com.schwarz.crystalapi.schema.CMField -import com.schwarz.crystalapi.schema.CMList +import com.schwarz.crystalapi.schema.CMJsonField +import com.schwarz.crystalapi.schema.CMJsonList -fun Bucket.useKeys(useKeys: CMField) = useKeys(useKeys.toDopeType()) +fun Bucket.useKeys(useKeys: CMJsonField) = useKeys(useKeys.toDopeType()) -fun Bucket.useKeys(useKeys: CMList) = useKeys(useKeys.toDopeType()) +fun Bucket.useKeys(useKeys: CMJsonList) = useKeys(useKeys.toDopeType())