diff --git a/core/src/integrationTest/kotlin/ch/ergon/dope/clauses/DeleteIntegrationTest.kt b/core/src/integrationTest/kotlin/ch/ergon/dope/clauses/DeleteIntegrationTest.kt index aa2983de..8e361045 100644 --- a/core/src/integrationTest/kotlin/ch/ergon/dope/clauses/DeleteIntegrationTest.kt +++ b/core/src/integrationTest/kotlin/ch/ergon/dope/clauses/DeleteIntegrationTest.kt @@ -7,6 +7,7 @@ import ch.ergon.dope.integrationTest.TestCouchbaseDatabase.resetDatabase import ch.ergon.dope.integrationTest.TestCouchbaseDatabase.testBucket import ch.ergon.dope.integrationTest.toMapValues import ch.ergon.dope.integrationTest.tryUntil +import ch.ergon.dope.resolvable.expression.asterisk import ch.ergon.dope.resolvable.expression.unaliased.type.arithmetic.add import ch.ergon.dope.resolvable.expression.unaliased.type.relational.isEqualTo import ch.ergon.dope.resolvable.fromable.useKeys @@ -28,7 +29,9 @@ class DeleteIntegrationTest : BaseIntegrationTest() { ) .returning( idField, - ).build() + asterisk(), + ) + .build() tryUntil { val queryResult = queryWithoutParameters(dopeQuery) diff --git a/core/src/integrationTest/kotlin/ch/ergon/dope/clauses/SelectQueryIntegrationTest.kt b/core/src/integrationTest/kotlin/ch/ergon/dope/clauses/SelectQueryIntegrationTest.kt index a02f4a50..d253a953 100644 --- a/core/src/integrationTest/kotlin/ch/ergon/dope/clauses/SelectQueryIntegrationTest.kt +++ b/core/src/integrationTest/kotlin/ch/ergon/dope/clauses/SelectQueryIntegrationTest.kt @@ -5,6 +5,7 @@ import ch.ergon.dope.integrationTest.BaseIntegrationTest import ch.ergon.dope.integrationTest.TestCouchbaseDatabase.idField import ch.ergon.dope.integrationTest.TestCouchbaseDatabase.isActiveField import ch.ergon.dope.integrationTest.TestCouchbaseDatabase.nameField +import ch.ergon.dope.integrationTest.TestCouchbaseDatabase.quantitiesField import ch.ergon.dope.integrationTest.TestCouchbaseDatabase.testBucket import ch.ergon.dope.integrationTest.TestCouchbaseDatabase.typeField import ch.ergon.dope.integrationTest.toMapValues @@ -12,8 +13,10 @@ import ch.ergon.dope.integrationTest.toRawValues import ch.ergon.dope.resolvable.clause.model.setoperator.intersect import ch.ergon.dope.resolvable.expression.alias import ch.ergon.dope.resolvable.expression.unaliased.type.asParameter +import ch.ergon.dope.resolvable.expression.unaliased.type.collection.any import ch.ergon.dope.resolvable.expression.unaliased.type.logical.and import ch.ergon.dope.resolvable.expression.unaliased.type.relational.isEqualTo +import ch.ergon.dope.resolvable.expression.unaliased.type.relational.isGreaterOrEqualThan import ch.ergon.dope.resolvable.expression.unaliased.type.relational.isGreaterThan import ch.ergon.dope.resolvable.expression.unaliased.type.relational.isLessThan import ch.ergon.dope.resolvable.expression.unaliased.type.relational.isNull @@ -228,4 +231,26 @@ class SelectQueryIntegrationTest : BaseIntegrationTest() { assertEquals(1, result["positionalParameter"]) } + + @Test + fun `select from subquery`() { + val create = QueryBuilder() + val subQuery = create + .selectRaw(quantitiesField) + .from(testBucket) + .where(typeField.isEqualTo("order")) + .limit(1) + .alias("subQuery") + val dopeQuery = create + .select(subQuery) + .from(subQuery) + .where( + subQuery.any { it.isGreaterOrEqualThan(1) }, + ).build() + + val queryResult = queryWithoutParameters(dopeQuery) + val result = queryResult.toMapValues() + + assertEquals(listOf(1, 2, 3), result["subQuery"]) + } } diff --git a/core/src/integrationTest/kotlin/ch/ergon/dope/clauses/UpdateIntegrationTest.kt b/core/src/integrationTest/kotlin/ch/ergon/dope/clauses/UpdateIntegrationTest.kt index 725bf8d1..90808305 100644 --- a/core/src/integrationTest/kotlin/ch/ergon/dope/clauses/UpdateIntegrationTest.kt +++ b/core/src/integrationTest/kotlin/ch/ergon/dope/clauses/UpdateIntegrationTest.kt @@ -38,7 +38,8 @@ class UpdateIntegrationTest : BaseIntegrationTest() { .returning( newField, nameField, - ).build() + ) + .build() tryUntil { val queryResult = queryWithoutParameters(dopeQuery) diff --git a/core/src/integrationTest/kotlin/ch/ergon/dope/functions/AggregateFunctionsIntegrationTest.kt b/core/src/integrationTest/kotlin/ch/ergon/dope/functions/AggregateFunctionsIntegrationTest.kt index 49a92dee..dba8ca54 100644 --- a/core/src/integrationTest/kotlin/ch/ergon/dope/functions/AggregateFunctionsIntegrationTest.kt +++ b/core/src/integrationTest/kotlin/ch/ergon/dope/functions/AggregateFunctionsIntegrationTest.kt @@ -9,8 +9,8 @@ import ch.ergon.dope.integrationTest.TestCouchbaseDatabase.testBucket import ch.ergon.dope.integrationTest.TestCouchbaseDatabase.typeField import ch.ergon.dope.integrationTest.toMapValues import ch.ergon.dope.integrationTest.tryUntil -import ch.ergon.dope.resolvable.expression.alias import ch.ergon.dope.resolvable.expression.unaliased.aggregator.AggregateQuantifier.DISTINCT +import ch.ergon.dope.resolvable.expression.unaliased.aggregator.alias import ch.ergon.dope.resolvable.expression.unaliased.aggregator.arrayAggregate import ch.ergon.dope.resolvable.expression.unaliased.aggregator.countAsterisk import ch.ergon.dope.resolvable.expression.unaliased.aggregator.max diff --git a/core/src/integrationTest/kotlin/ch/ergon/dope/integrationTest/TestCouchbaseDatabase.kt b/core/src/integrationTest/kotlin/ch/ergon/dope/integrationTest/TestCouchbaseDatabase.kt index e781377e..ee9f0146 100644 --- a/core/src/integrationTest/kotlin/ch/ergon/dope/integrationTest/TestCouchbaseDatabase.kt +++ b/core/src/integrationTest/kotlin/ch/ergon/dope/integrationTest/TestCouchbaseDatabase.kt @@ -4,6 +4,7 @@ import ch.ergon.dope.integrationTest.TestCouchbaseDatabase.testBucket import ch.ergon.dope.resolvable.expression.unaliased.type.Field import ch.ergon.dope.resolvable.fromable.Bucket import ch.ergon.dope.resolvable.fromable.UnaliasedBucket +import ch.ergon.dope.validtype.ArrayType import ch.ergon.dope.validtype.BooleanType import ch.ergon.dope.validtype.NumberType import ch.ergon.dope.validtype.StringType @@ -31,6 +32,7 @@ object TestCouchbaseDatabase { val isActiveField = Field("isActive", testBucket.name) val orderNumberField = Field("orderNumber", testBucket.name) val deliveryDateField = Field("deliveryDate", testBucket.name) + val quantitiesField = Field>("quantities", testBucket.name) init { initContainer() @@ -87,6 +89,7 @@ object TestCouchbaseDatabase { "client" to "client:$i", "employee" to "employee:$i", "deliveryDate" to null, + "quantities" to listOf(1, 2, 3), ), ) } diff --git a/core/src/main/kotlin/ch/ergon/dope/QueryBuilder.kt b/core/src/main/kotlin/ch/ergon/dope/QueryBuilder.kt index e979b368..8ac9ea7a 100644 --- a/core/src/main/kotlin/ch/ergon/dope/QueryBuilder.kt +++ b/core/src/main/kotlin/ch/ergon/dope/QueryBuilder.kt @@ -5,24 +5,24 @@ import ch.ergon.dope.resolvable.clause.model.SelectClause import ch.ergon.dope.resolvable.clause.model.SelectDistinctClause import ch.ergon.dope.resolvable.clause.model.SelectRawClause 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.expression.Asterisk import ch.ergon.dope.resolvable.fromable.Deletable import ch.ergon.dope.resolvable.fromable.Fromable +import ch.ergon.dope.resolvable.fromable.RawSelectable +import ch.ergon.dope.resolvable.fromable.Selectable import ch.ergon.dope.resolvable.fromable.Updatable import ch.ergon.dope.validtype.ValidType class QueryBuilder { - fun select(expression: Expression, vararg expressions: Expression) = SelectClause(expression, *expressions) + fun select(expression: Selectable, vararg expressions: Selectable) = SelectClause(expression, *expressions) - fun selectAsterisk() = SelectClause(AsteriskExpression()) + fun selectAsterisk() = SelectClause(Asterisk()) - fun selectDistinct(expression: Expression, vararg expressions: Expression) = SelectDistinctClause(expression, *expressions) + fun selectDistinct(expression: Selectable, vararg expressions: Selectable) = SelectDistinctClause(expression, *expressions) - fun selectRaw(expression: SingleExpression) = SelectRawClause(expression) + fun selectRaw(expression: RawSelectable) = SelectRawClause(expression) - fun selectFrom(fromable: Fromable) = SelectClause(AsteriskExpression()).from(fromable) + fun selectFrom(fromable: Fromable) = SelectClause(Asterisk()).from(fromable) fun deleteFrom(deletable: Deletable) = DeleteClause(deletable) 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 fa1d83e5..11f55eb6 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,10 +3,17 @@ 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.DeleteReturningSingleClause import ch.ergon.dope.resolvable.clause.model.DeleteWhereClause +import ch.ergon.dope.resolvable.clause.model.ReturningType.ELEMENT +import ch.ergon.dope.resolvable.clause.model.ReturningType.RAW +import ch.ergon.dope.resolvable.clause.model.ReturningType.VALUE +import ch.ergon.dope.resolvable.expression.SingleExpression import ch.ergon.dope.resolvable.expression.TypeExpression -import ch.ergon.dope.resolvable.expression.unaliased.type.Field +import ch.ergon.dope.resolvable.expression.asterisk import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType +import ch.ergon.dope.resolvable.fromable.Bucket +import ch.ergon.dope.resolvable.fromable.Returnable import ch.ergon.dope.validtype.BooleanType import ch.ergon.dope.validtype.NumberType import ch.ergon.dope.validtype.ValidType @@ -14,7 +21,16 @@ import ch.ergon.dope.validtype.ValidType interface IDeleteReturningClause : Clause interface IDeleteOffsetClause : IDeleteReturningClause { - fun returning(field: Field, vararg fields: Field) = DeleteReturningClause(field, *fields, parentClause = this) + fun returning(returningExpression: Returnable, vararg additionalReturningExpressions: Returnable) = + DeleteReturningClause(returningExpression, *additionalReturningExpressions, parentClause = this) + fun returningAsterisk(bucket: Bucket? = null) = DeleteReturningClause(asterisk(bucket), parentClause = this) + + fun returningRaw(returningExpression: SingleExpression) = + DeleteReturningSingleClause(returningExpression, returningType = RAW, parentClause = this) + fun returningValue(returningExpression: SingleExpression) = + DeleteReturningSingleClause(returningExpression, returningType = VALUE, parentClause = this) + fun returningElement(returningExpression: SingleExpression) = + DeleteReturningSingleClause(returningExpression, returningType = ELEMENT, parentClause = this) } interface IDeleteLimitClause : IDeleteOffsetClause { 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 a855b898..b2405c5b 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 @@ -18,7 +18,7 @@ import ch.ergon.dope.resolvable.clause.model.StandardJoinClause import ch.ergon.dope.resolvable.clause.model.UnnestClause import ch.ergon.dope.resolvable.clause.model.joinHint.HashOrNestedLoopHint import ch.ergon.dope.resolvable.clause.model.joinHint.KeysOrIndexHint -import ch.ergon.dope.resolvable.expression.AliasedExpression +import ch.ergon.dope.resolvable.expression.AliasedTypeExpression 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 @@ -140,7 +140,7 @@ interface ISelectJoinClause : ISelectLetClause { interface ISelectUnnestClause : ISelectJoinClause { fun unnest(arrayField: Field>) = UnnestClause(arrayField, this) - fun unnest(aliasedArrayExpression: AliasedExpression>) = + fun unnest(aliasedArrayExpression: AliasedTypeExpression>) = AliasedUnnestClause(aliasedArrayExpression, 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 dadaffc3..c04680f7 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 @@ -1,14 +1,21 @@ package ch.ergon.dope.resolvable.clause +import ch.ergon.dope.resolvable.clause.model.ReturningType.ELEMENT +import ch.ergon.dope.resolvable.clause.model.ReturningType.RAW +import ch.ergon.dope.resolvable.clause.model.ReturningType.VALUE 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.UpdateReturningSingleClause import ch.ergon.dope.resolvable.clause.model.UpdateWhereClause import ch.ergon.dope.resolvable.clause.model.to +import ch.ergon.dope.resolvable.expression.Asterisk 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.resolvable.fromable.Bucket +import ch.ergon.dope.resolvable.fromable.Returnable import ch.ergon.dope.validtype.BooleanType import ch.ergon.dope.validtype.NumberType import ch.ergon.dope.validtype.StringType @@ -17,8 +24,16 @@ import ch.ergon.dope.validtype.ValidType interface IUpdateReturningClause : Clause interface IUpdateLimitClause : IUpdateReturningClause { - fun returning(field: Field, vararg fields: Field) = - UpdateReturningClause(field, *fields, parentClause = this) + fun returning(returningExpression: Returnable, vararg additionalReturningExpressions: Returnable) = + UpdateReturningClause(returningExpression, *additionalReturningExpressions, parentClause = this) + fun returningAsterisk(bucket: Bucket? = null) = UpdateReturningClause(Asterisk(bucket), parentClause = this) + + fun returningRaw(returningExpression: TypeExpression) = + UpdateReturningSingleClause(returningExpression, returningType = RAW, parentClause = this) + fun returningValue(returningExpression: TypeExpression) = + UpdateReturningSingleClause(returningExpression, returningType = VALUE, parentClause = this) + fun returningElement(returningExpression: TypeExpression) = + UpdateReturningSingleClause(returningExpression, returningType = ELEMENT, parentClause = this) } interface IUpdateWhereClause : IUpdateLimitClause { diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/ReturningClause.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/ReturningClause.kt index 78e47af0..acd04930 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/ReturningClause.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/ReturningClause.kt @@ -2,47 +2,99 @@ package ch.ergon.dope.resolvable.clause.model import ch.ergon.dope.DopeQuery import ch.ergon.dope.DopeQueryManager +import ch.ergon.dope.resolvable.Resolvable import ch.ergon.dope.resolvable.clause.Clause import ch.ergon.dope.resolvable.clause.IDeleteOffsetClause import ch.ergon.dope.resolvable.clause.IDeleteReturningClause import ch.ergon.dope.resolvable.clause.IUpdateLimitClause import ch.ergon.dope.resolvable.clause.IUpdateReturningClause -import ch.ergon.dope.resolvable.expression.unaliased.type.Field +import ch.ergon.dope.resolvable.expression.SingleExpression import ch.ergon.dope.resolvable.formatToQueryStringWithSymbol +import ch.ergon.dope.resolvable.fromable.AliasedSelectClause +import ch.ergon.dope.resolvable.fromable.Returnable import ch.ergon.dope.validtype.ValidType +private const val RETURNING = "RETURNING" + +enum class ReturningType(val queryString: String) { + ELEMENT("ELEMENT"), + RAW("RAW"), + VALUE("VALUE"), +} + sealed class ReturningClause( - private val field: Field, - private vararg val fields: Field, + private val returnable: Returnable, + private vararg val additionalReturnables: Returnable, private val parentClause: Clause, -) { - fun toDopeQuery(manager: DopeQueryManager): DopeQuery { - val fieldsDopeQuery = fields.map { it.toDopeQuery(manager) } - val fieldDopeQuery = field.toDopeQuery(manager) +) : Resolvable { + override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { + val returnables = arrayOf(returnable) + additionalReturnables val parentDopeQuery = parentClause.toDopeQuery(manager) + val returnablesDopeQuery = returnables.map { + when (it) { + is AliasedSelectClause<*> -> it.asAliasedSelectClauseDefinition().toDopeQuery(manager) + else -> it.toDopeQuery(manager) + } + } return DopeQuery( queryString = formatToQueryStringWithSymbol( parentDopeQuery.queryString, - "RETURNING", - fieldDopeQuery.queryString, - *fieldsDopeQuery.map { it.queryString }.toTypedArray(), + RETURNING, + *returnablesDopeQuery.map { it.queryString }.toTypedArray(), ), parameters = parentDopeQuery.parameters.merge( - fieldDopeQuery.parameters, - *fieldsDopeQuery.map { it.parameters }.toTypedArray(), + *returnablesDopeQuery.map { it.parameters }.toTypedArray(), ), ) } } class DeleteReturningClause( - field: Field, - vararg fields: Field, + returnable: Returnable, + vararg additionalReturnables: Returnable, parentClause: IDeleteOffsetClause, -) : IDeleteReturningClause, ReturningClause(field, *fields, parentClause = parentClause) +) : IDeleteReturningClause, ReturningClause( + returnable, + *additionalReturnables, + parentClause = parentClause, +) class UpdateReturningClause( - field: Field, - vararg fields: Field, + returnable: Returnable, + vararg additionalReturnables: Returnable, + parentClause: IUpdateLimitClause, +) : IUpdateReturningClause, ReturningClause( + returnable, + *additionalReturnables, + parentClause = parentClause, +) + +sealed class ReturningSingleClause( + private val singleReturnable: SingleExpression, + private val returningType: ReturningType, + private val parentClause: Clause, +) : Resolvable { + override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { + val parentDopeQuery = parentClause.toDopeQuery(manager) + val singleReturnableDopeQuery = singleReturnable.toDopeQuery(manager) + return DopeQuery( + queryString = "${parentDopeQuery.queryString} $RETURNING " + + "${returningType.queryString} ${singleReturnableDopeQuery.queryString}", + parameters = parentDopeQuery.parameters.merge( + singleReturnableDopeQuery.parameters, + ), + ) + } +} + +class DeleteReturningSingleClause( + singleReturnable: SingleExpression, + returningType: ReturningType, + parentClause: IDeleteOffsetClause, +) : IDeleteReturningClause, ReturningSingleClause(singleReturnable, returningType, parentClause = parentClause) + +class UpdateReturningSingleClause( + singleReturnable: SingleExpression, + returningType: ReturningType, parentClause: IUpdateLimitClause, -) : IUpdateReturningClause, ReturningClause(field, *fields, parentClause = parentClause) +) : IUpdateReturningClause, ReturningSingleClause(singleReturnable, returningType, parentClause = parentClause) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/SelectClause.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/SelectClause.kt index d3485c2a..1c3231d0 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/SelectClause.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/SelectClause.kt @@ -3,15 +3,15 @@ package ch.ergon.dope.resolvable.clause.model import ch.ergon.dope.DopeQuery import ch.ergon.dope.DopeQueryManager import ch.ergon.dope.resolvable.clause.ISelectClause -import ch.ergon.dope.resolvable.expression.Expression -import ch.ergon.dope.resolvable.expression.SingleExpression import ch.ergon.dope.resolvable.formatToQueryString +import ch.ergon.dope.resolvable.fromable.RawSelectable +import ch.ergon.dope.resolvable.fromable.Selectable import ch.ergon.dope.validtype.ObjectType import ch.ergon.dope.validtype.ValidType class SelectClause( - private val expression: Expression, - private vararg val expressions: Expression, + private val expression: Selectable, + private vararg val expressions: Selectable, ) : ISelectClause { override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { val expressionDopeQuery = expression.toDopeQuery(manager) @@ -27,7 +27,7 @@ class SelectClause( } } -class SelectRawClause(private val expression: SingleExpression) : ISelectClause { +class SelectRawClause(private val expression: RawSelectable) : ISelectClause { override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { val expressionDopeQuery = expression.toDopeQuery(manager) return DopeQuery( @@ -37,7 +37,7 @@ class SelectRawClause(private val expression: SingleExpression } } -class SelectDistinctClause(private val expression: Expression, private vararg val expressions: Expression) : ISelectClause { +class SelectDistinctClause(private val expression: Selectable, private vararg val expressions: Selectable) : ISelectClause { override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { val expressionsDopeQuery = expressions.map { it.toDopeQuery(manager) } val expressionDopeQuery = expression.toDopeQuery(manager) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UnnestClause.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UnnestClause.kt index 3e370a18..f806ff93 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UnnestClause.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/clause/model/UnnestClause.kt @@ -3,7 +3,7 @@ package ch.ergon.dope.resolvable.clause.model import ch.ergon.dope.DopeQuery import ch.ergon.dope.DopeQueryManager import ch.ergon.dope.resolvable.clause.ISelectUnnestClause -import ch.ergon.dope.resolvable.expression.AliasedExpression +import ch.ergon.dope.resolvable.expression.AliasedTypeExpression import ch.ergon.dope.resolvable.expression.unaliased.type.Field import ch.ergon.dope.resolvable.formatToQueryStringWithSymbol import ch.ergon.dope.validtype.ArrayType @@ -26,15 +26,15 @@ class UnnestClause( } class AliasedUnnestClause( - private val aliasedExpression: AliasedExpression>, + private val aliasedTypeExpression: AliasedTypeExpression>, private val parentClause: ISelectUnnestClause, ) : ISelectUnnestClause { override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { val parentDopeQuery = parentClause.toDopeQuery(manager) - val aliasedExpressionDopeQuery = aliasedExpression.toDopeQuery(manager) + val aliasedTypeExpressionDopeQuery = aliasedTypeExpression.toDopeQuery(manager) return DopeQuery( - queryString = formatToQueryStringWithSymbol(parentDopeQuery.queryString, UNNEST, aliasedExpressionDopeQuery.queryString), - parameters = parentDopeQuery.parameters.merge(aliasedExpressionDopeQuery.parameters), + queryString = formatToQueryStringWithSymbol(parentDopeQuery.queryString, UNNEST, aliasedTypeExpressionDopeQuery.queryString), + parameters = parentDopeQuery.parameters.merge(aliasedTypeExpressionDopeQuery.parameters), ) } } diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/AliasedExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/AliasedExpression.kt deleted file mode 100644 index 77932f8f..00000000 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/AliasedExpression.kt +++ /dev/null @@ -1,30 +0,0 @@ -package ch.ergon.dope.resolvable.expression - -import ch.ergon.dope.DopeQuery -import ch.ergon.dope.DopeQueryManager -import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType -import ch.ergon.dope.resolvable.formatToQueryStringWithSymbol -import ch.ergon.dope.validtype.ValidType - -class AliasedExpression( - private val unaliasedExpression: UnaliasedExpression, - private val alias: String, -) : SingleExpression { - override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { - val unaliasedExpressionDopeQuery = unaliasedExpression.toDopeQuery(manager) - return DopeQuery( - queryString = formatToQueryStringWithSymbol(unaliasedExpressionDopeQuery.queryString, "AS", "`$alias`"), - parameters = unaliasedExpressionDopeQuery.parameters, - ) - } -} - -fun UnaliasedExpression.alias(string: String): AliasedExpression = AliasedExpression(this, string) - -fun Number.alias(string: String) = toDopeType().alias(string) - -fun String.alias(string: String) = toDopeType().alias(string) - -fun Boolean.alias(string: String) = toDopeType().alias(string) - -fun Map.alias(string: String) = toDopeType().alias(string) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/AliasedTypeExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/AliasedTypeExpression.kt new file mode 100644 index 00000000..57bfd128 --- /dev/null +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/AliasedTypeExpression.kt @@ -0,0 +1,34 @@ +package ch.ergon.dope.resolvable.expression + +import ch.ergon.dope.DopeQuery +import ch.ergon.dope.DopeQueryManager +import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType +import ch.ergon.dope.resolvable.formatToQueryStringWithSymbol +import ch.ergon.dope.validtype.BooleanType +import ch.ergon.dope.validtype.NumberType +import ch.ergon.dope.validtype.ObjectType +import ch.ergon.dope.validtype.StringType +import ch.ergon.dope.validtype.ValidType + +class AliasedTypeExpression( + private val typeExpression: TypeExpression, + private val alias: String, +) : SingleExpression { + override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { + val typeExpressionDopeQuery = typeExpression.toDopeQuery(manager) + return DopeQuery( + queryString = formatToQueryStringWithSymbol(typeExpressionDopeQuery.queryString, "AS", "`$alias`"), + parameters = typeExpressionDopeQuery.parameters, + ) + } +} + +fun TypeExpression.alias(alias: String): AliasedTypeExpression = AliasedTypeExpression(this, alias) + +fun Number.alias(string: String): AliasedTypeExpression = toDopeType().alias(string) + +fun String.alias(string: String): AliasedTypeExpression = toDopeType().alias(string) + +fun Boolean.alias(string: String): AliasedTypeExpression = toDopeType().alias(string) + +fun Map.alias(string: String): AliasedTypeExpression = toDopeType().alias(string) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/AsteriskExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/Asterisk.kt similarity index 65% rename from core/src/main/kotlin/ch/ergon/dope/resolvable/expression/AsteriskExpression.kt rename to core/src/main/kotlin/ch/ergon/dope/resolvable/expression/Asterisk.kt index d3cbdc2e..d42c0d70 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/AsteriskExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/Asterisk.kt @@ -3,12 +3,16 @@ package ch.ergon.dope.resolvable.expression import ch.ergon.dope.DopeQuery import ch.ergon.dope.DopeQueryManager import ch.ergon.dope.resolvable.fromable.Bucket +import ch.ergon.dope.resolvable.fromable.Returnable +import ch.ergon.dope.resolvable.fromable.Selectable const val ASTERISK_STRING = "*" -class AsteriskExpression(private val bucket: Bucket? = null) : Expression { +class Asterisk(private val bucket: Bucket? = null) : Selectable, Returnable { override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { val queryString = bucket?.toDopeQuery(manager)?.queryString?.let { "$it.$ASTERISK_STRING" } ?: ASTERISK_STRING return DopeQuery(queryString = queryString) } } + +fun asterisk(bucket: Bucket? = null) = Asterisk(bucket) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/Expression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/Expression.kt index c1fbfa9c..2b5eb9c0 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/Expression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/Expression.kt @@ -1,12 +1,9 @@ package ch.ergon.dope.resolvable.expression -import ch.ergon.dope.resolvable.Resolvable +import ch.ergon.dope.resolvable.fromable.RawSelectable +import ch.ergon.dope.resolvable.fromable.Returnable import ch.ergon.dope.validtype.ValidType -interface Expression : Resolvable +interface SingleExpression : RawSelectable, Returnable -interface SingleExpression : Expression - -interface UnaliasedExpression : SingleExpression - -interface TypeExpression : UnaliasedExpression +interface TypeExpression : SingleExpression diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/AggregateExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/AggregateExpression.kt index 03d7442b..12a97c4f 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/AggregateExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/AggregateExpression.kt @@ -2,20 +2,24 @@ package ch.ergon.dope.resolvable.expression.unaliased.aggregator import ch.ergon.dope.DopeQuery import ch.ergon.dope.DopeQueryManager -import ch.ergon.dope.resolvable.expression.UnaliasedExpression import ch.ergon.dope.resolvable.expression.unaliased.type.Field +import ch.ergon.dope.resolvable.fromable.RawSelectable import ch.ergon.dope.resolvable.operator.FunctionOperator import ch.ergon.dope.validtype.ValidType -sealed class AggregateExpression( +interface AggregateExpression : RawSelectable + +sealed class AggregateFunctionExpression( private val symbol: String, - private val field: Field, + private val field: Field, private val quantifier: AggregateQuantifier?, -) : FunctionOperator, UnaliasedExpression { +) : FunctionOperator, AggregateExpression { override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { val fieldDopeQuery = field.toDopeQuery(manager) return DopeQuery( - queryString = toFunctionQueryString(symbol, quantifier, fieldDopeQuery.queryString), + queryString = quantifier?.let { + "$symbol($quantifier ${fieldDopeQuery.queryString})" + } ?: toFunctionQueryString(symbol, fieldDopeQuery.queryString), parameters = fieldDopeQuery.parameters, ) } diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/AliasedAggregateExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/AliasedAggregateExpression.kt new file mode 100644 index 00000000..54923672 --- /dev/null +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/AliasedAggregateExpression.kt @@ -0,0 +1,26 @@ +package ch.ergon.dope.resolvable.expression.unaliased.aggregator + +import ch.ergon.dope.DopeQuery +import ch.ergon.dope.DopeQueryManager +import ch.ergon.dope.resolvable.formatToQueryStringWithSymbol +import ch.ergon.dope.resolvable.fromable.RawSelectable +import ch.ergon.dope.validtype.ValidType + +class AliasedAggregateExpression( + private val aggregateExpression: AggregateExpression, + private val alias: String, +) : RawSelectable { + override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { + val aggregateExpressionDopeQuery = aggregateExpression.toDopeQuery(manager) + return DopeQuery( + queryString = formatToQueryStringWithSymbol( + aggregateExpressionDopeQuery.queryString, + "AS", + "`$alias`", + ), + parameters = aggregateExpressionDopeQuery.parameters, + ) + } +} + +fun AggregateExpression.alias(alias: String) = AliasedAggregateExpression(this, alias) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/ArrayAggregateExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/ArrayAggregateExpression.kt index b89caf6a..54ee0039 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/ArrayAggregateExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/ArrayAggregateExpression.kt @@ -1,24 +1,11 @@ package ch.ergon.dope.resolvable.expression.unaliased.aggregator -import ch.ergon.dope.DopeQuery -import ch.ergon.dope.DopeQueryManager -import ch.ergon.dope.resolvable.expression.UnaliasedExpression import ch.ergon.dope.resolvable.expression.unaliased.type.Field -import ch.ergon.dope.resolvable.operator.FunctionOperator import ch.ergon.dope.validtype.ArrayType import ch.ergon.dope.validtype.ValidType -class ArrayAggregateExpression( - private val field: Field, - private val quantifier: AggregateQuantifier?, -) : FunctionOperator, UnaliasedExpression> { - override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { - val fieldDopeQuery = field.toDopeQuery(manager) - return DopeQuery( - queryString = toFunctionQueryString("ARRAY_AGG", quantifier, fieldDopeQuery.queryString), - parameters = fieldDopeQuery.parameters, - ) - } -} +class ArrayAggregateExpression(field: Field, quantifier: AggregateQuantifier?) : + AggregateFunctionExpression>("ARRAY_AGG", field, quantifier) -fun arrayAggregate(field: Field, quantifier: AggregateQuantifier? = null) = ArrayAggregateExpression(field, quantifier) +fun arrayAggregate(field: Field, quantifier: AggregateQuantifier? = null) = + ArrayAggregateExpression(field, quantifier) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/AverageExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/AverageExpression.kt index 2ce270da..1653bf08 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/AverageExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/AverageExpression.kt @@ -3,9 +3,9 @@ package ch.ergon.dope.resolvable.expression.unaliased.aggregator import ch.ergon.dope.resolvable.expression.unaliased.type.Field import ch.ergon.dope.validtype.NumberType -class AverageExpression( - number: Field, +class AverageExpression( + number: Field, quantifier: AggregateQuantifier?, -) : AggregateExpression("AVG", number, quantifier) +) : AggregateFunctionExpression("AVG", number, quantifier) -fun avg(number: Field, quantifier: AggregateQuantifier? = null) = AverageExpression(number, quantifier) +fun avg(number: Field, quantifier: AggregateQuantifier? = null) = AverageExpression(number, quantifier) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/CountExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/CountExpression.kt index 10023457..a238da34 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/CountExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/CountExpression.kt @@ -3,31 +3,19 @@ package ch.ergon.dope.resolvable.expression.unaliased.aggregator import ch.ergon.dope.DopeQuery import ch.ergon.dope.DopeQueryManager import ch.ergon.dope.resolvable.expression.ASTERISK_STRING -import ch.ergon.dope.resolvable.expression.UnaliasedExpression import ch.ergon.dope.resolvable.expression.unaliased.type.Field -import ch.ergon.dope.resolvable.operator.FunctionOperator import ch.ergon.dope.validtype.NumberType import ch.ergon.dope.validtype.ValidType -class CountExpression( - private val field: Field, - private val quantifier: AggregateQuantifier?, -) : FunctionOperator, UnaliasedExpression { - override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { - val fieldDopeQuery = field.toDopeQuery(manager) - return DopeQuery( - queryString = toFunctionQueryString("COUNT", quantifier, fieldDopeQuery.queryString), - parameters = fieldDopeQuery.parameters, - ) - } -} +class CountExpression(field: Field, quantifier: AggregateQuantifier?) : + AggregateFunctionExpression("COUNT", field, quantifier) + +fun count(field: Field, quantifier: AggregateQuantifier? = null) = CountExpression(field, quantifier) -class CountAsteriskExpression : UnaliasedExpression { +class CountAsteriskExpression : AggregateExpression { override fun toDopeQuery(manager: DopeQueryManager) = DopeQuery( queryString = "COUNT($ASTERISK_STRING)", ) } -fun count(field: Field, quantifier: AggregateQuantifier? = null) = CountExpression(field, quantifier) - fun countAsterisk() = CountAsteriskExpression() diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/MaxExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/MaxExpression.kt index 0474dd1c..69827e06 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/MaxExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/MaxExpression.kt @@ -6,6 +6,6 @@ import ch.ergon.dope.validtype.ValidType class MaxExpression( field: Field, quantifier: AggregateQuantifier?, -) : AggregateExpression("MAX", field, quantifier) +) : AggregateFunctionExpression("MAX", field, quantifier) -fun max(field: Field, quantifier: AggregateQuantifier? = null) = MaxExpression(field, quantifier) +fun max(field: Field, quantifier: AggregateQuantifier? = null) = MaxExpression(field, quantifier) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/MeanExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/MeanExpression.kt index 8cc55aeb..c8f0119c 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/MeanExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/MeanExpression.kt @@ -3,9 +3,9 @@ package ch.ergon.dope.resolvable.expression.unaliased.aggregator import ch.ergon.dope.resolvable.expression.unaliased.type.Field import ch.ergon.dope.validtype.NumberType -class MeanExpression( - number: Field, +class MeanExpression( + number: Field, quantifier: AggregateQuantifier?, -) : AggregateExpression("MEAN", number, quantifier) +) : AggregateFunctionExpression("MEAN", number, quantifier) -fun mean(number: Field, quantifier: AggregateQuantifier? = null) = MeanExpression(number, quantifier) +fun mean(number: Field, quantifier: AggregateQuantifier? = null) = MeanExpression(number, quantifier) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/MedianExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/MedianExpression.kt index 9012b19e..45ffe339 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/MedianExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/MedianExpression.kt @@ -3,9 +3,9 @@ package ch.ergon.dope.resolvable.expression.unaliased.aggregator import ch.ergon.dope.resolvable.expression.unaliased.type.Field import ch.ergon.dope.validtype.NumberType -class MedianExpression( - number: Field, +class MedianExpression( + number: Field, quantifier: AggregateQuantifier?, -) : AggregateExpression("MEDIAN", number, quantifier) +) : AggregateFunctionExpression("MEDIAN", number, quantifier) -fun median(number: Field, quantifier: AggregateQuantifier? = null) = MedianExpression(number, quantifier) +fun median(number: Field, quantifier: AggregateQuantifier? = null) = MedianExpression(number, quantifier) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/MinExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/MinExpression.kt index e4c86e2b..ef4b6d58 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/MinExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/MinExpression.kt @@ -6,6 +6,6 @@ import ch.ergon.dope.validtype.ValidType class MinExpression( field: Field, quantifier: AggregateQuantifier?, -) : AggregateExpression("MIN", field, quantifier) +) : AggregateFunctionExpression("MIN", field, quantifier) fun min(field: Field, quantifier: AggregateQuantifier? = null) = MinExpression(field, quantifier) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/StandardDeviationExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/StandardDeviationExpression.kt index be6d4bbd..fbce33c6 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/StandardDeviationExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/StandardDeviationExpression.kt @@ -3,9 +3,9 @@ package ch.ergon.dope.resolvable.expression.unaliased.aggregator import ch.ergon.dope.resolvable.expression.unaliased.type.Field import ch.ergon.dope.validtype.NumberType -class StandardDeviationExpression( - number: Field, +class StandardDeviationExpression( + number: Field, quantifier: AggregateQuantifier?, -) : AggregateExpression("STDDEV", number, quantifier) +) : AggregateFunctionExpression("STDDEV", number, quantifier) -fun stdDev(number: Field, quantifier: AggregateQuantifier? = null) = StandardDeviationExpression(number, quantifier) +fun stdDev(number: Field, quantifier: AggregateQuantifier? = null) = StandardDeviationExpression(number, quantifier) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/SumExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/SumExpression.kt index 0643105c..d23bc92c 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/SumExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/SumExpression.kt @@ -3,9 +3,9 @@ package ch.ergon.dope.resolvable.expression.unaliased.aggregator import ch.ergon.dope.resolvable.expression.unaliased.type.Field import ch.ergon.dope.validtype.NumberType -class SumExpression( - number: Field, +class SumExpression( + number: Field, quantifier: AggregateQuantifier?, -) : AggregateExpression("SUM", number, quantifier) +) : AggregateFunctionExpression("SUM", number, quantifier) fun sum(number: Field, quantifier: AggregateQuantifier? = null) = SumExpression(number, quantifier) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/VarianceExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/VarianceExpression.kt index 302f5639..98fac466 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/VarianceExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/aggregator/VarianceExpression.kt @@ -3,9 +3,9 @@ package ch.ergon.dope.resolvable.expression.unaliased.aggregator import ch.ergon.dope.resolvable.expression.unaliased.type.Field import ch.ergon.dope.validtype.NumberType -class VarianceExpression( - number: Field, +class VarianceExpression( + number: Field, quantifier: AggregateQuantifier?, -) : AggregateExpression("VARIANCE", number, quantifier) +) : AggregateFunctionExpression("VARIANCE", number, quantifier) -fun variance(number: Field, quantifier: AggregateQuantifier? = null) = VarianceExpression(number, quantifier) +fun variance(number: Field, quantifier: AggregateQuantifier? = null) = VarianceExpression(number, quantifier) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/access/ArrayAccess.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/access/ArrayAccess.kt index 9bf58028..8c3ec310 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/access/ArrayAccess.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/access/ArrayAccess.kt @@ -3,6 +3,7 @@ package ch.ergon.dope.resolvable.expression.unaliased.type.access import ch.ergon.dope.DopeQuery import ch.ergon.dope.DopeQueryManager import ch.ergon.dope.resolvable.clause.ISelectOffsetClause +import ch.ergon.dope.resolvable.expression.SingleExpression import ch.ergon.dope.resolvable.expression.TypeExpression import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType import ch.ergon.dope.validtype.ArrayType @@ -10,7 +11,7 @@ import ch.ergon.dope.validtype.NumberType import ch.ergon.dope.validtype.ValidType class ArrayAccess( - private val array: TypeExpression>, + private val array: SingleExpression>, private val index: TypeExpression, ) : TypeExpression { override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { @@ -23,9 +24,9 @@ class ArrayAccess( } } -fun TypeExpression>.get(index: TypeExpression) = ArrayAccess(this, index) +fun SingleExpression>.get(index: TypeExpression) = ArrayAccess(this, index) -fun TypeExpression>.get(index: Number) = get(index.toDopeType()) +fun SingleExpression>.get(index: Number) = get(index.toDopeType()) fun ISelectOffsetClause.get(index: TypeExpression) = asExpression().get(index) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/collection/SatisfiesExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/collection/SatisfiesExpression.kt index fe65a10d..f033134a 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/collection/SatisfiesExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/collection/SatisfiesExpression.kt @@ -3,6 +3,7 @@ package ch.ergon.dope.resolvable.expression.unaliased.type.collection import ch.ergon.dope.DopeQuery import ch.ergon.dope.DopeQueryManager import ch.ergon.dope.resolvable.clause.ISelectOffsetClause +import ch.ergon.dope.resolvable.expression.SingleExpression import ch.ergon.dope.resolvable.expression.TypeExpression import ch.ergon.dope.resolvable.expression.unaliased.type.collection.SatisfiesType.ANY import ch.ergon.dope.resolvable.expression.unaliased.type.collection.SatisfiesType.EVERY @@ -18,7 +19,7 @@ enum class SatisfiesType { sealed class SatisfiesExpression( private val satisfiesType: SatisfiesType, - private val arrayExpression: TypeExpression>, + private val arrayExpression: SingleExpression>, private val iteratorName: String? = null, private val predicate: (Iterator) -> TypeExpression, ) : TypeExpression { @@ -40,18 +41,18 @@ class Iterator(private val variable: String) : TypeExpression } class AnySatisfiesExpression( - arrayExpression: TypeExpression>, + arrayExpression: SingleExpression>, iteratorName: String? = null, predicate: (Iterator) -> TypeExpression, ) : SatisfiesExpression(ANY, arrayExpression, iteratorName, predicate) class EverySatisfiesExpression( - arrayExpression: TypeExpression>, + arrayExpression: SingleExpression>, iteratorName: String? = null, predicate: (Iterator) -> TypeExpression, ) : SatisfiesExpression(EVERY, arrayExpression, iteratorName, predicate) -fun TypeExpression>.any( +fun SingleExpression>.any( iteratorName: String? = null, predicate: (Iterator) -> TypeExpression, ) = AnySatisfiesExpression(this, iteratorName, predicate) @@ -66,7 +67,7 @@ fun ISelectOffsetClause.any( predicate: (Iterator) -> TypeExpression, ) = asExpression().any(iteratorName, predicate) -fun TypeExpression>.every( +fun SingleExpression>.every( iteratorName: String? = null, predicate: (Iterator) -> TypeExpression, ) = EverySatisfiesExpression(this, iteratorName, predicate) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/FunctionExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/FunctionExpression.kt index bf4f704e..dd293011 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/FunctionExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/FunctionExpression.kt @@ -4,13 +4,12 @@ import ch.ergon.dope.DopeQuery import ch.ergon.dope.DopeQueryManager import ch.ergon.dope.merge import ch.ergon.dope.resolvable.expression.TypeExpression -import ch.ergon.dope.resolvable.expression.UnaliasedExpression import ch.ergon.dope.resolvable.operator.FunctionOperator import ch.ergon.dope.validtype.ValidType abstract class FunctionExpression( private val symbol: String, - private vararg val expressions: UnaliasedExpression?, + private vararg val expressions: TypeExpression?, ) : TypeExpression, FunctionOperator { override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { val expressionsDopeQuery = expressions.mapNotNull { it?.toDopeQuery(manager) } diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/comparison/GreatestExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/comparison/GreatestExpression.kt index 42ad2483..335a3c9f 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/comparison/GreatestExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/comparison/GreatestExpression.kt @@ -1,17 +1,17 @@ package ch.ergon.dope.resolvable.expression.unaliased.type.function.comparison -import ch.ergon.dope.resolvable.expression.UnaliasedExpression +import ch.ergon.dope.resolvable.expression.TypeExpression import ch.ergon.dope.resolvable.expression.unaliased.type.function.FunctionExpression import ch.ergon.dope.validtype.ComparableType class GreatestExpression( - firstExpression: UnaliasedExpression, - secondExpression: UnaliasedExpression, - vararg additionalExpressions: UnaliasedExpression, + firstExpression: TypeExpression, + secondExpression: TypeExpression, + vararg additionalExpressions: TypeExpression, ) : FunctionExpression("GREATEST", firstExpression, secondExpression, *additionalExpressions) fun greatestOf( - firstExpression: UnaliasedExpression, - secondExpression: UnaliasedExpression, - vararg additionalExpressions: UnaliasedExpression, + firstExpression: TypeExpression, + secondExpression: TypeExpression, + vararg additionalExpressions: TypeExpression, ) = GreatestExpression(firstExpression, secondExpression, *additionalExpressions) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/comparison/LeastExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/comparison/LeastExpression.kt index 621fc357..e24b744c 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/comparison/LeastExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/comparison/LeastExpression.kt @@ -1,17 +1,17 @@ package ch.ergon.dope.resolvable.expression.unaliased.type.function.comparison -import ch.ergon.dope.resolvable.expression.UnaliasedExpression +import ch.ergon.dope.resolvable.expression.TypeExpression import ch.ergon.dope.resolvable.expression.unaliased.type.function.FunctionExpression import ch.ergon.dope.validtype.ComparableType class LeastExpression( - firstExpression: UnaliasedExpression, - secondExpression: UnaliasedExpression, - vararg additionalExpressions: UnaliasedExpression, + firstExpression: TypeExpression, + secondExpression: TypeExpression, + vararg additionalExpressions: TypeExpression, ) : FunctionExpression("LEAST", firstExpression, secondExpression, *additionalExpressions) fun leastOf( - firstExpression: UnaliasedExpression, - secondExpression: UnaliasedExpression, - vararg additionalExpressions: UnaliasedExpression, + firstExpression: TypeExpression, + secondExpression: TypeExpression, + vararg additionalExpressions: TypeExpression, ) = LeastExpression(firstExpression, secondExpression, *additionalExpressions) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/DecodeExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/DecodeExpression.kt index 03ee4042..8484a393 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/DecodeExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/DecodeExpression.kt @@ -3,15 +3,14 @@ package ch.ergon.dope.resolvable.expression.unaliased.type.function.conditional import ch.ergon.dope.DopeQuery import ch.ergon.dope.DopeQueryManager import ch.ergon.dope.resolvable.expression.TypeExpression -import ch.ergon.dope.resolvable.expression.UnaliasedExpression import ch.ergon.dope.resolvable.operator.FunctionOperator import ch.ergon.dope.validtype.ValidType class DecodeExpression( - private val decodeExpression: UnaliasedExpression, + private val decodeExpression: TypeExpression, private val searchResult: SearchResult, private vararg val searchResults: SearchResult, - private val default: UnaliasedExpression? = null, + private val default: TypeExpression? = null, ) : TypeExpression, FunctionOperator { override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { val decodeExpressionDopeQuery = decodeExpression.toDopeQuery(manager) @@ -46,22 +45,22 @@ class DecodeExpression( @JvmName("decodeWithGeneric") fun decode( - decodeExpression: UnaliasedExpression, + decodeExpression: TypeExpression, searchResult: SearchResult, vararg searchResults: SearchResult, ) = DecodeExpression(decodeExpression, searchResult, *searchResults) fun decode( - decodeExpression: UnaliasedExpression, + decodeExpression: TypeExpression, searchResult: SearchResult, vararg searchResults: SearchResult, - default: UnaliasedExpression, + default: TypeExpression, ) = DecodeExpression(decodeExpression, searchResult, *searchResults, default = default) @JvmName("decodeWithoutGeneric") fun decode( - decodeExpression: UnaliasedExpression, + decodeExpression: TypeExpression, searchResult: SearchResult, vararg searchResults: SearchResult, - default: UnaliasedExpression? = null, + default: TypeExpression? = null, ) = DecodeExpression(decodeExpression, searchResult, *searchResults, default = default) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/IfMissingExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/IfMissingExpression.kt index 309af612..59711ebd 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/IfMissingExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/IfMissingExpression.kt @@ -1,17 +1,17 @@ package ch.ergon.dope.resolvable.expression.unaliased.type.function.conditional -import ch.ergon.dope.resolvable.expression.UnaliasedExpression +import ch.ergon.dope.resolvable.expression.TypeExpression import ch.ergon.dope.resolvable.expression.unaliased.type.function.FunctionExpression import ch.ergon.dope.validtype.ValidType class IfMissingExpression( - firstExpression: UnaliasedExpression, - secondExpression: UnaliasedExpression, - vararg additionalExpressions: UnaliasedExpression, + firstExpression: TypeExpression, + secondExpression: TypeExpression, + vararg additionalExpressions: TypeExpression, ) : FunctionExpression("IFMISSING", firstExpression, secondExpression, *additionalExpressions) fun ifMissing( - firstExpression: UnaliasedExpression, - secondExpression: UnaliasedExpression, - vararg additionalExpressions: UnaliasedExpression, + firstExpression: TypeExpression, + secondExpression: TypeExpression, + vararg additionalExpressions: TypeExpression, ) = IfMissingExpression(firstExpression, secondExpression, *additionalExpressions) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/IfMissingOrNullExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/IfMissingOrNullExpression.kt index 855af64e..300777fc 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/IfMissingOrNullExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/IfMissingOrNullExpression.kt @@ -1,29 +1,29 @@ package ch.ergon.dope.resolvable.expression.unaliased.type.function.conditional -import ch.ergon.dope.resolvable.expression.UnaliasedExpression +import ch.ergon.dope.resolvable.expression.TypeExpression import ch.ergon.dope.resolvable.expression.unaliased.type.function.FunctionExpression import ch.ergon.dope.validtype.ValidType class IfMissingOrNullExpression( - firstExpression: UnaliasedExpression, - secondExpression: UnaliasedExpression, - vararg additionalExpressions: UnaliasedExpression, + firstExpression: TypeExpression, + secondExpression: TypeExpression, + vararg additionalExpressions: TypeExpression, ) : FunctionExpression("IFMISSINGORNULL", firstExpression, secondExpression, *additionalExpressions) fun ifMissingOrNull( - firstExpression: UnaliasedExpression, - secondExpression: UnaliasedExpression, - vararg additionalExpressions: UnaliasedExpression, + firstExpression: TypeExpression, + secondExpression: TypeExpression, + vararg additionalExpressions: TypeExpression, ) = IfMissingOrNullExpression(firstExpression, secondExpression, *additionalExpressions) class CoalesceExpression( - firstExpression: UnaliasedExpression, - secondExpression: UnaliasedExpression, - vararg additionalExpressions: UnaliasedExpression, + firstExpression: TypeExpression, + secondExpression: TypeExpression, + vararg additionalExpressions: TypeExpression, ) : FunctionExpression("COALESCE", firstExpression, secondExpression, *additionalExpressions) fun coalesce( - firstExpression: UnaliasedExpression, - secondExpression: UnaliasedExpression, - vararg additionalExpressions: UnaliasedExpression, + firstExpression: TypeExpression, + secondExpression: TypeExpression, + vararg additionalExpressions: TypeExpression, ) = CoalesceExpression(firstExpression, secondExpression, *additionalExpressions) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/IfNullExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/IfNullExpression.kt index 33f23273..d7262b42 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/IfNullExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/IfNullExpression.kt @@ -1,17 +1,17 @@ package ch.ergon.dope.resolvable.expression.unaliased.type.function.conditional -import ch.ergon.dope.resolvable.expression.UnaliasedExpression +import ch.ergon.dope.resolvable.expression.TypeExpression import ch.ergon.dope.resolvable.expression.unaliased.type.function.FunctionExpression import ch.ergon.dope.validtype.ValidType class IfNullExpression( - firstExpression: UnaliasedExpression, - secondExpression: UnaliasedExpression, - vararg additionalExpressions: UnaliasedExpression, + firstExpression: TypeExpression, + secondExpression: TypeExpression, + vararg additionalExpressions: TypeExpression, ) : FunctionExpression("IFNULL", firstExpression, secondExpression, *additionalExpressions) fun ifNull( - firstExpression: UnaliasedExpression, - secondExpression: UnaliasedExpression, - vararg additionalExpressions: UnaliasedExpression, + firstExpression: TypeExpression, + secondExpression: TypeExpression, + vararg additionalExpressions: TypeExpression, ) = IfNullExpression(firstExpression, secondExpression, *additionalExpressions) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/Nvl2Expression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/Nvl2Expression.kt index a1532230..74410fb8 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/Nvl2Expression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/Nvl2Expression.kt @@ -3,7 +3,6 @@ package ch.ergon.dope.resolvable.expression.unaliased.type.function.conditional import ch.ergon.dope.DopeQuery import ch.ergon.dope.DopeQueryManager import ch.ergon.dope.resolvable.expression.TypeExpression -import ch.ergon.dope.resolvable.expression.UnaliasedExpression import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType import ch.ergon.dope.resolvable.operator.FunctionOperator import ch.ergon.dope.validtype.BooleanType @@ -12,9 +11,9 @@ import ch.ergon.dope.validtype.StringType import ch.ergon.dope.validtype.ValidType class Nvl2Expression( - private val initialExpression: UnaliasedExpression, - private val valueIfExists: UnaliasedExpression, - private val valueIfNotExists: UnaliasedExpression, + private val initialExpression: TypeExpression, + private val valueIfExists: TypeExpression, + private val valueIfNotExists: TypeExpression, ) : TypeExpression, FunctionOperator { override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { val initialExpressionDopeQuery = initialExpression.toDopeQuery(manager) @@ -36,61 +35,61 @@ class Nvl2Expression( } fun nvl2( - initialExpression: UnaliasedExpression, - valueIfExists: UnaliasedExpression, - valueIfNotExists: UnaliasedExpression, + initialExpression: TypeExpression, + valueIfExists: TypeExpression, + valueIfNotExists: TypeExpression, ) = Nvl2Expression(initialExpression, valueIfExists, valueIfNotExists) fun nvl2( - initialExpression: UnaliasedExpression, - valueIfExists: UnaliasedExpression, + initialExpression: TypeExpression, + valueIfExists: TypeExpression, valueIfNotExists: Number, ) = Nvl2Expression(initialExpression, valueIfExists, valueIfNotExists.toDopeType()) fun nvl2( - initialExpression: UnaliasedExpression, - valueIfExists: UnaliasedExpression, + initialExpression: TypeExpression, + valueIfExists: TypeExpression, valueIfNotExists: String, ) = Nvl2Expression(initialExpression, valueIfExists, valueIfNotExists.toDopeType()) fun nvl2( - initialExpression: UnaliasedExpression, - valueIfExists: UnaliasedExpression, + initialExpression: TypeExpression, + valueIfExists: TypeExpression, valueIfNotExists: Boolean, ) = Nvl2Expression(initialExpression, valueIfExists, valueIfNotExists.toDopeType()) fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: Number, - valueIfNotExists: UnaliasedExpression, + valueIfNotExists: TypeExpression, ) = Nvl2Expression(initialExpression, valueIfExists.toDopeType(), valueIfNotExists) fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: String, - valueIfNotExists: UnaliasedExpression, + valueIfNotExists: TypeExpression, ) = Nvl2Expression(initialExpression, valueIfExists.toDopeType(), valueIfNotExists) fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: Boolean, - valueIfNotExists: UnaliasedExpression, + valueIfNotExists: TypeExpression, ) = Nvl2Expression(initialExpression, valueIfExists.toDopeType(), valueIfNotExists) fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: Number, valueIfNotExists: Number, ) = Nvl2Expression(initialExpression, valueIfExists.toDopeType(), valueIfNotExists.toDopeType()) fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: String, valueIfNotExists: String, ) = Nvl2Expression(initialExpression, valueIfExists.toDopeType(), valueIfNotExists.toDopeType()) fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: Boolean, valueIfNotExists: Boolean, ) = Nvl2Expression(initialExpression, valueIfExists.toDopeType(), valueIfNotExists.toDopeType()) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/NvlExpression.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/NvlExpression.kt index 60a68c8a..bfe70dab 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/NvlExpression.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/NvlExpression.kt @@ -1,6 +1,6 @@ package ch.ergon.dope.resolvable.expression.unaliased.type.function.conditional -import ch.ergon.dope.resolvable.expression.UnaliasedExpression +import ch.ergon.dope.resolvable.expression.TypeExpression import ch.ergon.dope.resolvable.expression.unaliased.type.function.FunctionExpression import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType import ch.ergon.dope.validtype.BooleanType @@ -9,18 +9,18 @@ import ch.ergon.dope.validtype.StringType import ch.ergon.dope.validtype.ValidType class NvlExpression( - initialExpression: UnaliasedExpression, - substituteExpression: UnaliasedExpression, + initialExpression: TypeExpression, + substituteExpression: TypeExpression, ) : FunctionExpression("NVL", initialExpression, substituteExpression) -fun nvl(initialExpression: UnaliasedExpression, substituteExpression: UnaliasedExpression) = +fun nvl(initialExpression: TypeExpression, substituteExpression: TypeExpression) = NvlExpression(initialExpression, substituteExpression) -fun nvl(initialExpression: UnaliasedExpression, substituteExpression: Number) = +fun nvl(initialExpression: TypeExpression, substituteExpression: Number) = NvlExpression(initialExpression, substituteExpression.toDopeType()) -fun nvl(initialExpression: UnaliasedExpression, substituteExpression: String) = +fun nvl(initialExpression: TypeExpression, substituteExpression: String) = NvlExpression(initialExpression, substituteExpression.toDopeType()) -fun nvl(initialExpression: UnaliasedExpression, substituteExpression: Boolean) = +fun nvl(initialExpression: TypeExpression, substituteExpression: Boolean) = NvlExpression(initialExpression, substituteExpression.toDopeType()) diff --git a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/SearchResult.kt b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/SearchResult.kt index e89360bc..6474546b 100644 --- a/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/SearchResult.kt +++ b/core/src/main/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/function/conditional/SearchResult.kt @@ -1,33 +1,33 @@ package ch.ergon.dope.resolvable.expression.unaliased.type.function.conditional -import ch.ergon.dope.resolvable.expression.UnaliasedExpression +import ch.ergon.dope.resolvable.expression.TypeExpression import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType import ch.ergon.dope.validtype.ValidType data class SearchResult( - val searchExpression: UnaliasedExpression, - val resultExpression: UnaliasedExpression, + val searchExpression: TypeExpression, + val resultExpression: TypeExpression, ) -fun UnaliasedExpression.resultsIn(resultExpression: UnaliasedExpression) = +fun TypeExpression.resultsIn(resultExpression: TypeExpression) = SearchResult(this, resultExpression) -fun UnaliasedExpression.resultsIn(resultExpression: Number) = +fun TypeExpression.resultsIn(resultExpression: Number) = SearchResult(this, resultExpression.toDopeType()) -fun UnaliasedExpression.resultsIn(resultExpression: String) = +fun TypeExpression.resultsIn(resultExpression: String) = SearchResult(this, resultExpression.toDopeType()) -fun UnaliasedExpression.resultsIn(resultExpression: Boolean) = +fun TypeExpression.resultsIn(resultExpression: Boolean) = SearchResult(this, resultExpression.toDopeType()) -fun Number.resultsIn(resultExpression: UnaliasedExpression) = +fun Number.resultsIn(resultExpression: TypeExpression) = SearchResult(toDopeType(), resultExpression) -fun String.resultsIn(resultExpression: UnaliasedExpression) = +fun String.resultsIn(resultExpression: TypeExpression) = SearchResult(toDopeType(), resultExpression) -fun Boolean.resultsIn(resultExpression: UnaliasedExpression) = +fun Boolean.resultsIn(resultExpression: TypeExpression) = SearchResult(toDopeType(), resultExpression) fun Number.resultsIn(resultExpression: Number) = 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 ef7b621c..99346d00 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 @@ -3,14 +3,13 @@ package ch.ergon.dope.resolvable.fromable import ch.ergon.dope.DopeQuery import ch.ergon.dope.DopeQueryManager import ch.ergon.dope.resolvable.clause.ISelectOffsetClause -import ch.ergon.dope.resolvable.expression.TypeExpression -import ch.ergon.dope.validtype.ArrayType +import ch.ergon.dope.resolvable.expression.SingleExpression import ch.ergon.dope.validtype.ValidType class AliasedSelectClause( private val alias: String, private val parentClause: ISelectOffsetClause, -) : Fromable, Joinable, TypeExpression> { +) : Fromable, Joinable, SingleExpression { override fun toDopeQuery(manager: DopeQueryManager): DopeQuery = DopeQuery( queryString = "`$alias`", @@ -22,7 +21,7 @@ class AliasedSelectClause( class AliasedSelectClauseDefinition( private val alias: String, private val parentClause: ISelectOffsetClause, -) : Fromable, Joinable, TypeExpression { +) : Fromable, Joinable, SingleExpression { override fun toDopeQuery(manager: DopeQueryManager): DopeQuery { val parentClauseDopeQuery = parentClause.toDopeQuery(manager) 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 50ccb973..538645af 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,10 +3,11 @@ package ch.ergon.dope.resolvable.fromable import ch.ergon.dope.DopeQuery import ch.ergon.dope.DopeQueryManager import ch.ergon.dope.resolvable.Resolvable -import ch.ergon.dope.resolvable.expression.AsteriskExpression -import ch.ergon.dope.resolvable.expression.Expression +import ch.ergon.dope.resolvable.expression.Asterisk +import ch.ergon.dope.resolvable.expression.SingleExpression +import ch.ergon.dope.validtype.ObjectType -sealed class Bucket(open val name: String) : Fromable, Joinable, Deletable, Updatable, Expression { +sealed class Bucket(open val name: String) : Fromable, Joinable, Deletable, Updatable, SingleExpression { override fun toDopeQuery(manager: DopeQueryManager) = DopeQuery( queryString = "`$name`", ) @@ -30,4 +31,4 @@ class AliasedBucketDefinition(val name: String, val alias: String) : Resolvable ) } -fun Bucket.asterisk() = AsteriskExpression(this) +fun Bucket.asterisk() = Asterisk(this) 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 0804a053..d5199959 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 @@ -1,6 +1,11 @@ package ch.ergon.dope.resolvable.fromable import ch.ergon.dope.resolvable.Resolvable +import ch.ergon.dope.validtype.ValidType + +interface Selectable : Resolvable + +interface RawSelectable : Selectable interface Fromable : Resolvable @@ -9,3 +14,5 @@ interface Joinable : Resolvable interface Deletable : Resolvable interface Updatable : Resolvable + +interface Returnable : Resolvable 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 4995ae66..4541bfca 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 @@ -1,7 +1,6 @@ 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 @@ -11,9 +10,4 @@ interface FunctionOperator { fun toFunctionQueryString(symbol: String, vararg arguments: String) = formatStringListToQueryStringWithBrackets(arguments.toList(), prefix = "$symbol(") - - fun toFunctionQueryString(symbol: String, quantifier: AggregateQuantifier?, argument: String) = - quantifier?.let { - "$symbol($quantifier $argument)" - } ?: toFunctionQueryString(symbol, argument) } diff --git a/core/src/test/kotlin/ch/ergon/dope/buildTest/AggregateFunctionsTest.kt b/core/src/test/kotlin/ch/ergon/dope/buildTest/AggregateFunctionsTest.kt index 9f9a7107..f253b4f5 100644 --- a/core/src/test/kotlin/ch/ergon/dope/buildTest/AggregateFunctionsTest.kt +++ b/core/src/test/kotlin/ch/ergon/dope/buildTest/AggregateFunctionsTest.kt @@ -8,9 +8,9 @@ import ch.ergon.dope.helper.someNumberArrayField import ch.ergon.dope.helper.someNumberField import ch.ergon.dope.helper.someStringArrayField import ch.ergon.dope.helper.someStringField -import ch.ergon.dope.resolvable.expression.alias import ch.ergon.dope.resolvable.expression.unaliased.aggregator.AggregateQuantifier.ALL import ch.ergon.dope.resolvable.expression.unaliased.aggregator.AggregateQuantifier.DISTINCT +import ch.ergon.dope.resolvable.expression.unaliased.aggregator.alias import ch.ergon.dope.resolvable.expression.unaliased.aggregator.arrayAggregate import ch.ergon.dope.resolvable.expression.unaliased.aggregator.avg import ch.ergon.dope.resolvable.expression.unaliased.aggregator.count 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 ac9a78ea..de621761 100644 --- a/core/src/test/kotlin/ch/ergon/dope/buildTest/JoinClauseTest.kt +++ b/core/src/test/kotlin/ch/ergon/dope/buildTest/JoinClauseTest.kt @@ -5,7 +5,7 @@ import ch.ergon.dope.helper.someBucket import ch.ergon.dope.helper.someNumberField import ch.ergon.dope.helper.someStringField import ch.ergon.dope.helper.unifyString -import ch.ergon.dope.resolvable.expression.alias +import ch.ergon.dope.resolvable.expression.unaliased.aggregator.alias import ch.ergon.dope.resolvable.expression.unaliased.aggregator.min import ch.ergon.dope.resolvable.expression.unaliased.type.logical.and import ch.ergon.dope.resolvable.expression.unaliased.type.meta.meta diff --git a/core/src/test/kotlin/ch/ergon/dope/buildTest/ObjectTest.kt b/core/src/test/kotlin/ch/ergon/dope/buildTest/ObjectTest.kt index 985bdce8..d89f5f5d 100644 --- a/core/src/test/kotlin/ch/ergon/dope/buildTest/ObjectTest.kt +++ b/core/src/test/kotlin/ch/ergon/dope/buildTest/ObjectTest.kt @@ -4,13 +4,12 @@ import ch.ergon.dope.DopeQueryManager import ch.ergon.dope.QueryBuilder import ch.ergon.dope.helper.ManagerDependentTest import ch.ergon.dope.helper.someBucket -import ch.ergon.dope.helper.someNumberField import ch.ergon.dope.helper.someObjectField import ch.ergon.dope.helper.someString +import ch.ergon.dope.helper.someStringArrayField import ch.ergon.dope.helper.someStringField import ch.ergon.dope.resolvable.expression.alias import ch.ergon.dope.resolvable.expression.unaliased.type.access.get -import ch.ergon.dope.resolvable.expression.unaliased.type.arithmetic.add import ch.ergon.dope.resolvable.expression.unaliased.type.asParameter import ch.ergon.dope.resolvable.expression.unaliased.type.collection.any import ch.ergon.dope.resolvable.expression.unaliased.type.function.stringfunction.upper @@ -171,15 +170,15 @@ class ObjectTest : ManagerDependentTest { } @Test - fun `should support object field on aliased sub select`() { - val subQuery = create.selectDistinct(someStringField(), someNumberField()).from(someBucket("other")).alias("subQuery") - val expected = "SELECT ANY `iterator1` IN `subQuery` SATISFIES `iterator1`.`someString` = \"something\" END, " + - "(`subQuery`[0].`asdf` + 5) AS `cool` FROM (SELECT DISTINCT `stringField`, `numberField` FROM `other`) AS `subQuery`" + fun `should support range operations on aliased sub select`() { + val subQuery = create.selectRaw(someStringArrayField()).from(someBucket("other")).alias("subQuery") + val expected = "SELECT ANY `iterator1` IN `subQuery` SATISFIES `iterator1` = \"something\" END, " + + "`subQuery`[0] AS `cool` FROM (SELECT RAW `stringArrayField` FROM `other`) AS `subQuery`" val actual: String = create .select( - subQuery.any { it.getString(someString()).isEqualTo("something") }, - subQuery.get(0).getNumber("asdf").add(5).alias("cool"), + subQuery.any { it.isEqualTo("something") }, + subQuery.get(0).alias("cool"), ).from( subQuery, ) diff --git a/core/src/test/kotlin/ch/ergon/dope/buildTest/UnnestClauseTest.kt b/core/src/test/kotlin/ch/ergon/dope/buildTest/UnnestClauseTest.kt index 88aa2fbd..d5d30cf9 100644 --- a/core/src/test/kotlin/ch/ergon/dope/buildTest/UnnestClauseTest.kt +++ b/core/src/test/kotlin/ch/ergon/dope/buildTest/UnnestClauseTest.kt @@ -6,7 +6,7 @@ import ch.ergon.dope.helper.someBucket import ch.ergon.dope.helper.someNumberArrayField import ch.ergon.dope.helper.someStringArrayField import ch.ergon.dope.helper.someStringField -import ch.ergon.dope.resolvable.expression.AliasedExpression +import ch.ergon.dope.resolvable.expression.AliasedTypeExpression import ch.ergon.dope.resolvable.expression.alias import ch.ergon.dope.resolvable.expression.unaliased.type.asParameter import ch.ergon.dope.resolvable.expression.unaliased.type.logical.and @@ -34,7 +34,7 @@ class UnnestClauseTest { val aField = listOf("a".toDopeType()).toDopeType() val expected = "SELECT * FROM `someBucket` UNNEST [\"a\"] AS `a`" - val alias: AliasedExpression> = aField.alias("a") + val alias: AliasedTypeExpression> = aField.alias("a") val actual: String = create .selectFrom(airline) .unnest(alias) diff --git a/core/src/test/kotlin/ch/ergon/dope/helper/Builder.kt b/core/src/test/kotlin/ch/ergon/dope/helper/Builder.kt index b7629229..6b509d2e 100644 --- a/core/src/test/kotlin/ch/ergon/dope/helper/Builder.kt +++ b/core/src/test/kotlin/ch/ergon/dope/helper/Builder.kt @@ -4,8 +4,6 @@ import ch.ergon.dope.resolvable.clause.model.OrderByType import ch.ergon.dope.resolvable.clause.model.OrderByType.ASC import ch.ergon.dope.resolvable.clause.model.OrderExpression import ch.ergon.dope.resolvable.expression.TypeExpression -import ch.ergon.dope.resolvable.expression.UnaliasedExpression -import ch.ergon.dope.resolvable.expression.unaliased.aggregator.CountAsteriskExpression import ch.ergon.dope.resolvable.expression.unaliased.type.Field import ch.ergon.dope.resolvable.expression.unaliased.type.TRUE import ch.ergon.dope.resolvable.expression.unaliased.type.conditional.CaseClass @@ -33,8 +31,6 @@ fun someObjectField(name: String = "objectField", bucket: Bucket = someBucket("" fun someBooleanExpression() = TRUE -fun someUnaliasedExpression() = CountAsteriskExpression() - fun someNumberArrayField(name: String = "numberArrayField", bucket: Bucket = someBucket("")) = Field>(name, getBucketName(bucket)) @@ -64,8 +60,8 @@ fun someCaseClass(expression: TypeExpression) = CaseClass( ) fun someStringSearchNumberResult( - searchExpression: UnaliasedExpression = someString().toDopeType(), - resultExpression: UnaliasedExpression = someNumber().toDopeType(), + searchExpression: TypeExpression = someString().toDopeType(), + resultExpression: TypeExpression = someNumber().toDopeType(), ) = SearchResult(searchExpression, resultExpression) fun someOrderExpression(typeExpression: TypeExpression = someStringField(), orderByType: OrderByType = ASC) = OrderExpression( diff --git a/core/src/test/kotlin/ch/ergon/dope/helper/ClauseBuilder.kt b/core/src/test/kotlin/ch/ergon/dope/helper/ClauseBuilder.kt index e451888a..4307a597 100644 --- a/core/src/test/kotlin/ch/ergon/dope/helper/ClauseBuilder.kt +++ b/core/src/test/kotlin/ch/ergon/dope/helper/ClauseBuilder.kt @@ -5,16 +5,16 @@ import ch.ergon.dope.resolvable.clause.model.FromClause import ch.ergon.dope.resolvable.clause.model.SelectClause import ch.ergon.dope.resolvable.clause.model.SelectRawClause 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.Asterisk import ch.ergon.dope.resolvable.expression.TypeExpression import ch.ergon.dope.resolvable.fromable.Bucket +import ch.ergon.dope.resolvable.fromable.Selectable import ch.ergon.dope.resolvable.fromable.UnaliasedBucket import ch.ergon.dope.validtype.BooleanType import ch.ergon.dope.validtype.NumberType import ch.ergon.dope.validtype.StringType -fun someSelectClause(expression: Expression = AsteriskExpression()) = SelectClause(expression) +fun someSelectClause(selectable: Selectable = Asterisk()) = SelectClause(selectable) fun someSelectRawClause() = someStringSelectRawClause() diff --git a/core/src/test/kotlin/ch/ergon/dope/resolvable/clause/ReturningClauseTest.kt b/core/src/test/kotlin/ch/ergon/dope/resolvable/clause/ReturningClauseTest.kt index 1f6072dd..eea00b5f 100644 --- a/core/src/test/kotlin/ch/ergon/dope/resolvable/clause/ReturningClauseTest.kt +++ b/core/src/test/kotlin/ch/ergon/dope/resolvable/clause/ReturningClauseTest.kt @@ -2,14 +2,23 @@ package ch.ergon.dope.resolvable.clause import ch.ergon.dope.DopeQuery import ch.ergon.dope.DopeQueryManager +import ch.ergon.dope.QueryBuilder import ch.ergon.dope.helper.ManagerDependentTest +import ch.ergon.dope.helper.someBucket import ch.ergon.dope.helper.someDeleteClause import ch.ergon.dope.helper.someNumberArrayField import ch.ergon.dope.helper.someNumberField import ch.ergon.dope.helper.someStringField import ch.ergon.dope.helper.someUpdateClause import ch.ergon.dope.resolvable.clause.model.DeleteReturningClause +import ch.ergon.dope.resolvable.clause.model.DeleteReturningSingleClause +import ch.ergon.dope.resolvable.clause.model.ReturningType.ELEMENT +import ch.ergon.dope.resolvable.clause.model.ReturningType.RAW +import ch.ergon.dope.resolvable.clause.model.ReturningType.VALUE import ch.ergon.dope.resolvable.clause.model.UpdateReturningClause +import ch.ergon.dope.resolvable.clause.model.UpdateReturningSingleClause +import ch.ergon.dope.resolvable.expression.Asterisk +import ch.ergon.dope.resolvable.expression.unaliased.type.function.stringfunction.concat import kotlin.test.Test import kotlin.test.assertEquals @@ -28,12 +37,96 @@ class ReturningClauseTest : ManagerDependentTest { assertEquals(expected, actual) } + @Test + fun `should support delete returning with asterisk`() { + val expected = DopeQuery( + queryString = "DELETE FROM `someBucket` RETURNING *", + ) + val underTest = DeleteReturningClause(Asterisk(), parentClause = someDeleteClause()) + + val actual = underTest.toDopeQuery(manager) + + assertEquals(expected, actual) + } + + @Test + fun `should support delete returning raw`() { + val expected = DopeQuery( + queryString = "DELETE FROM `someBucket` RETURNING RAW `stringField`", + ) + val underTest = DeleteReturningSingleClause(someStringField(), RAW, parentClause = someDeleteClause()) + + val actual = underTest.toDopeQuery(manager) + + assertEquals(expected, actual) + } + + @Test + fun `should support delete returning value`() { + val expected = DopeQuery( + queryString = "DELETE FROM `someBucket` RETURNING VALUE `stringField`", + ) + val underTest = DeleteReturningSingleClause(someStringField(), VALUE, parentClause = someDeleteClause()) + + val actual = underTest.toDopeQuery(manager) + + assertEquals(expected, actual) + } + + @Test + fun `should support delete returning element`() { + val expected = DopeQuery( + queryString = "DELETE FROM `someBucket` RETURNING ELEMENT `stringField`", + ) + val underTest = DeleteReturningSingleClause(someStringField(), ELEMENT, parentClause = someDeleteClause()) + + val actual = underTest.toDopeQuery(manager) + + assertEquals(expected, actual) + } + @Test fun `should support delete returning with multiple fields`() { val expected = DopeQuery( queryString = "DELETE FROM `someBucket` RETURNING `stringField`, `numberField`", ) - val underTest = DeleteReturningClause(someStringField(), someNumberField(), parentClause = someDeleteClause()) + val underTest = DeleteReturningClause( + someStringField(), + someNumberField(), + parentClause = someDeleteClause(), + ) + + val actual = underTest.toDopeQuery(manager) + + assertEquals(expected, actual) + } + + @Test + fun `should support delete returning with multiple fields, functions and asterisk`() { + val expected = DopeQuery( + queryString = "DELETE FROM `someBucket` RETURNING CONCAT(`stringField`, \"test\"), *, `numberField`", + ) + val underTest = DeleteReturningClause( + concat(someStringField(), "test"), + Asterisk(), + someNumberField(), + parentClause = someDeleteClause(), + ) + + val actual = underTest.toDopeQuery(manager) + + assertEquals(expected, actual) + } + + @Test + fun `should support delete returning with aliased subquery`() { + val expected = DopeQuery( + queryString = "DELETE FROM `someBucket` RETURNING (SELECT * FROM `someBucket`) AS `sub`", + ) + val underTest = DeleteReturningClause( + QueryBuilder().selectAsterisk().from(someBucket()).alias("sub"), + parentClause = someDeleteClause(), + ) val actual = underTest.toDopeQuery(manager) @@ -56,13 +149,35 @@ class ReturningClauseTest : ManagerDependentTest { val stringField = someStringField() val numberArrayField = someNumberArrayField() val parentClause = someDeleteClause() - val expected = DeleteReturningClause(stringField, numberArrayField, parentClause = parentClause) + val expected = DeleteReturningClause( + stringField, + numberArrayField, + parentClause = parentClause, + ) val actual = parentClause.returning(stringField, numberArrayField) assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager)) } + @Test + fun `should support delete returning with multiple fields, functions and asterisk extension`() { + val stringConcatenation = concat(someStringField(), "test") + val asterisk = Asterisk() + val numberArrayField = someNumberArrayField() + val parentClause = someDeleteClause() + val expected = DeleteReturningClause( + stringConcatenation, + asterisk, + numberArrayField, + parentClause = parentClause, + ) + + val actual = parentClause.returning(stringConcatenation, asterisk, numberArrayField) + + assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager)) + } + @Test fun `should support update returning`() { val expected = DopeQuery( @@ -76,11 +191,63 @@ class ReturningClauseTest : ManagerDependentTest { } @Test - fun `should support returning with multiple fields`() { + fun `should support update returning with asterisk`() { + val expected = DopeQuery( + queryString = "UPDATE `someBucket` RETURNING *", + ) + val underTest = UpdateReturningClause(Asterisk(), parentClause = someUpdateClause()) + + val actual = underTest.toDopeQuery(manager) + + assertEquals(expected, actual) + } + + @Test + fun `should support update returning raw`() { + val expected = DopeQuery( + queryString = "UPDATE `someBucket` RETURNING RAW `stringField`", + ) + val underTest = UpdateReturningSingleClause(someStringField(), RAW, parentClause = someUpdateClause()) + + val actual = underTest.toDopeQuery(manager) + + assertEquals(expected, actual) + } + + @Test + fun `should support update returning value`() { + val expected = DopeQuery( + queryString = "UPDATE `someBucket` RETURNING VALUE `stringField`", + ) + val underTest = UpdateReturningSingleClause(someStringField(), VALUE, parentClause = someUpdateClause()) + + val actual = underTest.toDopeQuery(manager) + + assertEquals(expected, actual) + } + + @Test + fun `should support update returning element`() { + val expected = DopeQuery( + queryString = "UPDATE `someBucket` RETURNING ELEMENT `stringField`", + ) + val underTest = UpdateReturningSingleClause(someStringField(), ELEMENT, parentClause = someUpdateClause()) + + val actual = underTest.toDopeQuery(manager) + + assertEquals(expected, actual) + } + + @Test + fun `should support update returning with multiple fields`() { val expected = DopeQuery( queryString = "UPDATE `someBucket` RETURNING `stringField`, `numberField`", ) - val underTest = UpdateReturningClause(someStringField(), someNumberField(), parentClause = someUpdateClause()) + val underTest = UpdateReturningClause( + someStringField(), + someNumberField(), + parentClause = someUpdateClause(), + ) val actual = underTest.toDopeQuery(manager) @@ -88,7 +255,24 @@ class ReturningClauseTest : ManagerDependentTest { } @Test - fun `should support returning function`() { + fun `should support update returning with multiple fields, functions and asterisk`() { + val expected = DopeQuery( + queryString = "UPDATE `someBucket` RETURNING CONCAT(`stringField`, \"test\"), *, `numberField`", + ) + val underTest = UpdateReturningClause( + concat(someStringField(), "test"), + Asterisk(), + someNumberField(), + parentClause = someUpdateClause(), + ) + + val actual = underTest.toDopeQuery(manager) + + assertEquals(expected, actual) + } + + @Test + fun `should support update returning function`() { val stringField = someStringField() val parentClause = someUpdateClause() val expected = UpdateReturningClause(stringField, parentClause = parentClause) @@ -99,14 +283,36 @@ class ReturningClauseTest : ManagerDependentTest { } @Test - fun `should support returning function with multiple fields`() { + fun `should support update returning function with multiple fields`() { val stringField = someStringField() val numberArrayField = someNumberArrayField() val parentClause = someUpdateClause() - val expected = UpdateReturningClause(stringField, numberArrayField, parentClause = parentClause) + val expected = UpdateReturningClause( + stringField, + numberArrayField, + parentClause = parentClause, + ) val actual = parentClause.returning(stringField, numberArrayField) assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager)) } + + @Test + fun `should support update returning with multiple fields, functions and asterisk extension`() { + val stringConcatenation = concat(someStringField(), "test") + val asterisk = Asterisk() + val numberArrayField = someNumberArrayField() + val parentClause = someUpdateClause() + val expected = UpdateReturningClause( + stringConcatenation, + asterisk, + numberArrayField, + parentClause = parentClause, + ) + + val actual = parentClause.returning(stringConcatenation, asterisk, numberArrayField) + + assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager)) + } } diff --git a/core/src/test/kotlin/ch/ergon/dope/resolvable/expression/AliasedExpressionTest.kt b/core/src/test/kotlin/ch/ergon/dope/resolvable/expression/AliasedExpressionTest.kt index 9b2848a4..054872dc 100644 --- a/core/src/test/kotlin/ch/ergon/dope/resolvable/expression/AliasedExpressionTest.kt +++ b/core/src/test/kotlin/ch/ergon/dope/resolvable/expression/AliasedExpressionTest.kt @@ -6,8 +6,11 @@ import ch.ergon.dope.DopeQueryManager import ch.ergon.dope.helper.ManagerDependentTest import ch.ergon.dope.helper.someBoolean import ch.ergon.dope.helper.someNumber +import ch.ergon.dope.helper.someSelectClause import ch.ergon.dope.helper.someString import ch.ergon.dope.helper.someStringField +import ch.ergon.dope.resolvable.expression.unaliased.aggregator.AliasedAggregateExpression +import ch.ergon.dope.resolvable.expression.unaliased.aggregator.countAsterisk import ch.ergon.dope.resolvable.expression.unaliased.type.asParameter import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType import kotlin.test.Test @@ -18,10 +21,22 @@ class AliasedExpressionTest : ManagerDependentTest { @Test fun `should support aliased expression`() { + val expected = DopeQuery( + queryString = "COUNT(*) AS `count`", + ) + val underTest = AliasedAggregateExpression(countAsterisk(), "count") + + val actual = underTest.toDopeQuery(manager) + + assertEquals(expected, actual) + } + + @Test + fun `should support aliased type expression`() { val expected = DopeQuery( queryString = "`stringField` AS `test`", ) - val underTest = AliasedExpression(someStringField(), "test") + val underTest = AliasedTypeExpression(someStringField(), "test") val actual = underTest.toDopeQuery(manager) @@ -35,7 +50,7 @@ class AliasedExpressionTest : ManagerDependentTest { queryString = "$1 AS `test`", DopeParameters(positionalParameters = listOf(parameterValue)), ) - val underTest = AliasedExpression(parameterValue.asParameter(), "test") + val underTest = AliasedTypeExpression(parameterValue.asParameter(), "test") val actual = underTest.toDopeQuery(manager) @@ -50,7 +65,7 @@ class AliasedExpressionTest : ManagerDependentTest { queryString = "\$$parameterName AS `test`", DopeParameters(namedParameters = mapOf(parameterName to parameterValue)), ) - val underTest = AliasedExpression(parameterValue.asParameter(parameterName), "test") + val underTest = AliasedTypeExpression(parameterValue.asParameter(parameterName), "test") val actual = underTest.toDopeQuery(manager) @@ -59,44 +74,55 @@ class AliasedExpressionTest : ManagerDependentTest { @Test fun `should support alias function type`() { - val unaliasedExpression = someStringField() + val typeExpression = someStringField() val alias = "alias" - val expected = AliasedExpression(unaliasedExpression, alias) + val expected = AliasedTypeExpression(typeExpression, alias) - val actual = unaliasedExpression.alias(alias) + val actual = typeExpression.alias(alias) assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager)) } @Test fun `should support alias function number`() { - val unaliasedExpression = someNumber() + val number = someNumber() val alias = "alias" - val expected = AliasedExpression(unaliasedExpression.toDopeType(), alias) + val expected = AliasedTypeExpression(number.toDopeType(), alias) - val actual = unaliasedExpression.alias(alias) + val actual = number.alias(alias) assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager)) } @Test fun `should support alias function string`() { - val unaliasedExpression = someString() + val string = someString() val alias = "alias" - val expected = AliasedExpression(unaliasedExpression.toDopeType(), alias) + val expected = AliasedTypeExpression(string.toDopeType(), alias) - val actual = unaliasedExpression.alias(alias) + val actual = string.alias(alias) assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager)) } @Test fun `should support alias function boolean`() { - val unaliasedExpression = someBoolean() + val boolean = someBoolean() + val alias = "alias" + val expected = AliasedTypeExpression(boolean.toDopeType(), alias) + + val actual = boolean.alias(alias) + + assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager)) + } + + @Test + fun `should support alias function select expression`() { + val selectExpression = someSelectClause().asExpression() val alias = "alias" - val expected = AliasedExpression(unaliasedExpression.toDopeType(), alias) + val expected = AliasedTypeExpression(selectExpression, alias) - val actual = unaliasedExpression.alias(alias) + val actual = selectExpression.alias(alias) assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager)) } diff --git a/core/src/test/kotlin/ch/ergon/dope/resolvable/expression/AsteriskExpressionTest.kt b/core/src/test/kotlin/ch/ergon/dope/resolvable/expression/AsteriskTest.kt similarity index 83% rename from core/src/test/kotlin/ch/ergon/dope/resolvable/expression/AsteriskExpressionTest.kt rename to core/src/test/kotlin/ch/ergon/dope/resolvable/expression/AsteriskTest.kt index 2bb062c6..c1a2b522 100644 --- a/core/src/test/kotlin/ch/ergon/dope/resolvable/expression/AsteriskExpressionTest.kt +++ b/core/src/test/kotlin/ch/ergon/dope/resolvable/expression/AsteriskTest.kt @@ -7,7 +7,7 @@ import ch.ergon.dope.helper.someBucket import kotlin.test.Test import kotlin.test.assertEquals -class AsteriskExpressionTest : ManagerDependentTest { +class AsteriskTest : ManagerDependentTest { override lateinit var manager: DopeQueryManager @Test @@ -15,7 +15,7 @@ class AsteriskExpressionTest : ManagerDependentTest { val expected = DopeQuery( queryString = "*", ) - val underTest = AsteriskExpression() + val underTest = Asterisk() val actual = underTest.toDopeQuery(manager) @@ -27,7 +27,7 @@ class AsteriskExpressionTest : ManagerDependentTest { val expected = DopeQuery( queryString = "`someBucket`.*", ) - val underTest = AsteriskExpression(someBucket()) + val underTest = Asterisk(someBucket()) val actual = underTest.toDopeQuery(manager) diff --git a/core/src/test/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/conditional/Nvl2ExpressionTest.kt b/core/src/test/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/conditional/Nvl2ExpressionTest.kt index 4dafa3b0..f3cb1bc6 100644 --- a/core/src/test/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/conditional/Nvl2ExpressionTest.kt +++ b/core/src/test/kotlin/ch/ergon/dope/resolvable/expression/unaliased/type/conditional/Nvl2ExpressionTest.kt @@ -10,7 +10,6 @@ import ch.ergon.dope.helper.someNumber import ch.ergon.dope.helper.someNumberField import ch.ergon.dope.helper.someString import ch.ergon.dope.helper.someStringField -import ch.ergon.dope.helper.someUnaliasedExpression import ch.ergon.dope.resolvable.expression.unaliased.type.asParameter import ch.ergon.dope.resolvable.expression.unaliased.type.function.conditional.Nvl2Expression import ch.ergon.dope.resolvable.expression.unaliased.type.function.conditional.nvl2 @@ -163,7 +162,7 @@ class Nvl2ExpressionTest : ManagerDependentTest { @Test fun `should support nvl2 function expression expression`() { - val initialExpression = someUnaliasedExpression() + val initialExpression = someNumberField() val valueIfExists = someStringField() val valueIfNotExists = someStringField() val expected = Nvl2Expression(initialExpression, valueIfExists, valueIfNotExists) @@ -175,7 +174,7 @@ class Nvl2ExpressionTest : ManagerDependentTest { @Test fun `should support nvl2 function expression number`() { - val initialExpression = someUnaliasedExpression() + val initialExpression = someNumberField() val valueIfExists = someNumberField() val valueIfNotExists = someNumber() val expected = Nvl2Expression(initialExpression, valueIfExists, valueIfNotExists.toDopeType()) @@ -187,7 +186,7 @@ class Nvl2ExpressionTest : ManagerDependentTest { @Test fun `should support nvl2 function expression string`() { - val initialExpression = someUnaliasedExpression() + val initialExpression = someNumberField() val valueIfExists = someStringField() val valueIfNotExists = someString() val expected = Nvl2Expression(initialExpression, valueIfExists, valueIfNotExists.toDopeType()) @@ -199,7 +198,7 @@ class Nvl2ExpressionTest : ManagerDependentTest { @Test fun `should support nvl2 function expression boolean`() { - val initialExpression = someUnaliasedExpression() + val initialExpression = someNumberField() val valueIfExists = someBooleanField() val valueIfNotExists = someBoolean() val expected = Nvl2Expression(initialExpression, valueIfExists, valueIfNotExists.toDopeType()) @@ -211,7 +210,7 @@ class Nvl2ExpressionTest : ManagerDependentTest { @Test fun `should support nvl2 function number expression`() { - val initialExpression = someUnaliasedExpression() + val initialExpression = someNumberField() val valueIfExists = someNumber() val valueIfNotExists = someNumberField() val expected = Nvl2Expression(initialExpression, valueIfExists.toDopeType(), valueIfNotExists) @@ -223,7 +222,7 @@ class Nvl2ExpressionTest : ManagerDependentTest { @Test fun `should support nvl2 function string expression`() { - val initialExpression = someUnaliasedExpression() + val initialExpression = someNumberField() val valueIfExists = someString() val valueIfNotExists = someStringField() val expected = Nvl2Expression(initialExpression, valueIfExists.toDopeType(), valueIfNotExists) @@ -235,7 +234,7 @@ class Nvl2ExpressionTest : ManagerDependentTest { @Test fun `should support nvl2 function boolean expression`() { - val initialExpression = someUnaliasedExpression() + val initialExpression = someNumberField() val valueIfExists = someBoolean() val valueIfNotExists = someBooleanField() val expected = Nvl2Expression(initialExpression, valueIfExists.toDopeType(), valueIfNotExists) @@ -247,7 +246,7 @@ class Nvl2ExpressionTest : ManagerDependentTest { @Test fun `should support nvl2 function number number`() { - val initialExpression = someUnaliasedExpression() + val initialExpression = someNumberField() val valueIfExists = someNumber() val valueIfNotExists = someNumber() val expected = Nvl2Expression(initialExpression, valueIfExists.toDopeType(), valueIfNotExists.toDopeType()) @@ -259,7 +258,7 @@ class Nvl2ExpressionTest : ManagerDependentTest { @Test fun `should support nvl2 function string string`() { - val initialExpression = someUnaliasedExpression() + val initialExpression = someNumberField() val valueIfExists = someString() val valueIfNotExists = someString() val expected = Nvl2Expression(initialExpression, valueIfExists.toDopeType(), valueIfNotExists.toDopeType()) @@ -271,7 +270,7 @@ class Nvl2ExpressionTest : ManagerDependentTest { @Test fun `should support nvl2 function boolean boolean`() { - val initialExpression = someUnaliasedExpression() + val initialExpression = someNumberField() val valueIfExists = someBoolean() val valueIfNotExists = someBoolean() val expected = Nvl2Expression(initialExpression, valueIfExists.toDopeType(), valueIfNotExists.toDopeType()) diff --git a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/QueryBuilder.kt b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/QueryBuilder.kt index 09b7a60a..246423a0 100644 --- a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/QueryBuilder.kt +++ b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/QueryBuilder.kt @@ -1,7 +1,7 @@ package ch.ergon.dope.extension import ch.ergon.dope.QueryBuilder -import ch.ergon.dope.resolvable.expression.Expression +import ch.ergon.dope.resolvable.fromable.Selectable import ch.ergon.dope.toDopeType import com.schwarz.crystalapi.schema.CMJsonField import com.schwarz.crystalapi.schema.CMJsonList @@ -10,19 +10,19 @@ import com.schwarz.crystalapi.schema.CMType fun QueryBuilder.select(expression: CMType, vararg expressions: CMType) = select(expression.toDopeType(), *expressions.map { it.toDopeType() }.toTypedArray()) -fun QueryBuilder.select(firstExpression: Expression, secondExpression: CMType, vararg expressions: CMType) = +fun QueryBuilder.select(firstExpression: Selectable, secondExpression: CMType, vararg expressions: CMType) = select(firstExpression, *listOf(secondExpression, *expressions).map { it.toDopeType() }.toTypedArray()) -fun QueryBuilder.select(firstExpression: CMType, secondExpression: Expression, vararg expressions: Expression) = +fun QueryBuilder.select(firstExpression: CMType, secondExpression: Selectable, vararg expressions: Selectable) = select(firstExpression.toDopeType(), secondExpression, *expressions) fun QueryBuilder.selectDistinct(expression: CMType, vararg expressions: CMType) = selectDistinct(expression.toDopeType(), *expressions.map { it.toDopeType() }.toTypedArray()) -fun QueryBuilder.selectDistinct(firstExpression: Expression, secondExpression: CMType, vararg expressions: CMType) = +fun QueryBuilder.selectDistinct(firstExpression: Selectable, secondExpression: CMType, vararg expressions: CMType) = selectDistinct(firstExpression, *listOf(secondExpression, *expressions).map { it.toDopeType() }.toTypedArray()) -fun QueryBuilder.selectDistinct(firstExpression: CMType, secondExpression: Expression, vararg expressions: Expression) = +fun QueryBuilder.selectDistinct(firstExpression: CMType, secondExpression: Selectable, vararg expressions: Selectable) = selectDistinct(firstExpression.toDopeType(), secondExpression, *expressions) @JvmName("selectRawNumber") diff --git a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/ArrayAggregate.kt b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/ArrayAggregate.kt index 22dfaab2..8ee62ed6 100644 --- a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/ArrayAggregate.kt +++ b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/ArrayAggregate.kt @@ -1,33 +1,31 @@ package ch.ergon.dope.extension.aggregator import ch.ergon.dope.resolvable.expression.unaliased.aggregator.AggregateQuantifier -import ch.ergon.dope.resolvable.expression.unaliased.aggregator.ArrayAggregateExpression import ch.ergon.dope.resolvable.expression.unaliased.aggregator.arrayAggregate import ch.ergon.dope.toDopeType -import ch.ergon.dope.validtype.ValidType import com.schwarz.crystalapi.schema.CMJsonField import com.schwarz.crystalapi.schema.CMJsonList @JvmName("arrayAggNumber") -fun arrayAggregate(field: CMJsonField, quantifier: AggregateQuantifier? = null): - ArrayAggregateExpression = arrayAggregate(field.toDopeType(), quantifier) +fun arrayAggregate(field: CMJsonField, quantifier: AggregateQuantifier? = null) = + arrayAggregate(field.toDopeType(), quantifier) @JvmName("arrayAggString") -fun arrayAggregate(field: CMJsonField, quantifier: AggregateQuantifier? = null): - ArrayAggregateExpression = arrayAggregate(field.toDopeType(), quantifier) +fun arrayAggregate(field: CMJsonField, quantifier: AggregateQuantifier? = null) = + arrayAggregate(field.toDopeType(), quantifier) @JvmName("arrayAggBoolean") -fun arrayAggregate(field: CMJsonField, quantifier: AggregateQuantifier? = null): - ArrayAggregateExpression = arrayAggregate(field.toDopeType(), quantifier) +fun arrayAggregate(field: CMJsonField, quantifier: AggregateQuantifier? = null) = + arrayAggregate(field.toDopeType(), quantifier) @JvmName("arrayAggNumberArray") -fun arrayAggregate(field: CMJsonList, quantifier: AggregateQuantifier? = null): - ArrayAggregateExpression = arrayAggregate(field.toDopeType(), quantifier) +fun arrayAggregate(field: CMJsonList, quantifier: AggregateQuantifier? = null) = + arrayAggregate(field.toDopeType(), quantifier) @JvmName("arrayAggStringArray") -fun arrayAggregate(field: CMJsonList, quantifier: AggregateQuantifier? = null): - ArrayAggregateExpression = arrayAggregate(field.toDopeType(), quantifier) +fun arrayAggregate(field: CMJsonList, quantifier: AggregateQuantifier? = null) = + arrayAggregate(field.toDopeType(), quantifier) @JvmName("arrayAggBooleanArray") -fun arrayAggregate(field: CMJsonList, quantifier: AggregateQuantifier? = null): - ArrayAggregateExpression = arrayAggregate(field.toDopeType(), quantifier) +fun arrayAggregate(field: CMJsonList, quantifier: AggregateQuantifier? = null) = + arrayAggregate(field.toDopeType(), quantifier) diff --git a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/Count.kt b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/Count.kt index ce980c60..7a0c78a7 100644 --- a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/Count.kt +++ b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/Count.kt @@ -1,32 +1,31 @@ package ch.ergon.dope.extension.aggregator import ch.ergon.dope.resolvable.expression.unaliased.aggregator.AggregateQuantifier -import ch.ergon.dope.resolvable.expression.unaliased.aggregator.CountExpression import ch.ergon.dope.resolvable.expression.unaliased.aggregator.count import ch.ergon.dope.toDopeType import com.schwarz.crystalapi.schema.CMJsonField import com.schwarz.crystalapi.schema.CMJsonList @JvmName("countNumber") -fun count(field: CMJsonField, quantifier: AggregateQuantifier? = null): - CountExpression = count(field.toDopeType(), quantifier) +fun count(field: CMJsonField, quantifier: AggregateQuantifier? = null) = + count(field.toDopeType(), quantifier) @JvmName("countString") -fun count(field: CMJsonField, quantifier: AggregateQuantifier? = null): - CountExpression = count(field.toDopeType(), quantifier) +fun count(field: CMJsonField, quantifier: AggregateQuantifier? = null) = + count(field.toDopeType(), quantifier) @JvmName("countBoolean") -fun count(field: CMJsonField, quantifier: AggregateQuantifier? = null): - CountExpression = count(field.toDopeType(), quantifier) +fun count(field: CMJsonField, quantifier: AggregateQuantifier? = null) = + count(field.toDopeType(), quantifier) @JvmName("countNumber") -fun count(field: CMJsonList, quantifier: AggregateQuantifier? = null): - CountExpression = count(field.toDopeType(), quantifier) +fun count(field: CMJsonList, quantifier: AggregateQuantifier? = null) = + count(field.toDopeType(), quantifier) @JvmName("countString") -fun count(field: CMJsonList, quantifier: AggregateQuantifier? = null): - CountExpression = count(field.toDopeType(), quantifier) +fun count(field: CMJsonList, quantifier: AggregateQuantifier? = null) = + count(field.toDopeType(), quantifier) @JvmName("countBoolean") -fun count(field: CMJsonList, quantifier: AggregateQuantifier? = null): - CountExpression = count(field.toDopeType(), quantifier) +fun count(field: CMJsonList, quantifier: AggregateQuantifier? = null) = + count(field.toDopeType(), quantifier) diff --git a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/Max.kt b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/Max.kt index cbc93f97..31856c19 100644 --- a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/Max.kt +++ b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/Max.kt @@ -1,33 +1,25 @@ package ch.ergon.dope.extension.aggregator import ch.ergon.dope.resolvable.expression.unaliased.aggregator.AggregateQuantifier -import ch.ergon.dope.resolvable.expression.unaliased.aggregator.MaxExpression import ch.ergon.dope.resolvable.expression.unaliased.aggregator.max import ch.ergon.dope.toDopeType -import ch.ergon.dope.validtype.ValidType import com.schwarz.crystalapi.schema.CMJsonField import com.schwarz.crystalapi.schema.CMJsonList @JvmName("maxNumber") -fun max(field: CMJsonField, quantifier: AggregateQuantifier? = null): - MaxExpression = max(field.toDopeType(), quantifier) +fun max(field: CMJsonField, quantifier: AggregateQuantifier? = null) = max(field.toDopeType(), quantifier) @JvmName("maxString") -fun max(field: CMJsonField, quantifier: AggregateQuantifier? = null): - MaxExpression = max(field.toDopeType(), quantifier) +fun max(field: CMJsonField, quantifier: AggregateQuantifier? = null) = max(field.toDopeType(), quantifier) @JvmName("maxBoolean") -fun max(field: CMJsonField, quantifier: AggregateQuantifier? = null): - MaxExpression = max(field.toDopeType(), quantifier) +fun max(field: CMJsonField, quantifier: AggregateQuantifier? = null) = max(field.toDopeType(), quantifier) @JvmName("maxNumber") -fun max(field: CMJsonList, quantifier: AggregateQuantifier? = null): - MaxExpression = max(field.toDopeType(), quantifier) +fun max(field: CMJsonList, quantifier: AggregateQuantifier? = null) = max(field.toDopeType(), quantifier) @JvmName("maxString") -fun max(field: CMJsonList, quantifier: AggregateQuantifier? = null): - MaxExpression = max(field.toDopeType(), quantifier) +fun max(field: CMJsonList, quantifier: AggregateQuantifier? = null) = max(field.toDopeType(), quantifier) @JvmName("maxBoolean") -fun max(field: CMJsonList, quantifier: AggregateQuantifier? = null): - MaxExpression = max(field.toDopeType(), quantifier) +fun max(field: CMJsonList, quantifier: AggregateQuantifier? = null) = max(field.toDopeType(), quantifier) diff --git a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/Min.kt b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/Min.kt index c1534d98..e4936470 100644 --- a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/Min.kt +++ b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/Min.kt @@ -1,33 +1,25 @@ package ch.ergon.dope.extension.aggregator import ch.ergon.dope.resolvable.expression.unaliased.aggregator.AggregateQuantifier -import ch.ergon.dope.resolvable.expression.unaliased.aggregator.MinExpression import ch.ergon.dope.resolvable.expression.unaliased.aggregator.min import ch.ergon.dope.toDopeType -import ch.ergon.dope.validtype.ValidType import com.schwarz.crystalapi.schema.CMJsonField import com.schwarz.crystalapi.schema.CMJsonList @JvmName("minNumber") -fun min(field: CMJsonField, quantifier: AggregateQuantifier? = null): - MinExpression = min(field.toDopeType(), quantifier) +fun min(field: CMJsonField, quantifier: AggregateQuantifier? = null) = min(field.toDopeType(), quantifier) @JvmName("minString") -fun min(field: CMJsonField, quantifier: AggregateQuantifier? = null): - MinExpression = min(field.toDopeType(), quantifier) +fun min(field: CMJsonField, quantifier: AggregateQuantifier? = null) = min(field.toDopeType(), quantifier) @JvmName("minBoolean") -fun min(field: CMJsonField, quantifier: AggregateQuantifier? = null): - MinExpression = min(field.toDopeType(), quantifier) +fun min(field: CMJsonField, quantifier: AggregateQuantifier? = null) = min(field.toDopeType(), quantifier) @JvmName("minNumber") -fun min(field: CMJsonList, quantifier: AggregateQuantifier? = null): - MinExpression = min(field.toDopeType(), quantifier) +fun min(field: CMJsonList, quantifier: AggregateQuantifier? = null) = min(field.toDopeType(), quantifier) @JvmName("minString") -fun min(field: CMJsonList, quantifier: AggregateQuantifier? = null): - MinExpression = min(field.toDopeType(), quantifier) +fun min(field: CMJsonList, quantifier: AggregateQuantifier? = null) = min(field.toDopeType(), quantifier) @JvmName("minBoolean") -fun min(field: CMJsonList, quantifier: AggregateQuantifier? = null): - MinExpression = min(field.toDopeType(), quantifier) +fun min(field: CMJsonList, quantifier: AggregateQuantifier? = null) = min(field.toDopeType(), quantifier) diff --git a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/NumberAggregate.kt b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/NumberAggregate.kt index 5db3567e..aa6904f2 100644 --- a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/NumberAggregate.kt +++ b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/aggregator/NumberAggregate.kt @@ -14,29 +14,28 @@ import ch.ergon.dope.resolvable.expression.unaliased.aggregator.stdDev import ch.ergon.dope.resolvable.expression.unaliased.aggregator.sum import ch.ergon.dope.resolvable.expression.unaliased.aggregator.variance import ch.ergon.dope.toDopeType -import ch.ergon.dope.validtype.NumberType import com.schwarz.crystalapi.schema.CMJsonField @JvmName("avgNumber") fun avg(field: CMJsonField, quantifier: AggregateQuantifier? = null): - AverageExpression = avg(field.toDopeType(), quantifier) + AverageExpression = avg(field.toDopeType(), quantifier) @JvmName("meanNumber") fun mean(field: CMJsonField, quantifier: AggregateQuantifier? = null): - MeanExpression = mean(field.toDopeType(), quantifier) + MeanExpression = mean(field.toDopeType(), quantifier) @JvmName("medianNumber") fun median(field: CMJsonField, quantifier: AggregateQuantifier? = null): - MedianExpression = median(field.toDopeType(), quantifier) + MedianExpression = median(field.toDopeType(), quantifier) @JvmName("sumNumber") fun sum(field: CMJsonField, quantifier: AggregateQuantifier? = null): - SumExpression = sum(field.toDopeType(), quantifier) + SumExpression = sum(field.toDopeType(), quantifier) @JvmName("stdDevNumber") fun stdDev(field: CMJsonField, quantifier: AggregateQuantifier? = null): - StandardDeviationExpression = stdDev(field.toDopeType(), quantifier) + StandardDeviationExpression = stdDev(field.toDopeType(), quantifier) @JvmName("varianceNumber") fun variance(field: CMJsonField, quantifier: AggregateQuantifier? = null): - VarianceExpression = variance(field.toDopeType(), quantifier) + VarianceExpression = variance(field.toDopeType(), quantifier) 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 5d4556dc..516ebe0a 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 @@ -11,6 +11,15 @@ import com.schwarz.crystalapi.schema.CMType fun IDeleteOffsetClause.returning(field: CMType, vararg fields: CMType) = returning(field.toDopeType(), *fields.map { it.toDopeType() }.toTypedArray()) +fun IDeleteOffsetClause.returningRaw(field: CMType) = + returningRaw(field.toDopeType()) + +fun IDeleteOffsetClause.returningValue(field: CMType) = + returningValue(field.toDopeType()) + +fun IDeleteOffsetClause.returningElement(field: CMType) = + returningElement(field.toDopeType()) + fun IDeleteLimitClause.offset(numberExpression: CMJsonField) = offset(numberExpression.toDopeType()) fun IDeleteWhereClause.limit(numberExpression: CMJsonField) = limit(numberExpression.toDopeType()) 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 3853f42c..5ee65821 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 @@ -22,6 +22,15 @@ import com.schwarz.crystalapi.schema.CMType fun IUpdateLimitClause.returning(field: CMType, vararg fields: CMType) = returning(field.toDopeType(), *fields.map { it.toDopeType() }.toTypedArray()) +fun IUpdateLimitClause.returningRaw(field: CMType) = + returningRaw(field.toDopeType()) + +fun IUpdateLimitClause.returningValue(field: CMType) = + returningValue(field.toDopeType()) + +fun IUpdateLimitClause.returningElement(field: CMType) = + returningElement(field.toDopeType()) + fun IUpdateWhereClause.limit(numberField: CMJsonField) = limit(numberField.toDopeType()) fun IUpdateUnsetClause.where(whereExpression: CMJsonField) = where(whereExpression.toDopeType()) diff --git a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/type/conditional/Nvl2.kt b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/type/conditional/Nvl2.kt index 8dfe7b92..3d7aefad 100644 --- a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/type/conditional/Nvl2.kt +++ b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/type/conditional/Nvl2.kt @@ -1,6 +1,6 @@ package ch.ergon.dope.extension.type.conditional -import ch.ergon.dope.resolvable.expression.UnaliasedExpression +import ch.ergon.dope.resolvable.expression.TypeExpression import ch.ergon.dope.resolvable.expression.unaliased.type.function.conditional.nvl2 import ch.ergon.dope.toDopeType import ch.ergon.dope.validtype.ArrayType @@ -58,42 +58,42 @@ fun nvl2( fun nvl2( initialExpression: CMType, valueIfExists: CMJsonField, - valueIfNotExists: UnaliasedExpression, + valueIfNotExists: TypeExpression, ) = nvl2(initialExpression.toDopeType(), valueIfExists.toDopeType(), valueIfNotExists) @JvmName("nvl2CMStringFieldAndStringType") fun nvl2( initialExpression: CMType, valueIfExists: CMJsonField, - valueIfNotExists: UnaliasedExpression, + valueIfNotExists: TypeExpression, ) = nvl2(initialExpression.toDopeType(), valueIfExists.toDopeType(), valueIfNotExists) @JvmName("nvl2CMBooleanFieldAndBooleanType") fun nvl2( initialExpression: CMType, valueIfExists: CMJsonField, - valueIfNotExists: UnaliasedExpression, + valueIfNotExists: TypeExpression, ) = nvl2(initialExpression.toDopeType(), valueIfExists.toDopeType(), valueIfNotExists) @JvmName("nvl2CMNumberListAndArrayNumberType") fun nvl2( initialExpression: CMType, valueIfExists: CMJsonList, - valueIfNotExists: UnaliasedExpression>, + valueIfNotExists: TypeExpression>, ) = nvl2(initialExpression.toDopeType(), valueIfExists.toDopeType(), valueIfNotExists) @JvmName("nvl2CMStringListAndArrayStringType") fun nvl2( initialExpression: CMType, valueIfExists: CMJsonList, - valueIfNotExists: UnaliasedExpression>, + valueIfNotExists: TypeExpression>, ) = nvl2(initialExpression.toDopeType(), valueIfExists.toDopeType(), valueIfNotExists) @JvmName("nvl2CMBooleanListAndArrayBooleanType") fun nvl2( initialExpression: CMType, valueIfExists: CMJsonList, - valueIfNotExists: UnaliasedExpression>, + valueIfNotExists: TypeExpression>, ) = nvl2(initialExpression.toDopeType(), valueIfExists.toDopeType(), valueIfNotExists) @JvmName("nvl2CMNumberFieldAndNumber") @@ -120,42 +120,42 @@ fun nvl2( @JvmName("nvl2NumberTypeAndCMNumberField") fun nvl2( initialExpression: CMType, - valueIfExists: UnaliasedExpression, + valueIfExists: TypeExpression, valueIfNotExists: CMJsonField, ) = nvl2(initialExpression.toDopeType(), valueIfExists, valueIfNotExists.toDopeType()) @JvmName("nvl2StringTypeAndCMStringField") fun nvl2( initialExpression: CMType, - valueIfExists: UnaliasedExpression, + valueIfExists: TypeExpression, valueIfNotExists: CMJsonField, ) = nvl2(initialExpression.toDopeType(), valueIfExists, valueIfNotExists.toDopeType()) @JvmName("nvl2BooleanTypeAndCMBooleanField") fun nvl2( initialExpression: CMType, - valueIfExists: UnaliasedExpression, + valueIfExists: TypeExpression, valueIfNotExists: CMJsonField, ) = nvl2(initialExpression.toDopeType(), valueIfExists, valueIfNotExists.toDopeType()) @JvmName("nvl2ArrayNumberTypeAndCMNumberList") fun nvl2( initialExpression: CMType, - valueIfExists: UnaliasedExpression>, + valueIfExists: TypeExpression>, valueIfNotExists: CMJsonList, ) = nvl2(initialExpression.toDopeType(), valueIfExists, valueIfNotExists.toDopeType()) @JvmName("nvl2ArrayStringTypeAndCMStringList") fun nvl2( initialExpression: CMType, - valueIfExists: UnaliasedExpression>, + valueIfExists: TypeExpression>, valueIfNotExists: CMJsonList, ) = nvl2(initialExpression.toDopeType(), valueIfExists, valueIfNotExists.toDopeType()) @JvmName("nvl2ArrayBooleanTypeAndCMBooleanList") fun nvl2( initialExpression: CMType, - valueIfExists: UnaliasedExpression>, + valueIfExists: TypeExpression>, valueIfNotExists: CMJsonList, ) = nvl2(initialExpression.toDopeType(), valueIfExists, valueIfNotExists.toDopeType()) @@ -200,168 +200,168 @@ fun nvl2( @JvmName("nvl2CMNumberFieldAndCMNumberField") fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: CMJsonField, valueIfNotExists: CMJsonField, ) = nvl2(initialExpression, valueIfExists.toDopeType(), valueIfNotExists.toDopeType()) @JvmName("nvl2CMStringFieldAndCMStringField") fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: CMJsonField, valueIfNotExists: CMJsonField, ) = nvl2(initialExpression, valueIfExists.toDopeType(), valueIfNotExists.toDopeType()) @JvmName("nvl2CMBooleanFieldAndCMBooleanField") fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: CMJsonField, valueIfNotExists: CMJsonField, ) = nvl2(initialExpression, valueIfExists.toDopeType(), valueIfNotExists.toDopeType()) @JvmName("nvl2CMNumberListAndCMNumberList") fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: CMJsonList, valueIfNotExists: CMJsonList, ) = nvl2(initialExpression, valueIfExists.toDopeType(), valueIfNotExists.toDopeType()) @JvmName("nvl2CMStringListAndCMStringList") fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: CMJsonList, valueIfNotExists: CMJsonList, ) = nvl2(initialExpression, valueIfExists.toDopeType(), valueIfNotExists.toDopeType()) @JvmName("nvl2CMBooleanListAndCMBooleanList") fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: CMJsonList, valueIfNotExists: CMJsonList, ) = nvl2(initialExpression, valueIfExists.toDopeType(), valueIfNotExists.toDopeType()) @JvmName("nvl2CMNumberFieldAndNumberType") fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: CMJsonField, - valueIfNotExists: UnaliasedExpression, + valueIfNotExists: TypeExpression, ) = nvl2(initialExpression, valueIfExists.toDopeType(), valueIfNotExists) @JvmName("nvl2CMStringFieldAndStringType") fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: CMJsonField, - valueIfNotExists: UnaliasedExpression, + valueIfNotExists: TypeExpression, ) = nvl2(initialExpression, valueIfExists.toDopeType(), valueIfNotExists) @JvmName("nvl2CMBooleanFieldAndBooleanType") fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: CMJsonField, - valueIfNotExists: UnaliasedExpression, + valueIfNotExists: TypeExpression, ) = nvl2(initialExpression, valueIfExists.toDopeType(), valueIfNotExists) @JvmName("nvl2CMNumberListAndArrayNumberType") fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: CMJsonList, - valueIfNotExists: UnaliasedExpression>, + valueIfNotExists: TypeExpression>, ) = nvl2(initialExpression, valueIfExists.toDopeType(), valueIfNotExists) @JvmName("nvl2CMStringListAndArrayStringType") fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: CMJsonList, - valueIfNotExists: UnaliasedExpression>, + valueIfNotExists: TypeExpression>, ) = nvl2(initialExpression, valueIfExists.toDopeType(), valueIfNotExists) @JvmName("nvl2CMBooleanListAndArrayBooleanType") fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: CMJsonList, - valueIfNotExists: UnaliasedExpression>, + valueIfNotExists: TypeExpression>, ) = nvl2(initialExpression, valueIfExists.toDopeType(), valueIfNotExists) @JvmName("nvl2CMNumberFieldAndNumber") fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: CMJsonField, valueIfNotExists: Number, ) = nvl2(initialExpression, valueIfExists.toDopeType(), valueIfNotExists) @JvmName("nvl2CMStringFieldAndString") fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: CMJsonField, valueIfNotExists: String, ) = nvl2(initialExpression, valueIfExists.toDopeType(), valueIfNotExists) @JvmName("nvl2CMBooleanFieldAndBoolean") fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: CMJsonField, valueIfNotExists: Boolean, ) = nvl2(initialExpression, valueIfExists.toDopeType(), valueIfNotExists) @JvmName("nvl2NumberTypeAndCMNumberField") fun nvl2( - initialExpression: UnaliasedExpression, - valueIfExists: UnaliasedExpression, + initialExpression: TypeExpression, + valueIfExists: TypeExpression, valueIfNotExists: CMJsonField, ) = nvl2(initialExpression, valueIfExists, valueIfNotExists.toDopeType()) @JvmName("nvl2StringTypeAndCMStringField") fun nvl2( - initialExpression: UnaliasedExpression, - valueIfExists: UnaliasedExpression, + initialExpression: TypeExpression, + valueIfExists: TypeExpression, valueIfNotExists: CMJsonField, ) = nvl2(initialExpression, valueIfExists, valueIfNotExists.toDopeType()) @JvmName("nvl2BooleanTypeAndCMBooleanField") fun nvl2( - initialExpression: UnaliasedExpression, - valueIfExists: UnaliasedExpression, + initialExpression: TypeExpression, + valueIfExists: TypeExpression, valueIfNotExists: CMJsonField, ) = nvl2(initialExpression, valueIfExists, valueIfNotExists.toDopeType()) @JvmName("nvl2ArrayNumberTypeAndCMNumberList") fun nvl2( - initialExpression: UnaliasedExpression, - valueIfExists: UnaliasedExpression>, + initialExpression: TypeExpression, + valueIfExists: TypeExpression>, valueIfNotExists: CMJsonList, ) = nvl2(initialExpression, valueIfExists, valueIfNotExists.toDopeType()) @JvmName("nvl2ArrayStringTypeAndCMStringList") fun nvl2( - initialExpression: UnaliasedExpression, - valueIfExists: UnaliasedExpression>, + initialExpression: TypeExpression, + valueIfExists: TypeExpression>, valueIfNotExists: CMJsonList, ) = nvl2(initialExpression, valueIfExists, valueIfNotExists.toDopeType()) @JvmName("nvl2ArrayBooleanTypeAndCMBooleanList") fun nvl2( - initialExpression: UnaliasedExpression, - valueIfExists: UnaliasedExpression>, + initialExpression: TypeExpression, + valueIfExists: TypeExpression>, valueIfNotExists: CMJsonList, ) = nvl2(initialExpression, valueIfExists, valueIfNotExists.toDopeType()) @JvmName("nvl2NumberAndCMNumberField") fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: Number, valueIfNotExists: CMJsonField, ) = nvl2(initialExpression, valueIfExists, valueIfNotExists.toDopeType()) @JvmName("nvl2StringAndCMStringField") fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: String, valueIfNotExists: CMJsonField, ) = nvl2(initialExpression, valueIfExists, valueIfNotExists.toDopeType()) @JvmName("nvl2BooleanAndCMBooleanField") fun nvl2( - initialExpression: UnaliasedExpression, + initialExpression: TypeExpression, valueIfExists: Boolean, valueIfNotExists: CMJsonField, ) = nvl2(initialExpression, valueIfExists, valueIfNotExists.toDopeType()) diff --git a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/type/conditional/SearchResult.kt b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/type/conditional/SearchResult.kt index fb1e8165..97afe442 100644 --- a/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/type/conditional/SearchResult.kt +++ b/crystal-map-connector/src/main/kotlin/ch/ergon/dope/extension/type/conditional/SearchResult.kt @@ -1,6 +1,6 @@ package ch.ergon.dope.extension.type.conditional -import ch.ergon.dope.resolvable.expression.UnaliasedExpression +import ch.ergon.dope.resolvable.expression.TypeExpression import ch.ergon.dope.resolvable.expression.unaliased.type.function.conditional.SearchResult import ch.ergon.dope.toDopeType import ch.ergon.dope.validtype.BooleanType @@ -13,33 +13,33 @@ import com.schwarz.crystalapi.schema.CMObjectField import com.schwarz.crystalapi.schema.Schema @JvmName("caseNumberField") -fun CMJsonField.resultsIn(resultExpression: UnaliasedExpression) = +fun CMJsonField.resultsIn(resultExpression: TypeExpression) = SearchResult(toDopeType(), resultExpression) @JvmName("caseStringField") -fun CMJsonField.resultsIn(resultExpression: UnaliasedExpression) = +fun CMJsonField.resultsIn(resultExpression: TypeExpression) = SearchResult(toDopeType(), resultExpression) @JvmName("caseBooleanField") -fun CMJsonField.resultsIn(resultExpression: UnaliasedExpression) = +fun CMJsonField.resultsIn(resultExpression: TypeExpression) = SearchResult(toDopeType(), resultExpression) @JvmName("caseObjectField") -fun CMObjectField.resultsIn(resultExpression: UnaliasedExpression) = +fun CMObjectField.resultsIn(resultExpression: TypeExpression) = SearchResult(toDopeType(), resultExpression) @JvmName("caseNumberField") -fun UnaliasedExpression.resultsIn(resultField: CMJsonField): SearchResult = +fun TypeExpression.resultsIn(resultField: CMJsonField): SearchResult = SearchResult(this, resultField.toDopeType()) @JvmName("caseStringField") -fun UnaliasedExpression.resultsIn(resultField: CMJsonField): SearchResult = +fun TypeExpression.resultsIn(resultField: CMJsonField): SearchResult = SearchResult(this, resultField.toDopeType()) @JvmName("caseBooleanField") -fun UnaliasedExpression.resultsIn(resultField: CMJsonField): SearchResult = +fun TypeExpression.resultsIn(resultField: CMJsonField): SearchResult = SearchResult(this, resultField.toDopeType()) @JvmName("caseObjectField") -fun UnaliasedExpression.resultsIn(resultField: CMObjectField): SearchResult = +fun TypeExpression.resultsIn(resultField: CMObjectField): SearchResult = SearchResult(this, resultField.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 3a36ec2b..9733f5f1 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 @@ -4,6 +4,9 @@ import ch.ergon.dope.DopeQueryManager 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.returningElement +import ch.ergon.dope.extension.clause.returningRaw +import ch.ergon.dope.extension.clause.returningValue import ch.ergon.dope.extension.clause.where import ch.ergon.dope.helper.ManagerDependentTest import ch.ergon.dope.helper.someCMBooleanField @@ -14,7 +17,12 @@ 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.DeleteReturningSingleClause import ch.ergon.dope.resolvable.clause.model.DeleteWhereClause +import ch.ergon.dope.resolvable.clause.model.ReturningType.ELEMENT +import ch.ergon.dope.resolvable.clause.model.ReturningType.RAW +import ch.ergon.dope.resolvable.clause.model.ReturningType.VALUE +import ch.ergon.dope.resolvable.expression.Asterisk import ch.ergon.dope.toDopeType import kotlin.test.Test import kotlin.test.assertEquals @@ -67,14 +75,53 @@ class DeleteClauseTest : ManagerDependentTest { } @Test - fun `should support delete returning with multiple CM`() { + fun `should support delete returning raw with CM`() { + val field = someCMBooleanField() + val parentClause = someDelete() + val expected = DeleteReturningSingleClause(field.toDopeType(), returningType = RAW, parentClause = parentClause) + + val actual = parentClause.returningRaw(field) + + assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager)) + } + + @Test + fun `should support delete returning value with CM`() { + val field = someCMBooleanField() + val parentClause = someDelete() + val expected = DeleteReturningSingleClause(field.toDopeType(), returningType = VALUE, parentClause = parentClause) + + val actual = parentClause.returningValue(field) + + assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager)) + } + + @Test + fun `should support delete returning element with CM`() { + val field = someCMBooleanField() + val parentClause = someDelete() + val expected = DeleteReturningSingleClause(field.toDopeType(), returningType = ELEMENT, parentClause = parentClause) + + val actual = parentClause.returningElement(field) + + assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager)) + } + + @Test + fun `should support delete returning with multiple CM and asterisk`() { val field1 = someCMBooleanField() val field2 = someCMNumberList() val field3 = someCMStringField() val parentClause = someDelete() - val expected = DeleteReturningClause(field1.toDopeType(), field2.toDopeType(), field3.toDopeType(), parentClause = parentClause) - - val actual = parentClause.returning(field1, field2, field3) + val expected = DeleteReturningClause( + field1.toDopeType(), + field2.toDopeType(), + Asterisk(), + field3.toDopeType(), + parentClause = parentClause, + ) + + val actual = parentClause.returning(field1.toDopeType(), field2.toDopeType(), Asterisk(), field3.toDopeType()) assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager)) } 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 a6caac49..dffb4462 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 @@ -3,6 +3,9 @@ package ch.ergon.dope.extensions.clause import ch.ergon.dope.DopeQueryManager import ch.ergon.dope.extension.clause.limit import ch.ergon.dope.extension.clause.returning +import ch.ergon.dope.extension.clause.returningElement +import ch.ergon.dope.extension.clause.returningRaw +import ch.ergon.dope.extension.clause.returningValue import ch.ergon.dope.extension.clause.set import ch.ergon.dope.extension.clause.unset import ch.ergon.dope.extension.clause.where @@ -21,12 +24,17 @@ import ch.ergon.dope.helper.someDate import ch.ergon.dope.helper.someNumber import ch.ergon.dope.helper.someString import ch.ergon.dope.helper.someUpdate +import ch.ergon.dope.resolvable.clause.model.ReturningType.ELEMENT +import ch.ergon.dope.resolvable.clause.model.ReturningType.RAW +import ch.ergon.dope.resolvable.clause.model.ReturningType.VALUE 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.UpdateReturningSingleClause import ch.ergon.dope.resolvable.clause.model.UpdateWhereClause import ch.ergon.dope.resolvable.clause.model.to +import ch.ergon.dope.resolvable.expression.Asterisk import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType import ch.ergon.dope.toDopeType import kotlin.test.Test @@ -638,14 +646,53 @@ class UpdateClauseTest : ManagerDependentTest { } @Test - fun `should support update returning with multiple CM`() { + fun `should support update returning raw with CM`() { + val field = someCMBooleanField() + val parentClause = someUpdate() + val expected = UpdateReturningSingleClause(field.toDopeType(), returningType = RAW, parentClause = parentClause) + + val actual = parentClause.returningRaw(field) + + assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager)) + } + + @Test + fun `should support update returning value with CM`() { + val field = someCMBooleanField() + val parentClause = someUpdate() + val expected = UpdateReturningSingleClause(field.toDopeType(), returningType = VALUE, parentClause = parentClause) + + val actual = parentClause.returningValue(field) + + assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager)) + } + + @Test + fun `should support update returning element with CM`() { + val field = someCMBooleanField() + val parentClause = someUpdate() + val expected = UpdateReturningSingleClause(field.toDopeType(), returningType = ELEMENT, parentClause = parentClause) + + val actual = parentClause.returningElement(field) + + assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager)) + } + + @Test + fun `should support update returning with multiple CM and asterisk`() { val field1 = someCMBooleanField() val field2 = someCMNumberList() val field3 = someCMStringField() val parentClause = someUpdate() - val expected = UpdateReturningClause(field1.toDopeType(), field2.toDopeType(), field3.toDopeType(), parentClause = parentClause) + val expected = UpdateReturningClause( + field1.toDopeType(), + field2.toDopeType(), + Asterisk(), + field3.toDopeType(), + parentClause = parentClause, + ) - val actual = parentClause.returning(field1, field2, field3) + val actual = parentClause.returning(field1.toDopeType(), field2.toDopeType(), Asterisk(), field3.toDopeType()) assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager)) } diff --git a/crystal-map-connector/src/test/kotlin/ch/ergon/dope/helper/Builder.kt b/crystal-map-connector/src/test/kotlin/ch/ergon/dope/helper/Builder.kt index 55028543..8f4bb1b5 100644 --- a/crystal-map-connector/src/test/kotlin/ch/ergon/dope/helper/Builder.kt +++ b/crystal-map-connector/src/test/kotlin/ch/ergon/dope/helper/Builder.kt @@ -5,14 +5,14 @@ import ch.ergon.dope.resolvable.clause.model.FromClause import ch.ergon.dope.resolvable.clause.model.OrderByType import ch.ergon.dope.resolvable.clause.model.SelectClause 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.Asterisk import ch.ergon.dope.resolvable.expression.TypeExpression import ch.ergon.dope.resolvable.expression.unaliased.type.Field import ch.ergon.dope.resolvable.expression.unaliased.type.conditional.CaseClass import ch.ergon.dope.resolvable.fromable.AliasedBucket import ch.ergon.dope.resolvable.fromable.Bucket import ch.ergon.dope.resolvable.fromable.Fromable +import ch.ergon.dope.resolvable.fromable.Selectable import ch.ergon.dope.resolvable.fromable.UnaliasedBucket import ch.ergon.dope.validtype.ArrayType import ch.ergon.dope.validtype.BooleanType @@ -67,7 +67,7 @@ fun someCMConverterStringList(name: String = "cmConverterStringList", path: Stri fun someCMConverterBooleanList(name: String = "cmConverterBooleanList", path: String = "") = CMConverterList(name, path, DateBooleanConverterInstance) -fun someSelect(expression: Expression = AsteriskExpression()) = SelectClause(expression) +fun someSelect(selectable: Selectable = Asterisk()) = SelectClause(selectable) fun someOrderBy(selectClause: SelectClause) = selectClause.orderBy(someNumberField(), OrderByType.ASC) fun someFrom(fromable: Fromable = someBucket(), selectClause: SelectClause = someSelect()) = FromClause(fromable, selectClause)