Skip to content

Commit f94a3ce

Browse files
committed
Added implementation of Mutations
1 parent 0f81329 commit f94a3ce

File tree

3 files changed

+66
-7
lines changed

3 files changed

+66
-7
lines changed

src/main/kotlin/org/neo4j/graphql/CrudOperations.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fun augmentedSchema(ctx: Translator.Context, type: ObjectTypeDefinition): Augmen
1717
Augmentation().copy(create = """create$typeName($fieldArgs) : $typeName """)
1818
.let { aug ->
1919
if (idField != null) aug.copy(
20-
delete = """delete$typeName($idFieldArg) : Boolean """,
20+
delete = """delete$typeName($idFieldArg) : $typeName """,
2121
update = """update$typeName($fieldArgs) : $typeName """)
2222
else aug
2323
}

src/main/kotlin/org/neo4j/graphql/Translator.kt

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,32 @@ class Translator(val schema: GraphQLSchema) {
6060
return cypherQueryOrMutation(variable, fieldDefinition, field, cypherDirective, mapProjection, ordering, skipLimit, isQuery)
6161

6262
} else {
63-
val where = if (ctx.topLevelWhere) where(variable, fieldDefinition, type, propertyArguments(field)) else Cypher.EMPTY
64-
val properties = if (ctx.topLevelWhere) Cypher.EMPTY else properties(variable, fieldDefinition, propertyArguments(field))
65-
return Cypher("MATCH ($variable:$label${properties.query})${where.query} RETURN ${mapProjection.query} AS $variable$ordering$skipLimit" ,
66-
(mapProjection.params + properties.params + where.params))
63+
if (isQuery) {
64+
val where = if (ctx.topLevelWhere) where(variable, fieldDefinition, type, propertyArguments(field)) else Cypher.EMPTY
65+
val properties = if (ctx.topLevelWhere) Cypher.EMPTY else properties(variable, fieldDefinition, propertyArguments(field))
66+
return Cypher("MATCH ($variable:$label${properties.query})${where.query} RETURN ${mapProjection.query} AS $variable$ordering$skipLimit",
67+
(mapProjection.params + properties.params + where.params))
68+
} else {
69+
// todo extract method or better object
70+
val properties = properties(variable, fieldDefinition, propertyArguments(field))
71+
val idProperty = fieldDefinition.arguments.find { it.type.inner() == Scalars.GraphQLID }
72+
val returnStatement = " WITH $variable RETURN ${mapProjection.query} AS $variable$ordering$skipLimit";
73+
return when (name) {
74+
"create"+type.name -> Cypher("CREATE ($variable:$label${properties.query})"+returnStatement, (mapProjection.params + properties.params))
75+
"update"+type.name -> {
76+
val setProperties = setProperties(variable, fieldDefinition, propertyArguments(field))
77+
Cypher("MATCH ($variable:$label {${idProperty!!.name.quote()}:\$${paramName(variable, idProperty.name, properties.params[idProperty.name])}}) "+setProperties.query + returnStatement,
78+
(mapProjection.params + setProperties.params))
79+
}
80+
"delete"+type.name -> {
81+
val paramName = paramName(variable, idProperty!!.name, properties.params[idProperty.name]) // todo currently wrong, needs to be paramName
82+
Cypher("MATCH ($variable:$label {${idProperty.name.quote()}:\$$paramName}) " +
83+
"WITH $variable as toDelete, ${mapProjection.query} AS $variable $ordering$skipLimit DETACH DELETE toDelete RETURN $variable",
84+
(mapProjection.params + mapOf(paramName to properties.params[paramName])))
85+
}
86+
else -> throw IllegalArgumentException("Unknown Mutation "+name)
87+
}
88+
}
6789
}
6890
}
6991

@@ -118,7 +140,12 @@ class Translator(val schema: GraphQLSchema) {
118140
private fun properties(variable: String, field: GraphQLFieldDefinition, arguments: List<Argument>) : Cypher {
119141
val all = preparePredicateArguments(field, arguments)
120142
return Cypher(all.map { (k,p, v) -> "${p.quote()}:\$${paramName(variable, k, v)}"}.joinToString(" , "," {","}") ,
121-
all.map { (k,p,v) -> paramName(variable, k, v) to v }.toMap())
143+
all.map { (k,_,v) -> paramName(variable, k, v) to v }.toMap())
144+
}
145+
private fun setProperties(variable: String, field: GraphQLFieldDefinition, arguments: List<Argument>) : Cypher {
146+
val all = preparePredicateArguments(field, arguments)
147+
return Cypher(all.map { (k,p, v) -> "${variable.quote()}.${p.quote()}=\$${paramName(variable, k, v)}"}.joinToString(","," SET "," ") ,
148+
all.map { (k,_,v) -> paramName(variable, k, v) to v }.toMap())
122149
}
123150

124151
data class CypherArgument(val name:String, val propertyName:String, val value:Any?)

src/test/kotlin/org/neo4j/graphql/AugmentationTest.kt

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ class AugmentationTest {
1414
type Person2 { name: String, age: [Int] }
1515
type Person3 { name: String!}
1616
type Person4 { id:ID!, name: String}
17+
type Person5 { id:ID!, movies:[Movie]}
18+
type Movie { id:ID! }
1719
""")
1820

1921
@Test
@@ -33,7 +35,7 @@ class AugmentationTest {
3335
augmentedSchema(ctx, typeFor("Person4")).let {
3436
assertEquals("createPerson4(id:ID!, name:String) : Person4 ",it.create)
3537
assertEquals("updatePerson4(id:ID!, name:String) : Person4 ",it.update)
36-
assertEquals("deletePerson4(id:ID!) : Boolean ",it.delete)
38+
assertEquals("deletePerson4(id:ID!) : Person4 ",it.delete)
3739
assertEquals("",it.query)
3840
}
3941

@@ -101,6 +103,7 @@ class AugmentationTest {
101103
assertEquals("input _Person3Input { name:String } ", augmentedSchema(ctx, typeFor("Person3")).inputType)
102104
assertEquals("input _Person4Input { id:ID, name:String } ", augmentedSchema(ctx, typeFor("Person4")).inputType)
103105
}
106+
104107
@Test
105108
fun testOrderings() {
106109
val ctx = Translator.Context(mutation = Translator.CRUDConfig(enabled = false), query = Translator.CRUDConfig(enabled = true, exclude = listOf("Person0")))
@@ -118,5 +121,34 @@ class AugmentationTest {
118121
assertEquals("enum _Person4Ordering { id_asc ,id_desc,name_asc ,name_desc } ", augmentedSchema(ctx, typeFor("Person4")).ordering)
119122
}
120123

124+
@Test
125+
fun testMutations() {
126+
val ctx = Translator.Context(mutation = Translator.CRUDConfig(enabled = true, exclude = listOf("Person0","Person1","Person2","Person3")), query = Translator.CRUDConfig(enabled = false))
127+
assertEquals("",augmentedSchema(ctx, typeFor("Person0")).ordering)
128+
assertEquals("",augmentedSchema(ctx, typeFor("Person1")).filterType)
129+
assertEquals("",augmentedSchema(ctx, typeFor("Person2")).query)
130+
assertEquals("",augmentedSchema(ctx, typeFor("Person3")).inputType)
131+
132+
augmentedSchema(ctx, typeFor("Person4")).let {
133+
assertEquals("",it.ordering)
134+
assertEquals("",it.filterType)
135+
assertEquals("createPerson4(id:ID!, name:String) : Person4 ",it.create)
136+
assertEquals("updatePerson4(id:ID!, name:String) : Person4 ",it.update)
137+
assertEquals("deletePerson4(id:ID!) : Person4 ",it.delete)
138+
}
139+
}
140+
141+
@Test
142+
fun testMutationForRelations() {
143+
val ctx = Translator.Context(mutation = Translator.CRUDConfig(enabled = true, exclude = listOf("Person0","Person1","Person2","Person3", "Person4")), query = Translator.CRUDConfig(enabled = false))
144+
augmentedSchema(ctx, typeFor("Person5")).let {
145+
assertEquals("",it.ordering)
146+
assertEquals("",it.filterType)
147+
assertEquals("createPerson5(id:ID!) : Person5 ",it.create)
148+
assertEquals("updatePerson5(id:ID!) : Person5 ",it.update)
149+
assertEquals("deletePerson5(id:ID!) : Person5 ",it.delete)
150+
}
151+
}
152+
121153
private fun typeFor(name: String) = types.getType(name).get() as ObjectTypeDefinition
122154
}

0 commit comments

Comments
 (0)