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-239: implemented all objectFunctions with extensions for cm and added tests #64

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should also add some integration-tests for objects

Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,28 @@ class UpdateIntegrationTest : BaseIntegrationTest() {

@Test
fun `update to set and unset single attribute`() {
val newField = Field<StringType>("newField", testBucket.name)
val newFieldName = Field<StringType>("newFieldName", testBucket.name)
val dopeQuery = QueryBuilder()
.update(
testBucket.useKeys("client:1"),
)
.set(
newField,
newFieldName,
"newName",
)
.unset(
nameField,
)
.returning(
newField,
newFieldName,
nameField,
).build()

tryUntil {
val queryResult = queryWithoutParameters(dopeQuery)
val result = queryResult.toMapValues()

assertEquals("newName", result["newField"])
assertEquals("newName", result["newFieldName"])
assertNull(result["nameField"])
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ class ObjectPrimitive(
)

class ObjectEntryPrimitive<T : ValidType>(
private val key: TypeExpression<StringType>,
private val value: TypeExpression<T>,
val key: TypeExpression<StringType>,
val value: TypeExpression<T>,
) : Resolvable {
override fun toDopeQuery(manager: DopeQueryManager): DopeQuery {
val keyQuery = key.toDopeQuery(manager)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.`object`

import ch.ergon.dope.resolvable.expression.TypeExpression
import ch.ergon.dope.resolvable.expression.unaliased.type.ObjectEntryPrimitive
import ch.ergon.dope.resolvable.expression.unaliased.type.function.FunctionExpression
import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType
import ch.ergon.dope.resolvable.expression.unaliased.type.toObjectEntry
import ch.ergon.dope.validtype.ObjectType
import ch.ergon.dope.validtype.StringType
import ch.ergon.dope.validtype.ValidType

class ObjectAddExpression(
objectExpression: TypeExpression<ObjectType>,
objectEntryPrimitive: ObjectEntryPrimitive<out ValidType>,
) : FunctionExpression<ObjectType>("OBJECT_ADD", objectExpression, objectEntryPrimitive.key, objectEntryPrimitive.value)

fun TypeExpression<ObjectType>.addAttribute(objectEntryPrimitive: ObjectEntryPrimitive<out ValidType>) =
ObjectAddExpression(this, objectEntryPrimitive)

fun TypeExpression<ObjectType>.addAttribute(key: TypeExpression<StringType>, value: TypeExpression<out ValidType>) =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are no build/integration tests, where you play around with different typeEpressions / nested-functions etc, right? Please add some

addAttribute(key.toObjectEntry(value))

fun TypeExpression<ObjectType>.addAttribute(key: String, value: TypeExpression<out ValidType>) =
addAttribute(key.toDopeType(), value)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.`object`

import ch.ergon.dope.resolvable.expression.TypeExpression
import ch.ergon.dope.resolvable.expression.unaliased.type.function.FunctionExpression
import ch.ergon.dope.validtype.ObjectType

class ObjectConcatExpression(
firstObjectExpression: TypeExpression<ObjectType>,
secondObjectExpression: TypeExpression<ObjectType>,
vararg additionalObjectExpression: TypeExpression<ObjectType>,
) : FunctionExpression<ObjectType>("OBJECT_CONCAT", firstObjectExpression, secondObjectExpression, *additionalObjectExpression)

fun TypeExpression<ObjectType>.concat(
secondObjectExpression: TypeExpression<ObjectType>,
vararg additionalObjectExpression: TypeExpression<ObjectType>,
) = ObjectConcatExpression(this, secondObjectExpression, *additionalObjectExpression)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.`object`

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.ObjectType
import ch.ergon.dope.validtype.StringType
import ch.ergon.dope.validtype.ValidType

class ObjectFieldExpression(
objectExpression: TypeExpression<ObjectType>,
jansigi marked this conversation as resolved.
Show resolved Hide resolved
attributeKey: TypeExpression<StringType>,
jansigi marked this conversation as resolved.
Show resolved Hide resolved
) : FunctionExpression<ValidType>("OBJECT_FIELD", objectExpression, attributeKey)

fun TypeExpression<ObjectType>.objectField(key: TypeExpression<StringType>) =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the prefix object from the extension-funciton (You are not doing .objectConcat or similar as well).
Use a more descriptive naming, like getField()? (I'm don't know what the function should do)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(or something with Attribute?, below you use that term, would not use both for the same thing)

ObjectFieldExpression(this, key)
jansigi marked this conversation as resolved.
Show resolved Hide resolved

fun TypeExpression<ObjectType>.objectField(key: String) = objectField(key.toDopeType())
jansigi marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.`object`

import ch.ergon.dope.resolvable.expression.TypeExpression
import ch.ergon.dope.resolvable.expression.unaliased.type.function.FunctionExpression
import ch.ergon.dope.validtype.ArrayType
import ch.ergon.dope.validtype.ObjectType

class ObjectInnerPairsExpression(
objectExpression: TypeExpression<ObjectType>,
) : FunctionExpression<ArrayType<ObjectType>>("OBJECT_INNER_PAIRS", objectExpression)

fun TypeExpression<ObjectType>.innerPairs() = ObjectInnerPairsExpression(this)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefer to have function with a verb. Something like getInnerPairs()/createInnerPairs() or something (same for all of the functions)

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.`object`

import ch.ergon.dope.resolvable.expression.TypeExpression
import ch.ergon.dope.resolvable.expression.unaliased.type.function.FunctionExpression
import ch.ergon.dope.validtype.ArrayType
import ch.ergon.dope.validtype.ObjectType
import ch.ergon.dope.validtype.ValidType

class ObjectInnerValuesExpression(
objectExpression: TypeExpression<ObjectType>,
) : FunctionExpression<ArrayType<ValidType>>("OBJECT_INNER_VALUES", objectExpression)

fun TypeExpression<ObjectType>.innerValues() = ObjectInnerValuesExpression(this)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.`object`

import ch.ergon.dope.resolvable.expression.TypeExpression
import ch.ergon.dope.resolvable.expression.unaliased.type.function.FunctionExpression
import ch.ergon.dope.validtype.NumberType
import ch.ergon.dope.validtype.ObjectType

class ObjectLengthExpression(
objectExpression: TypeExpression<ObjectType>,
) : FunctionExpression<NumberType>("OBJECT_LENGTH", objectExpression)

fun TypeExpression<ObjectType>.length() = ObjectLengthExpression(this)
jansigi marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.`object`

import ch.ergon.dope.resolvable.expression.TypeExpression
import ch.ergon.dope.resolvable.expression.unaliased.type.function.FunctionExpression
import ch.ergon.dope.validtype.ArrayType
import ch.ergon.dope.validtype.ObjectType
import ch.ergon.dope.validtype.StringType

class ObjectNamesExpression(
objectExpression: TypeExpression<ObjectType>,
) : FunctionExpression<ArrayType<StringType>>("OBJECT_NAMES", objectExpression)

fun TypeExpression<ObjectType>.names() = ObjectNamesExpression(this)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.`object`

import ch.ergon.dope.resolvable.expression.TypeExpression
import ch.ergon.dope.resolvable.expression.unaliased.type.function.FunctionExpression
import ch.ergon.dope.validtype.ArrayType
import ch.ergon.dope.validtype.ObjectType

class ObjectPairsExpression(
objectExpression: TypeExpression<ObjectType>,
) : FunctionExpression<ArrayType<ObjectType>>("OBJECT_PAIRS", objectExpression)

fun TypeExpression<ObjectType>.pairs() = ObjectPairsExpression(this)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.`object`

import ch.ergon.dope.resolvable.expression.TypeExpression
import ch.ergon.dope.resolvable.expression.unaliased.type.function.FunctionExpression
import ch.ergon.dope.validtype.ArrayType
import ch.ergon.dope.validtype.ObjectType

class ObjectPairsNestedExpression(
objectExpression: TypeExpression<ObjectType>,
options: TypeExpression<ObjectType>? = null,
) : FunctionExpression<ArrayType<ObjectType>>("OBJECT_PAIRS_NESTED", objectExpression, options)

fun TypeExpression<ObjectType>.pairsNested(options: TypeExpression<ObjectType>? = null) = ObjectPairsNestedExpression(this, options)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.`object`

import ch.ergon.dope.resolvable.expression.TypeExpression
import ch.ergon.dope.resolvable.expression.unaliased.type.function.FunctionExpression
import ch.ergon.dope.validtype.ArrayType
import ch.ergon.dope.validtype.ObjectType
import ch.ergon.dope.validtype.StringType

class ObjectPathsExpression(
objectExpression: TypeExpression<ObjectType>,
options: TypeExpression<ObjectType>? = null,
) : FunctionExpression<ArrayType<StringType>>("OBJECT_PATHS", objectExpression, options)

fun TypeExpression<ObjectType>.paths(options: TypeExpression<ObjectType>? = null) = ObjectPathsExpression(this, options)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.`object`

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.ObjectType
import ch.ergon.dope.validtype.StringType
import ch.ergon.dope.validtype.ValidType

class ObjectPutExpression(
objectExpression: TypeExpression<ObjectType>,
attributeKey: TypeExpression<StringType>,
attributeValue: TypeExpression<out ValidType>,
) : FunctionExpression<ObjectType>("OBJECT_PUT", objectExpression, attributeKey, attributeValue)

fun TypeExpression<ObjectType>.putAttribute(key: TypeExpression<StringType>, value: TypeExpression<out ValidType>) =
ObjectPutExpression(this, key, value)

fun TypeExpression<ObjectType>.putAttribute(key: String, value: TypeExpression<out ValidType>) = putAttribute(key.toDopeType(), value)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.`object`

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.ObjectType
import ch.ergon.dope.validtype.StringType

class ObjectRemoveExpression(
objectExpression: TypeExpression<ObjectType>,
attributeKey: TypeExpression<StringType>,
) : FunctionExpression<ObjectType>("OBJECT_REMOVE", objectExpression, attributeKey)

fun TypeExpression<ObjectType>.removeAttribute(key: TypeExpression<StringType>) = ObjectRemoveExpression(this, key)

fun TypeExpression<ObjectType>.removeAttribute(key: String) = removeAttribute(key.toDopeType())
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.`object`

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.ObjectType
import ch.ergon.dope.validtype.StringType

class ObjectRenameExpression(
objectExpression: TypeExpression<ObjectType>,
oldFieldName: TypeExpression<StringType>,
newFieldName: TypeExpression<StringType>,
) : FunctionExpression<ObjectType>("OBJECT_RENAME", objectExpression, oldFieldName, newFieldName)

fun TypeExpression<ObjectType>.renameAttribute(
oldFieldName: TypeExpression<StringType>,
newFieldName: TypeExpression<StringType>,
) = ObjectRenameExpression(this, oldFieldName, newFieldName)

fun TypeExpression<ObjectType>.renameAttribute(
oldFieldName: String,
newFieldName: String,
) = renameAttribute(oldFieldName.toDopeType(), newFieldName.toDopeType())

fun TypeExpression<ObjectType>.renameAttribute(
jansigi marked this conversation as resolved.
Show resolved Hide resolved
oldFieldName: TypeExpression<StringType>,
newFieldName: String,
) = renameAttribute(oldFieldName, newFieldName.toDopeType())

fun TypeExpression<ObjectType>.renameAttribute(
jansigi marked this conversation as resolved.
Show resolved Hide resolved
oldFieldName: String,
newFieldName: TypeExpression<StringType>,
) = renameAttribute(oldFieldName.toDopeType(), newFieldName)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.`object`

import ch.ergon.dope.resolvable.expression.TypeExpression
import ch.ergon.dope.resolvable.expression.unaliased.type.function.FunctionExpression
import ch.ergon.dope.validtype.ObjectType
import ch.ergon.dope.validtype.ValidType

class ObjectReplaceExpression(
objectExpression: TypeExpression<ObjectType>,
oldValue: TypeExpression<out ValidType>,
newValue: TypeExpression<out ValidType>,
) : FunctionExpression<ObjectType>("OBJECT_REPLACE", objectExpression, oldValue, newValue)

fun TypeExpression<ObjectType>.replace(oldValue: TypeExpression<out ValidType>, newValue: TypeExpression<out ValidType>) =
ObjectReplaceExpression(this, oldValue, newValue)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.`object`

import ch.ergon.dope.resolvable.expression.TypeExpression
import ch.ergon.dope.resolvable.expression.unaliased.type.function.FunctionExpression
import ch.ergon.dope.validtype.ObjectType
import ch.ergon.dope.validtype.ValidType

class ObjectUnwrapExpression(
objectExpression: TypeExpression<ObjectType>,
jansigi marked this conversation as resolved.
Show resolved Hide resolved
) : FunctionExpression<ValidType>("OBJECT_UNWRAP", objectExpression)

fun TypeExpression<ObjectType>.unwrap() = ObjectUnwrapExpression(this)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.`object`

import ch.ergon.dope.resolvable.expression.TypeExpression
import ch.ergon.dope.resolvable.expression.unaliased.type.function.FunctionExpression
import ch.ergon.dope.validtype.ArrayType
import ch.ergon.dope.validtype.ObjectType
import ch.ergon.dope.validtype.ValidType

class ObjectValuesExpression(
objectExpression: TypeExpression<ObjectType>,
) : FunctionExpression<ArrayType<out ValidType>>("OBJECT_VALUES", objectExpression)

fun TypeExpression<ObjectType>.values() = ObjectValuesExpression(this)
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package ch.ergon.dope.resolvable.expression.unaliased.type.function.`object`

import ch.ergon.dope.DopeQuery
import ch.ergon.dope.DopeQueryManager
import ch.ergon.dope.helper.ManagerDependentTest
import ch.ergon.dope.helper.someObjectField
import ch.ergon.dope.resolvable.expression.unaliased.type.ObjectEntryPrimitive
import ch.ergon.dope.resolvable.expression.unaliased.type.toDopeType
import kotlin.test.Test
import kotlin.test.assertEquals

class ObjectAddExpressionTest : ManagerDependentTest {
override lateinit var manager: DopeQueryManager

@Test
fun `should support object add expression`() {
val expected = DopeQuery(
queryString = "OBJECT_ADD(`objectField`, \"key\", \"value\")",
)
val underTest = ObjectAddExpression(someObjectField(), ObjectEntryPrimitive("key".toDopeType(), "value".toDopeType()))

val actual = underTest.toDopeQuery(manager)

assertEquals(expected, actual)
}

@Test
fun `should support object add function`() {
val objectExpression = someObjectField()
val newAttributeKey = "key".toDopeType()
val newAttributeValue = "value".toDopeType()
val expected = ObjectAddExpression(objectExpression, ObjectEntryPrimitive(newAttributeKey, newAttributeValue))

val actual = objectExpression.addAttribute(newAttributeKey, newAttributeValue)

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

@Test
fun `should support object add function string`() {
val objectExpression = someObjectField()
val newAttributeKey = "key"
val newAttributeValue = "value".toDopeType()
val expected = ObjectAddExpression(objectExpression, ObjectEntryPrimitive(newAttributeKey.toDopeType(), newAttributeValue))

val actual = objectExpression.addAttribute(newAttributeKey, newAttributeValue)

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