Skip to content

Commit

Permalink
Merge pull request #40 from ergon/feature/dope-244-use-type-convesion
Browse files Browse the repository at this point in the history
DOPE-244: implemented extensions for CMConverters
  • Loading branch information
jansigi authored Aug 29, 2024
2 parents 8187005 + ddeaa76 commit 0792fc2
Show file tree
Hide file tree
Showing 86 changed files with 1,938 additions and 1,115 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import ch.ergon.dope.validtype.StringType
class SubstringExpression(
private val inStr: TypeExpression<StringType>,
private val startPos: Int,
private val length: Int,
private val length: Int? = null,
) : TypeExpression<StringType>, FunctionOperator {
override fun toDopeQuery(manager: DopeQueryManager): DopeQuery {
val inStrDopeQuery = inStr.toDopeQuery(manager)
Expand All @@ -19,13 +19,13 @@ class SubstringExpression(
symbol = "SUBSTR",
inStrDopeQuery,
startPos.toDopeType().toDopeQuery(manager),
length.toDopeType().toDopeQuery(manager),
length?.toDopeType()?.toDopeQuery(manager),
),
parameters = inStrDopeQuery.parameters,
)
}
}

fun substr(inStr: TypeExpression<StringType>, startPos: Int, length: Int) = SubstringExpression(inStr, startPos, length)
fun substr(inStr: TypeExpression<StringType>, startPos: Int, length: Int? = null) = SubstringExpression(inStr, startPos, length)

fun substr(inStr: String, startPos: Int, length: Int = inStr.length) = substr(inStr.toDopeType(), startPos, length)
fun substr(inStr: String, startPos: Int, length: Int? = null) = substr(inStr.toDopeType(), startPos, length)
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ class StringFunctionsTest : ManagerDependentTest {
@Test
fun `should Support Substring`() {
val expected =
"SELECT SUBSTR(\"N1QL is awesome\", 3, 15) AS `end_of_string`, SUBSTR(\"N1QL is awesome\", 3, 1) AS" +
"SELECT SUBSTR(\"N1QL is awesome\", 3) AS `end_of_string`, SUBSTR(\"N1QL is awesome\", 3, 1) AS" +
" `single_letter`, SUBSTR(\"N1QL is awesome\", 3, 3) AS `three_letters`"

val actual: String = create.select(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,17 @@ class SubstringExpressionTest : ManagerDependentTest {
assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager))
}

@Test
fun `should support substring function type int`() {
val inStr = someStringField("inStr")
val startPos = 1
val expected = SubstringExpression(inStr, startPos)

val actual = substr(inStr, startPos)

assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager))
}

@Test
fun `should support substring function string int int`() {
val inStr = someString("inStr")
Expand All @@ -68,8 +79,7 @@ class SubstringExpressionTest : ManagerDependentTest {
fun `should support substring function string int`() {
val inStr = someString("inStr")
val startPos = 1
val length = inStr.length
val expected = SubstringExpression(inStr.toDopeType(), startPos, length)
val expected = SubstringExpression(inStr.toDopeType(), startPos)

val actual = substr(inStr, startPos)

Expand Down
2 changes: 1 addition & 1 deletion crystal-map-connector/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ repositories {
}

dependencies {
implementation("com.github.SchwarzIT.crystal-map:crystal-map-api:3.18.0")
implementation("com.github.SchwarzIT.crystal-map:crystal-map-api:4.0.3")
implementation(kotlin("reflect"))
implementation(project(":core"))

Expand Down
Original file line number Diff line number Diff line change
@@ -1,48 +1,93 @@
package ch.ergon.dope

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.formatPathToQueryString
import ch.ergon.dope.validtype.ArrayType
import ch.ergon.dope.validtype.BooleanType
import ch.ergon.dope.validtype.DopeSchemaArray
import ch.ergon.dope.validtype.NumberType
import ch.ergon.dope.validtype.StringType
import ch.ergon.dope.validtype.ValidType
import com.schwarz.crystalapi.schema.CMField
import com.schwarz.crystalapi.schema.CMList
import com.schwarz.crystalapi.schema.CMConverterField
import com.schwarz.crystalapi.schema.CMConverterList
import com.schwarz.crystalapi.schema.CMJsonField
import com.schwarz.crystalapi.schema.CMJsonList
import com.schwarz.crystalapi.schema.CMObject
import com.schwarz.crystalapi.schema.CMObjectList
import com.schwarz.crystalapi.schema.CMType
import com.schwarz.crystalapi.schema.Schema
import kotlin.reflect.KClass

fun CMType.toDopeType(reference: String = path): Field<ValidType> = Field(
when (this) {
is CMField<*> -> this.name
is CMList<*> -> this.name
is CMJsonField<*> -> this.name
is CMJsonList<*> -> this.name
is CMObjectList<*> -> this.name
is CMObject<*> -> TODO("DOPE-216")
else -> throw IllegalArgumentException("Unsupported type $this")
},
reference,
)

@JvmName("toDopeTypeNumber")
fun <Convertable : Any, JsonType : Number> Convertable.toDopeType(other: CMConverterField<Convertable, JsonType>): TypeExpression<NumberType> =
requireValidConvertable(other.typeConverter.write(this), Number::class).toDopeType()

@JvmName("toDopeTypeString")
fun <Convertable : Any> Convertable.toDopeType(other: CMConverterField<Convertable, String>): TypeExpression<StringType> =
requireValidConvertable(other.typeConverter.write(this), String::class).toDopeType()

@JvmName("toDopeTypeBoolean")
fun <Convertable : Any> Convertable.toDopeType(other: CMConverterField<Convertable, Boolean>): TypeExpression<BooleanType> =
requireValidConvertable(other.typeConverter.write(this), Boolean::class).toDopeType()

@JvmName("toDopeTypeListNumber")
fun <Convertable : Any, JsonType : Number> Convertable.toDopeType(other: CMConverterList<Convertable, JsonType>): TypeExpression<NumberType> =
requireValidConvertable(other.typeConverter.write(this), Number::class).toDopeType()

@JvmName("toDopeTypeListString")
fun <Convertable : Any> Convertable.toDopeType(other: CMConverterList<Convertable, String>): TypeExpression<StringType> =
requireValidConvertable(other.typeConverter.write(this), String::class).toDopeType()

@JvmName("toDopeTypeListBoolean")
fun <Convertable : Any> Convertable.toDopeType(other: CMConverterList<Convertable, Boolean>): TypeExpression<BooleanType> =
requireValidConvertable(other.typeConverter.write(this), Boolean::class).toDopeType()

fun <Convertable : Any, JsonType : Number> CMConverterField<Convertable, JsonType>.toDopeType(other: Convertable) =
requireValidConvertable(typeConverter.write(other), Number::class).toDopeType()

fun <Convertable : Any> CMConverterField<Convertable, String>.toDopeType(other: Convertable) =
requireValidConvertable(typeConverter.write(other), String::class).toDopeType()

fun <Convertable : Any> CMConverterField<Convertable, Boolean>.toDopeType(other: Convertable) =
requireValidConvertable(typeConverter.write(other), Boolean::class).toDopeType()

@JvmName("toDopeNumberField")
fun CMField<out Number>.toDopeType(reference: String = path): Field<NumberType> = Field(name, reference)
fun CMJsonField<out Number>.toDopeType(reference: String = path): Field<NumberType> = Field(name, reference)

@JvmName("toDopeStringField")
fun CMField<String>.toDopeType(reference: String = path): Field<StringType> = Field(name, reference)
fun CMJsonField<String>.toDopeType(reference: String = path): Field<StringType> = Field(name, reference)

@JvmName("toDopeBooleanField")
fun CMField<Boolean>.toDopeType(reference: String = path): Field<BooleanType> = Field(name, reference)
fun CMJsonField<Boolean>.toDopeType(reference: String = path): Field<BooleanType> = Field(name, reference)

@JvmName("toDopeNumberArrayField")
fun CMList<out Number>.toDopeType(): Field<ArrayType<NumberType>> = Field(name, path)
fun CMJsonList<out Number>.toDopeType(): Field<ArrayType<NumberType>> = Field(name, path)

@JvmName("toDopeStringArrayField")
fun CMList<String>.toDopeType(): Field<ArrayType<StringType>> = Field(name, path)
fun CMJsonList<String>.toDopeType(): Field<ArrayType<StringType>> = Field(name, path)

@JvmName("toDopeBooleanArrayField")
fun CMList<Boolean>.toDopeType(): Field<ArrayType<BooleanType>> = Field(name, path)
fun CMJsonList<Boolean>.toDopeType(): Field<ArrayType<BooleanType>> = Field(name, path)

fun CMJsonList<out Any>.toDopeType(): Field<ArrayType<ValidType>> = Field(name, path)

// TODO: DOPE-192
fun <T : Schema> CMObjectList<T>.toDopeType() = DopeSchemaArray(element, formatPathToQueryString(name, path))

private fun <Convertable : Any, JsonType : Any> Convertable.requireValidConvertable(jsonType: JsonType?, jsonTypeClass: KClass<JsonType>) =
requireNotNull(jsonType) {
"Conversion failed: " +
"The value of type '${this::class.simpleName}' couldn't be converted to the expected JSON type '${jsonTypeClass.simpleName}'. "
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,29 @@ import ch.ergon.dope.resolvable.expression.unaliased.aggregator.ArrayAggregateEx
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.CMField
import com.schwarz.crystalapi.schema.CMList
import com.schwarz.crystalapi.schema.CMJsonField
import com.schwarz.crystalapi.schema.CMJsonList

@JvmName("arrayAggNumber")
fun arrayAggregate(field: CMField<out Number>, quantifier: AggregateQuantifier? = null):
fun arrayAggregate(field: CMJsonField<out Number>, quantifier: AggregateQuantifier? = null):
ArrayAggregateExpression<out ValidType> = arrayAggregate(field.toDopeType(), quantifier)

@JvmName("arrayAggString")
fun arrayAggregate(field: CMField<String>, quantifier: AggregateQuantifier? = null):
fun arrayAggregate(field: CMJsonField<String>, quantifier: AggregateQuantifier? = null):
ArrayAggregateExpression<out ValidType> = arrayAggregate(field.toDopeType(), quantifier)

@JvmName("arrayAggBoolean")
fun arrayAggregate(field: CMField<Boolean>, quantifier: AggregateQuantifier? = null):
fun arrayAggregate(field: CMJsonField<Boolean>, quantifier: AggregateQuantifier? = null):
ArrayAggregateExpression<out ValidType> = arrayAggregate(field.toDopeType(), quantifier)

@JvmName("arrayAggNumberArray")
fun arrayAggregate(field: CMList<out Number>, quantifier: AggregateQuantifier? = null):
fun arrayAggregate(field: CMJsonList<out Number>, quantifier: AggregateQuantifier? = null):
ArrayAggregateExpression<out ValidType> = arrayAggregate(field.toDopeType(), quantifier)

@JvmName("arrayAggStringArray")
fun arrayAggregate(field: CMList<String>, quantifier: AggregateQuantifier? = null):
fun arrayAggregate(field: CMJsonList<String>, quantifier: AggregateQuantifier? = null):
ArrayAggregateExpression<out ValidType> = arrayAggregate(field.toDopeType(), quantifier)

@JvmName("arrayAggBooleanArray")
fun arrayAggregate(field: CMList<Boolean>, quantifier: AggregateQuantifier? = null):
fun arrayAggregate(field: CMJsonList<Boolean>, quantifier: AggregateQuantifier? = null):
ArrayAggregateExpression<out ValidType> = arrayAggregate(field.toDopeType(), quantifier)
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,29 @@ import ch.ergon.dope.resolvable.expression.unaliased.aggregator.AggregateQuantif
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.CMField
import com.schwarz.crystalapi.schema.CMList
import com.schwarz.crystalapi.schema.CMJsonField
import com.schwarz.crystalapi.schema.CMJsonList

@JvmName("countNumber")
fun count(field: CMField<out Number>, quantifier: AggregateQuantifier? = null):
fun count(field: CMJsonField<out Number>, quantifier: AggregateQuantifier? = null):
CountExpression = count(field.toDopeType(), quantifier)

@JvmName("countString")
fun count(field: CMField<String>, quantifier: AggregateQuantifier? = null):
fun count(field: CMJsonField<String>, quantifier: AggregateQuantifier? = null):
CountExpression = count(field.toDopeType(), quantifier)

@JvmName("countBoolean")
fun count(field: CMField<Boolean>, quantifier: AggregateQuantifier? = null):
fun count(field: CMJsonField<Boolean>, quantifier: AggregateQuantifier? = null):
CountExpression = count(field.toDopeType(), quantifier)

@JvmName("countNumber")
fun count(field: CMList<out Number>, quantifier: AggregateQuantifier? = null):
fun count(field: CMJsonList<out Number>, quantifier: AggregateQuantifier? = null):
CountExpression = count(field.toDopeType(), quantifier)

@JvmName("countString")
fun count(field: CMList<String>, quantifier: AggregateQuantifier? = null):
fun count(field: CMJsonList<String>, quantifier: AggregateQuantifier? = null):
CountExpression = count(field.toDopeType(), quantifier)

@JvmName("countBoolean")
fun count(field: CMList<Boolean>, quantifier: AggregateQuantifier? = null):
fun count(field: CMJsonList<Boolean>, quantifier: AggregateQuantifier? = null):
CountExpression = count(field.toDopeType(), quantifier)
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,29 @@ 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.CMField
import com.schwarz.crystalapi.schema.CMList
import com.schwarz.crystalapi.schema.CMJsonField
import com.schwarz.crystalapi.schema.CMJsonList

@JvmName("maxNumber")
fun max(field: CMField<out Number>, quantifier: AggregateQuantifier? = null):
fun max(field: CMJsonField<out Number>, quantifier: AggregateQuantifier? = null):
MaxExpression<out ValidType> = max(field.toDopeType(), quantifier)

@JvmName("maxString")
fun max(field: CMField<String>, quantifier: AggregateQuantifier? = null):
fun max(field: CMJsonField<String>, quantifier: AggregateQuantifier? = null):
MaxExpression<out ValidType> = max(field.toDopeType(), quantifier)

@JvmName("maxBoolean")
fun max(field: CMField<Boolean>, quantifier: AggregateQuantifier? = null):
fun max(field: CMJsonField<Boolean>, quantifier: AggregateQuantifier? = null):
MaxExpression<out ValidType> = max(field.toDopeType(), quantifier)

@JvmName("maxNumber")
fun max(field: CMList<out Number>, quantifier: AggregateQuantifier? = null):
fun max(field: CMJsonList<out Number>, quantifier: AggregateQuantifier? = null):
MaxExpression<out ValidType> = max(field.toDopeType(), quantifier)

@JvmName("maxString")
fun max(field: CMList<String>, quantifier: AggregateQuantifier? = null):
fun max(field: CMJsonList<String>, quantifier: AggregateQuantifier? = null):
MaxExpression<out ValidType> = max(field.toDopeType(), quantifier)

@JvmName("maxBoolean")
fun max(field: CMList<Boolean>, quantifier: AggregateQuantifier? = null):
fun max(field: CMJsonList<Boolean>, quantifier: AggregateQuantifier? = null):
MaxExpression<out ValidType> = max(field.toDopeType(), quantifier)
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,29 @@ 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.CMField
import com.schwarz.crystalapi.schema.CMList
import com.schwarz.crystalapi.schema.CMJsonField
import com.schwarz.crystalapi.schema.CMJsonList

@JvmName("minNumber")
fun min(field: CMField<out Number>, quantifier: AggregateQuantifier? = null):
fun min(field: CMJsonField<out Number>, quantifier: AggregateQuantifier? = null):
MinExpression<out ValidType> = min(field.toDopeType(), quantifier)

@JvmName("minString")
fun min(field: CMField<String>, quantifier: AggregateQuantifier? = null):
fun min(field: CMJsonField<String>, quantifier: AggregateQuantifier? = null):
MinExpression<out ValidType> = min(field.toDopeType(), quantifier)

@JvmName("minBoolean")
fun min(field: CMField<Boolean>, quantifier: AggregateQuantifier? = null):
fun min(field: CMJsonField<Boolean>, quantifier: AggregateQuantifier? = null):
MinExpression<out ValidType> = min(field.toDopeType(), quantifier)

@JvmName("minNumber")
fun min(field: CMList<out Number>, quantifier: AggregateQuantifier? = null):
fun min(field: CMJsonList<out Number>, quantifier: AggregateQuantifier? = null):
MinExpression<out ValidType> = min(field.toDopeType(), quantifier)

@JvmName("minString")
fun min(field: CMList<String>, quantifier: AggregateQuantifier? = null):
fun min(field: CMJsonList<String>, quantifier: AggregateQuantifier? = null):
MinExpression<out ValidType> = min(field.toDopeType(), quantifier)

@JvmName("minBoolean")
fun min(field: CMList<Boolean>, quantifier: AggregateQuantifier? = null):
fun min(field: CMJsonList<Boolean>, quantifier: AggregateQuantifier? = null):
MinExpression<out ValidType> = min(field.toDopeType(), quantifier)
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,28 @@ 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.CMField
import com.schwarz.crystalapi.schema.CMJsonField

@JvmName("avgNumber")
fun avg(field: CMField<out Number>, quantifier: AggregateQuantifier? = null):
fun avg(field: CMJsonField<out Number>, quantifier: AggregateQuantifier? = null):
AverageExpression<out NumberType> = avg(field.toDopeType(), quantifier)

@JvmName("meanNumber")
fun mean(field: CMField<out Number>, quantifier: AggregateQuantifier? = null):
fun mean(field: CMJsonField<out Number>, quantifier: AggregateQuantifier? = null):
MeanExpression<out NumberType> = mean(field.toDopeType(), quantifier)

@JvmName("medianNumber")
fun median(field: CMField<out Number>, quantifier: AggregateQuantifier? = null):
fun median(field: CMJsonField<out Number>, quantifier: AggregateQuantifier? = null):
MedianExpression<out NumberType> = median(field.toDopeType(), quantifier)

@JvmName("sumNumber")
fun sum(field: CMField<out Number>, quantifier: AggregateQuantifier? = null):
fun sum(field: CMJsonField<out Number>, quantifier: AggregateQuantifier? = null):
SumExpression<out NumberType> = sum(field.toDopeType(), quantifier)

@JvmName("stdDevNumber")
fun stdDev(field: CMField<out Number>, quantifier: AggregateQuantifier? = null):
fun stdDev(field: CMJsonField<out Number>, quantifier: AggregateQuantifier? = null):
StandardDeviationExpression<out NumberType> = stdDev(field.toDopeType(), quantifier)

@JvmName("varianceNumber")
fun variance(field: CMField<out Number>, quantifier: AggregateQuantifier? = null):
fun variance(field: CMJsonField<out Number>, quantifier: AggregateQuantifier? = null):
VarianceExpression<out NumberType> = variance(field.toDopeType(), quantifier)
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ import ch.ergon.dope.resolvable.clause.IDeleteOffsetClause
import ch.ergon.dope.resolvable.clause.IDeleteUseKeysClause
import ch.ergon.dope.resolvable.clause.IDeleteWhereClause
import ch.ergon.dope.toDopeType
import com.schwarz.crystalapi.schema.CMField
import com.schwarz.crystalapi.schema.CMList
import com.schwarz.crystalapi.schema.CMJsonField
import com.schwarz.crystalapi.schema.CMJsonList
import com.schwarz.crystalapi.schema.CMType

fun IDeleteOffsetClause.returning(field: CMType, vararg fields: CMType) =
returning(field.toDopeType(), *fields.map { it.toDopeType() }.toTypedArray())

fun IDeleteLimitClause.offset(numberExpression: CMField<Number>) = offset(numberExpression.toDopeType())
fun IDeleteLimitClause.offset(numberExpression: CMJsonField<Number>) = offset(numberExpression.toDopeType())

fun IDeleteWhereClause.limit(numberExpression: CMField<Number>) = limit(numberExpression.toDopeType())
fun IDeleteWhereClause.limit(numberExpression: CMJsonField<Number>) = limit(numberExpression.toDopeType())

fun IDeleteUseKeysClause.where(booleanExpression: CMField<Boolean>) = where(booleanExpression.toDopeType())
fun IDeleteUseKeysClause.where(booleanExpression: CMJsonField<Boolean>) = where(booleanExpression.toDopeType())

fun IDeleteClause.useKeys(useKeys: CMField<String>) = useKeys(useKeys.toDopeType())
fun IDeleteClause.useKeys(useKeys: CMList<String>) = useKeys(useKeys.toDopeType())
fun IDeleteClause.useKeys(useKeys: CMJsonField<String>) = useKeys(useKeys.toDopeType())
fun IDeleteClause.useKeys(useKeys: CMJsonList<String>) = useKeys(useKeys.toDopeType())
Loading

0 comments on commit 0792fc2

Please sign in to comment.