Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOPE-247: added array star function, tests and cm extensions #69

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ fun Collection<Number>.asParameter(parameterName: String? = null) = ArrayParamet
@JvmName("stringCollectionAsParameter")
fun Collection<String>.asParameter(parameterName: String? = null) = ArrayParameter<StringType>(this, parameterName)

@JvmName("booleanParameterAsParameter")
@JvmName("booleanCollectionAsParameter")
fun Collection<Boolean>.asParameter(parameterName: String? = null) = ArrayParameter<BooleanType>(this, parameterName)

@JvmName("objectCollectionAsParameter")
fun Collection<Map<String, Any>>.asParameter(parameterName: String? = null) =
ArrayParameter<ObjectType>(this, parameterName)

fun Map<String, Any>.asParameter(parameterName: String? = null) = ObjectParameter(this, parameterName)
martinagallati-ergon marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.arrayfunction

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.resolvable.expression.unaliased.type.toDopeType
import ch.ergon.dope.resolvable.operator.FunctionOperator
import ch.ergon.dope.validtype.ArrayType
import ch.ergon.dope.validtype.ObjectType

class ArrayStarExpression(
private val objectArray: TypeExpression<ArrayType<ObjectType>>,
) : TypeExpression<ObjectType>, FunctionOperator {
override fun toDopeQuery(manager: DopeQueryManager): DopeQuery {
val objectArrayDopeQuery = objectArray.toDopeQuery(manager)
return DopeQuery(
queryString = toFunctionQueryString("ARRAY_STAR", objectArrayDopeQuery.queryString),
parameters = objectArrayDopeQuery.parameters,
)
}
}

fun arrayStar(objectArray: TypeExpression<ArrayType<ObjectType>>) = ArrayStarExpression(objectArray)

@JvmName("receiverArrayStar")
fun TypeExpression<ArrayType<ObjectType>>.arrayStar() = arrayStar(this)
martinagallati-ergon marked this conversation as resolved.
Show resolved Hide resolved

fun arrayStar(objectArray: Collection<TypeExpression<ObjectType>>) = arrayStar(objectArray.toDopeType())

@JvmName("collectionReceiverArrayStar")
fun Collection<TypeExpression<ObjectType>>.arrayStar() = arrayStar(this.toDopeType())

fun arrayStar(objectArray: ISelectOffsetClause<ObjectType>) = ArrayStarExpression(objectArray.asExpression())

@JvmName("selectClauseReceiverArrayStar")
fun ISelectOffsetClause<ObjectType>.arrayStar() = arrayStar(this.asExpression())
martinagallati-ergon marked this conversation as resolved.
Show resolved Hide resolved
16 changes: 16 additions & 0 deletions core/src/test/kotlin/ch/ergon/dope/buildTest/ArrayFunctionsTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import ch.ergon.dope.QueryBuilder
import ch.ergon.dope.helper.someBucket
import ch.ergon.dope.helper.someNumberArrayField
import ch.ergon.dope.helper.someNumberField
import ch.ergon.dope.helper.someObjectArrayField
import ch.ergon.dope.helper.someStringArrayField
import ch.ergon.dope.helper.someStringField
import ch.ergon.dope.resolvable.expression.unaliased.type.access.get
Expand Down Expand Up @@ -33,11 +34,13 @@ import ch.ergon.dope.resolvable.expression.unaliased.type.function.arrayfunction
import ch.ergon.dope.resolvable.expression.unaliased.type.function.arrayfunction.arrayReplace
import ch.ergon.dope.resolvable.expression.unaliased.type.function.arrayfunction.arrayReverse
import ch.ergon.dope.resolvable.expression.unaliased.type.function.arrayfunction.arraySort
import ch.ergon.dope.resolvable.expression.unaliased.type.function.arrayfunction.arrayStar
import ch.ergon.dope.resolvable.expression.unaliased.type.function.arrayfunction.arraySum
import ch.ergon.dope.resolvable.expression.unaliased.type.function.arrayfunction.arraySymDiff
import ch.ergon.dope.resolvable.expression.unaliased.type.function.arrayfunction.arraySymDiffN
import ch.ergon.dope.resolvable.expression.unaliased.type.function.arrayfunction.arrayUnion
import ch.ergon.dope.resolvable.expression.unaliased.type.function.stringfunction.lower
import ch.ergon.dope.resolvable.expression.unaliased.type.getNumberArray
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
Expand Down Expand Up @@ -372,6 +375,19 @@ class ArrayFunctionsTest {
assertEquals(expected, actual)
}

@Test
fun `should support array star with object function`() {
val objectArray = someObjectArrayField()
val expected = "SELECT ARRAY_STAR(`objectArrayField`).`key`"

val actual = create
.select(
arrayStar(objectArray).getNumberArray("key"),
).build().queryString

assertEquals(expected, actual)
}

@Test
fun `should support array symmetric difference with array access`() {
val expected = "SELECT ARRAY_SYMDIFF(`stringArrayField`, `anotherStringArrayField`)[0]"
Expand Down
3 changes: 3 additions & 0 deletions core/src/test/kotlin/ch/ergon/dope/helper/Builder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ fun someStringArrayField(name: String = "stringArrayField", bucket: Bucket = som
fun someBooleanArrayField(name: String = "booleanArrayField", bucket: Bucket = someBucket("")) =
Field<ArrayType<BooleanType>>(name, getBucketName(bucket))

fun someObjectArrayField(name: String = "objectArrayField", bucket: Bucket = someBucket("")) =
Field<ArrayType<ObjectType>>(name, getBucketName(bucket))

fun someNumber(value: Number = 5) = value

fun someInt(value: Int = 5) = value
Expand Down
7 changes: 6 additions & 1 deletion core/src/test/kotlin/ch/ergon/dope/helper/ClauseBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import ch.ergon.dope.resolvable.fromable.Bucket
import ch.ergon.dope.resolvable.fromable.UnaliasedBucket
import ch.ergon.dope.validtype.BooleanType
import ch.ergon.dope.validtype.NumberType
import ch.ergon.dope.validtype.ObjectType
import ch.ergon.dope.validtype.StringType

fun someSelectClause(expression: Expression = AsteriskExpression()) = SelectClause(expression)
Expand All @@ -27,8 +28,12 @@ fun someNumberSelectRawClause(expression: TypeExpression<NumberType> = someNumbe
fun someBooleanSelectRawClause(expression: TypeExpression<BooleanType> = someBooleanField()) =
SelectRawClause(expression)

fun someObjectSelectRawClause(expression: TypeExpression<ObjectType> = someObjectField()) =
SelectRawClause(expression)

fun someDeleteClause(bucket: Bucket = someBucket()) = DeleteClause(bucket)

fun someUpdateClause(bucket: Bucket = someBucket()) = UpdateClause(bucket)

fun someFromClause(bucket: UnaliasedBucket = someBucket(), parent: SelectClause = someSelectClause()) = FromClause(bucket, parent)
fun someFromClause(bucket: UnaliasedBucket = someBucket(), parent: SelectClause = someSelectClause()) =
FromClause(bucket, parent)
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.arrayfunction

import ch.ergon.dope.DopeParameters
import ch.ergon.dope.DopeQuery
import ch.ergon.dope.DopeQueryManager
import ch.ergon.dope.helper.ManagerDependentTest
import ch.ergon.dope.helper.someObjectArrayField
import ch.ergon.dope.helper.someObjectField
import ch.ergon.dope.helper.someObjectSelectRawClause
import ch.ergon.dope.resolvable.expression.unaliased.type.asParameter
import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType
import kotlin.test.Test
import kotlin.test.assertEquals

class ArrayStarExpressionTest : ManagerDependentTest {
override lateinit var manager: DopeQueryManager

@Test
fun `should support ARRAY_STAR`() {
val expected = DopeQuery(
queryString = "ARRAY_STAR(`objectArrayField`)",
)
val underTest = ArrayStarExpression(someObjectArrayField())

val actual = underTest.toDopeQuery(manager)

assertEquals(expected, actual)
}

@Test
fun `should support ARRAY_STAR with named parameter`() {
val parameterName = "objectArray"
val parameterValue = listOf(
jansigi marked this conversation as resolved.
Show resolved Hide resolved
mapOf("key1" to 1, "key2" to "test"),
mapOf("key1" to 2, "key2" to "string"),
)
val expected = DopeQuery(
queryString = "ARRAY_STAR(\$objectArray)",
parameters = DopeParameters(
namedParameters = mapOf(parameterName to parameterValue),
),
)
val underTest = ArrayStarExpression(parameterValue.asParameter(parameterName))

val actual = underTest.toDopeQuery(manager)

assertEquals(expected, actual)
}

@Test
fun `should support ARRAY_STAR with positional parameter`() {
val parameterValue = listOf(
jansigi marked this conversation as resolved.
Show resolved Hide resolved
mapOf("key1" to 1, "key2" to "test"),
mapOf("key1" to 2, "key2" to "string"),
)
val expected = DopeQuery(
queryString = "ARRAY_STAR(\$1)",
parameters = DopeParameters(
positionalParameters = listOf(parameterValue),
),
)
val underTest = ArrayStarExpression(parameterValue.asParameter())

val actual = underTest.toDopeQuery(manager)

assertEquals(expected, actual)
}

@Test
fun `should support ARRAY_STAR extension type`() {
val objectArray = someObjectArrayField()
val expected = ArrayStarExpression(objectArray)

val actual = arrayStar(objectArray)

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

@Test
fun `should support ARRAY_STAR extension collection`() {
val objectArray = listOf(someObjectField(), someObjectField())
val expected = ArrayStarExpression(objectArray.toDopeType())

val actual = arrayStar(objectArray)

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

@Test
fun `should support ARRAY_STAR extension select`() {
val selectClause = someObjectSelectRawClause()
val expected = ArrayStarExpression(selectClause.asExpression())

val actual = arrayStar(selectClause)

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

@Test
fun `should support ARRAY_STAR receiver extension type`() {
val objectArray = someObjectArrayField()
val expected = ArrayStarExpression(objectArray)

val actual = objectArray.arrayStar()

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

@Test
fun `should support ARRAY_STAR receiver extension collection`() {
val objectArray = listOf(someObjectField(), someObjectField())
val expected = ArrayStarExpression(objectArray.toDopeType())

val actual = objectArray.arrayStar()

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

@Test
fun `should support ARRAY_STAR receiver extension select`() {
val selectClause = someObjectSelectRawClause()
val expected = ArrayStarExpression(selectClause.asExpression())

val actual = selectClause.arrayStar()

assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package ch.ergon.dope.extension.type.array

import ch.ergon.dope.resolvable.expression.unaliased.type.function.arrayfunction.arrayStar
import ch.ergon.dope.toDopeType
import com.schwarz.crystalapi.schema.CMObjectList
import com.schwarz.crystalapi.schema.Schema

fun <S : Schema> arrayStar(array: CMObjectList<S>) = arrayStar(array.toDopeType())

@JvmName("schemaArrayStar")
fun <S : Schema> CMObjectList<S>.arrayStar() = arrayStar(this.toDopeType())
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import ch.ergon.dope.DopeQueryManager
import ch.ergon.dope.QueryBuilder
import ch.ergon.dope.extension.select
import ch.ergon.dope.extension.type.access.get
import ch.ergon.dope.extension.type.array.arrayStar
import ch.ergon.dope.extension.type.getField
import ch.ergon.dope.extension.type.relational.inArray
import ch.ergon.dope.extension.type.relational.isEqualTo
import ch.ergon.dope.extension.type.relational.isGreaterOrEqualThan
import ch.ergon.dope.helper.ManagerDependentTest
Expand All @@ -13,6 +15,7 @@ import ch.ergon.dope.resolvable.expression.unaliased.type.conditional.case
import ch.ergon.dope.resolvable.expression.unaliased.type.conditional.condition
import ch.ergon.dope.resolvable.expression.unaliased.type.function.conditional.resultsIn
import ch.ergon.dope.resolvable.expression.unaliased.type.getString
import ch.ergon.dope.resolvable.expression.unaliased.type.getStringArray
import ch.ergon.dope.toDopeType
import com.schwarz.crystalapi.schema.CMJsonField
import com.schwarz.crystalapi.schema.CMObjectField
Expand Down Expand Up @@ -114,4 +117,23 @@ class ObjectTest : ManagerDependentTest {

assertEquals(expected, actual)
}

@Test
fun `should support array star function with object list`() {
val bucket = someBucket().alias("p")
val schema = Person("p")
val objectField = schema.primaryHobby.toDopeType()
val expected = "SELECT * FROM `someBucket` AS `p` WHERE `p`.`primaryHobby`.`name` IN " +
"ARRAY_STAR(`p`.`hobbies`).`name`"

val actual = QueryBuilder()
.selectAsterisk()
.from(bucket)
.where(
objectField.getField(Hobby::name).inArray(schema.hobbies.arrayStar().getStringArray("name")),
)
.build().queryString

assertEquals(expected, actual)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import ch.ergon.dope.extension.type.array.arrayContains
import ch.ergon.dope.extension.type.array.arrayDistinct
import ch.ergon.dope.extension.type.array.arrayIntersect
import ch.ergon.dope.extension.type.array.arrayLength
import ch.ergon.dope.extension.type.array.arrayStar
import ch.ergon.dope.extension.type.array.arraySum
import ch.ergon.dope.helper.ManagerDependentTest
import ch.ergon.dope.helper.someCMBooleanField
Expand All @@ -20,6 +21,7 @@ import ch.ergon.dope.resolvable.expression.unaliased.type.function.arrayfunction
import ch.ergon.dope.resolvable.expression.unaliased.type.function.arrayfunction.ArrayDistinctExpression
import ch.ergon.dope.resolvable.expression.unaliased.type.function.arrayfunction.ArrayIntersectExpression
import ch.ergon.dope.resolvable.expression.unaliased.type.function.arrayfunction.ArrayLengthExpression
import ch.ergon.dope.resolvable.expression.unaliased.type.function.arrayfunction.ArrayStarExpression
import ch.ergon.dope.resolvable.expression.unaliased.type.function.arrayfunction.ArraySumExpression
import ch.ergon.dope.toDopeType
import kotlin.test.Test
Expand Down Expand Up @@ -218,6 +220,26 @@ class ArrayFunctionTest : ManagerDependentTest {
assertEquals(expected.toDopeQuery(manager), actual.toDopeQuery(manager))
}

@Test
fun `should support ARRAY_STAR with CM Object list`() {
val cMJsonList = someCMObjectList()
val expected = ArrayStarExpression(cMJsonList.toDopeType())

val actual = arrayStar(cMJsonList)

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

@Test
fun `should support ARRAY_STAR with CM Object list as receiver`() {
val cMJsonList = someCMObjectList()
val expected = ArrayStarExpression(cMJsonList.toDopeType())

val actual = cMJsonList.arrayStar()

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

@Test
fun `should support ARRAY_SUM with CM Number list`() {
val cMJsonList = someCMNumberList()
Expand Down
Loading