add schema TC
Project: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/commit/ca35bb56 Tree: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/tree/ca35bb56 Diff: http://git-wip-us.apache.org/repos/asf/incubator-s2graph/diff/ca35bb56 Branch: refs/heads/master Commit: ca35bb5649343f057a847d212e1d7206d94be079 Parents: e1f2bb4 Author: daewon <[email protected]> Authored: Tue Mar 6 18:50:08 2018 +0900 Committer: daewon <[email protected]> Committed: Tue Mar 6 18:50:08 2018 +0900 ---------------------------------------------------------------------- .../graphql/repository/GraphRepository.scala | 1 + .../graphql/types/S2ManagementType.scala | 129 ++++++------- .../apache/s2graph/graphql/types/S2Type.scala | 61 ++---- .../types/SangriaPlayJsonScalarType.scala | 152 +++++++-------- .../apache/s2graph/graphql/types/package.scala | 14 +- s2graphql/src/test/resources/application.conf | 17 +- .../s2graph/graphql/ArgumentParseTest.scala | 18 -- .../org/apache/s2graph/graphql/SchemaTest.scala | 191 +++++++++++++++++++ 8 files changed, 368 insertions(+), 215 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/ca35bb56/s2graphql/src/main/scala/org/apache/s2graph/graphql/repository/GraphRepository.scala ---------------------------------------------------------------------- diff --git a/s2graphql/src/main/scala/org/apache/s2graph/graphql/repository/GraphRepository.scala b/s2graphql/src/main/scala/org/apache/s2graph/graphql/repository/GraphRepository.scala index 2a0a2bf..2e34c27 100644 --- a/s2graphql/src/main/scala/org/apache/s2graph/graphql/repository/GraphRepository.scala +++ b/s2graphql/src/main/scala/org/apache/s2graph/graphql/repository/GraphRepository.scala @@ -194,6 +194,7 @@ class GraphRepository(val graph: S2GraphLike) { val ret = partialColumns.map { pc => val serviceName = pc.serviceName val columnName = pc.columnName + Try { pc.props.foreach { prop => Management.addVertexProp(serviceName, columnName, prop.name, prop.dataType, prop.defaultValue, prop.storeInGlobalIndex) http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/ca35bb56/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/S2ManagementType.scala ---------------------------------------------------------------------- diff --git a/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/S2ManagementType.scala b/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/S2ManagementType.scala index 0ea12e1..3317755 100644 --- a/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/S2ManagementType.scala +++ b/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/S2ManagementType.scala @@ -42,8 +42,8 @@ object S2ManagementType { case class MutationResponse[T](result: Try[T]) - def makeMutationResponseType[T](name: String, desc: String, tpe: ObjectType[_, T]) = { - ObjectType( + def makeMutationResponseType[T](name: String, desc: String, tpe: ObjectType[_, T]): ObjectType[Unit, MutationResponse[T]] = { + val retType = ObjectType( name, desc, () => fields[Unit, MutationResponse[T]]( @@ -64,6 +64,8 @@ object S2ManagementType { ) ) ) + + retType } } @@ -75,7 +77,7 @@ class S2ManagementType(repo: GraphRepository) { lazy val serviceColumnOnServiceWithPropInputObjectFields = repo.allServices.map { service => InputField(service.serviceName, OptionInputType(InputObjectType( - s"columnWithProp", + s"Input_Column_Props", description = "desc here", fields = List( InputField("columnName", makeServiceColumnEnumTypeOnService(service)), @@ -87,7 +89,7 @@ class S2ManagementType(repo: GraphRepository) { lazy val serviceColumnOnServiceInputObjectFields = repo.allServices.map { service => InputField(service.serviceName, OptionInputType(InputObjectType( - s"column", + s"Input_Column", description = "desc here", fields = List( InputField("columnName", makeServiceColumnEnumTypeOnService(service)) @@ -98,7 +100,7 @@ class S2ManagementType(repo: GraphRepository) { def makeServiceColumnEnumTypeOnService(service: Service): EnumType[String] = { val columns = service.serviceColumns(false).toList EnumType( - s"${service.serviceName}_columns", + s"Enum_${service.serviceName}_ServiceColumn", description = Option("desc here"), values = dummyEnum +: columns.map { column => EnumValue(column.columnName, value = column.columnName) @@ -106,9 +108,9 @@ class S2ManagementType(repo: GraphRepository) { ) } - lazy val labelMetaInputObjectFields = repo.allLabels.map { label => + lazy val labelPropsInputFields = repo.allLabels.map { label => InputField(label.label, OptionInputType(InputObjectType( - s"labelMetaOnLabel", + s"Input_${label.label}_props", description = "desc here", fields = List( InputField("props", ListInputType(InputPropType)) @@ -138,7 +140,7 @@ class S2ManagementType(repo: GraphRepository) { val dummyEnum = EnumValue("_", value = "_") lazy val ServiceListType = EnumType( - s"ServiceList", + s"Enum_Service", description = Option("desc here"), values = dummyEnum +: repo.allServices.map { service => @@ -147,7 +149,7 @@ class S2ManagementType(repo: GraphRepository) { ) lazy val ServiceColumnListType = EnumType( - s"ServiceColumnList", + s"Enum_ServiceColumn", description = Option("desc here"), values = dummyEnum +: repo.allServiceColumns.map { serviceColumn => @@ -155,8 +157,8 @@ class S2ManagementType(repo: GraphRepository) { } ) - lazy val LabelListType = EnumType( - s"LabelList", + lazy val EnumLabelsType = EnumType( + s"Enum_Label", description = Option("desc here"), values = dummyEnum +: repo.allLabels.map { label => @@ -177,24 +179,11 @@ class S2ManagementType(repo: GraphRepository) { ) lazy val LabelMutationResponseType = makeMutationResponseType[Label]( - "MutateLabelLabel", + "MutateLabel", "desc here", LabelType ) - lazy val serviceColumnField: Field[GraphRepository, Any] = Field( - "ServiceColumn", - ListType(ServiceColumnType), - description = Option("desc here"), - arguments = List(ServiceNameRawArg, ColumnNameArg, PropArg), - resolve = { c => - c.argOpt[String]("name") match { - case Some(name) => c.ctx.allServiceColumns.filter(_.columnName == name) - case None => c.ctx.allServiceColumns - } - } - ) - lazy val labelField: Field[GraphRepository, Any] = Field( "Labels", ListType(LabelType), @@ -217,53 +206,29 @@ class S2ManagementType(repo: GraphRepository) { ).map { case (name, _type) => Argument(name, OptionInputType(_type)) } val AddPropServiceType = InputObjectType[Vector[PartialServiceColumn]]( - "serviceName", + "Input_Service_ServiceColumn_Props", description = "desc", fields = serviceColumnOnServiceWithPropInputObjectFields ) val ServiceColumnSelectType = InputObjectType[Vector[PartialServiceColumn]]( - "serviceColumnSelect", + "Input_Service_ServiceColumn", description = "desc", fields = serviceColumnOnServiceInputObjectFields ) val LabelPropType = InputObjectType[Vector[PartialLabelMeta]]( - "labelMetaProp", + "Input_Label_Props", description = "desc", - fields = labelMetaInputObjectFields + fields = labelPropsInputFields ) - val SourceServiceType = InputObjectType[PartialServiceColumn]( - "sourceService", + val InputServiceType = InputObjectType[PartialServiceColumn]( + "Input_Service", description = "desc", fields = serviceColumnOnServiceInputObjectFields ) - val TargetServiceType = InputObjectType[PartialServiceColumn]( - "sourceService", - description = "desc", - fields = serviceColumnOnServiceInputObjectFields - ) - - lazy val labelRequiredArg = List( - "sourceService" -> SourceServiceType, - "targetService" -> TargetServiceType - ).map { case (name, _type) => Argument(name, _type) } - - val labelOptsArgs = List( - "serviceName" -> ServiceListType, - "consistencyLevel" -> ConsistencyLevelType, - "isDirected" -> BooleanType, - "isAsync" -> BooleanType, - "schemaVersion" -> StringType - ).map { case (name, _type) => Argument(name, OptionInputType(_type)) } - - - /** - * Management query - */ - lazy val serviceField: Field[GraphRepository, Any] = Field( "Services", ListType(ServiceType), @@ -277,17 +242,34 @@ class S2ManagementType(repo: GraphRepository) { } ) + /** + * Query Fields + * Provide s2graph management query API + */ lazy val queryFields: List[Field[GraphRepository, Any]] = List(serviceField, labelField) /** * Mutation fields - * Provide s2graph management API + * Provide s2graph management mutate API * * - createService * - createLabel * - ... */ + lazy val labelRequiredArg = List( + Argument("sourceService", InputServiceType), + Argument("targetService", InputServiceType) + ) + + val labelOptsArgs = List( + Argument("serviceName", OptionInputType(ServiceListType)), + Argument("consistencyLevel", OptionInputType(ConsistencyLevelType)), + Argument("isDirected", OptionInputType(BooleanType)), + Argument("isAsync", OptionInputType(BooleanType)), + Argument("schemaVersion", OptionInputType(StringType)) + ) + val NameArg = Argument("name", StringType, description = "desc here") lazy val ServiceNameArg = Argument("name", OptionInputType(ServiceListType), description = "desc here") @@ -298,7 +280,7 @@ class S2ManagementType(repo: GraphRepository) { lazy val ColumnTypeArg = Argument("columnType", DataTypeType, description = "desc here") - lazy val LabelNameArg = Argument("name", OptionInputType(LabelListType), description = "desc here") + lazy val LabelNameArg = Argument("name", OptionInputType(EnumLabelsType), description = "desc here") lazy val PropArg = Argument("props", OptionInputType(ListInputType(InputPropType)), description = "desc here") @@ -310,11 +292,29 @@ class S2ManagementType(repo: GraphRepository) { arguments = NameArg :: serviceOptArgs, resolve = c => MutationResponse(c.ctx.createService(c.args)) ), + + Field("createLabel", + LabelMutationResponseType, + arguments = NameArg :: PropArg :: IndicesArg :: labelRequiredArg ::: labelOptsArgs, + resolve = c => MutationResponse(c.ctx.createLabel(c.args)) + ), + Field("deleteLabel", + LabelMutationResponseType, + arguments = LabelNameArg :: Nil, + resolve = c => MutationResponse(c.ctx.deleteLabel(c.args)) + ), + Field("createServiceColumn", ServiceColumnMutationResponseType, arguments = List(ServiceNameRawArg, Argument("columnName", StringType), ColumnTypeArg, PropArg), resolve = c => MutationResponse(c.ctx.createServiceColumn(c.args)) ), + Field("deleteServiceColumn", + ListType(ServiceColumnMutationResponseType), + arguments = Argument("serviceName", ServiceColumnSelectType) :: Nil, + resolve = c => c.ctx.deleteServiceColumn(c.args).map(MutationResponse(_)) + ), + Field("addPropsToServiceColumn", ListType(ServiceColumnMutationResponseType), arguments = Argument("serviceName", AddPropServiceType) :: Nil, @@ -324,21 +324,6 @@ class S2ManagementType(repo: GraphRepository) { ListType(LabelMutationResponseType), arguments = Argument("labelName", LabelPropType) :: Nil, resolve = c => c.ctx.addPropsToLabel(c.args) map (MutationResponse(_)) - ), - Field("deleteServiceColumn", - ListType(ServiceColumnMutationResponseType), - arguments = Argument("serviceName", ServiceColumnSelectType) :: Nil, - resolve = c => c.ctx.deleteServiceColumn(c.args).map(MutationResponse(_)) - ), - Field("createLabel", - LabelMutationResponseType, - arguments = NameArg :: PropArg :: IndicesArg :: labelRequiredArg ::: labelOptsArgs, - resolve = c => MutationResponse(c.ctx.createLabel(c.args)) - ), - Field("deleteLabel", - LabelMutationResponseType, - arguments = LabelNameArg :: Nil, - resolve = c => MutationResponse(c.ctx.deleteLabel(c.args)) ) ) } http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/ca35bb56/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/S2Type.scala ---------------------------------------------------------------------- diff --git a/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/S2Type.scala b/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/S2Type.scala index 14e83e8..451dda3 100644 --- a/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/S2Type.scala +++ b/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/S2Type.scala @@ -35,6 +35,7 @@ import scala.util.{Failure, Success, Try} import org.apache.s2graph.graphql.marshaller._ object S2Type { + case class PartialLabelMeta(labelName: String, props: Seq[Prop] = Nil) @@ -100,7 +101,7 @@ object S2Type { def makeInputPartialVertexParamType(service: Service, serviceColumn: ServiceColumn): InputObjectType[PartialVertexParam] = { lazy val InputPropsType = InputObjectType[Map[String, ScalarType[_]]]( - s"${service.serviceName}_${serviceColumn.columnName}_props", + s"Input_${service.serviceName}_${serviceColumn.columnName}_vertex_props", description = "desc here", () => serviceColumn.metas.filter(ColumnMeta.isValid).map { lm => InputField(lm.name, OptionInputType(s2TypeToScalarType(lm.dataType))) @@ -112,7 +113,7 @@ object S2Type { ) InputObjectType[PartialVertexParam]( - s"${service.serviceName}_on_${serviceColumn.columnName}_mutate", + s"Input_${service.serviceName}_${serviceColumn.columnName}_vertex_mutate", description = "desc here", () => if (!serviceColumn.metas.exists(ColumnMeta.isValid)) fields @@ -122,7 +123,7 @@ object S2Type { def makeInputPartialEdgeParamType(label: Label): InputObjectType[PartialEdgeParam] = { lazy val InputPropsType = InputObjectType[Map[String, ScalarType[_]]]( - s"${label.label}_props", + s"Input_${label.label}_edge_props", description = "desc here", () => label.labelMetaSet.toList.map { lm => InputField(lm.name, OptionInputType(s2TypeToScalarType(lm.dataType))) @@ -137,7 +138,7 @@ object S2Type { ) InputObjectType[PartialEdgeParam]( - s"${label.label}_mutate", + s"Input_${label.label}_edge_mutate", description = "desc here", () => if (label.labelMetaSet.isEmpty) labelFields @@ -156,13 +157,14 @@ object S2Type { val reservedFields = List("id" -> column.columnType, "timestamp" -> "long") val vertexPropFields = makePropFields(reservedFields ++ columnMetasKv) - lazy val LabelType = ObjectType( - s"${service.serviceName}_${column.columnName}", + + lazy val ConnectedLabelType = ObjectType( + s"Input_${service.serviceName}_${column.columnName}", () => fields[GraphRepository, Any](vertexPropFields ++ connectedLabelFields: _*) ) Field(column.columnName, - ListType(LabelType), + ListType(ConnectedLabelType), arguments = List( Argument("id", OptionInputType(s2TypeToScalarType(column.columnType))), Argument("ids", OptionInputType(ListInputType(s2TypeToScalarType(column.columnType)))), @@ -197,10 +199,14 @@ object S2Type { val labelColumns = List("from" -> label.srcColumnType, "to" -> label.tgtColumnType, "timestamp" -> "long") val labelProps = label.labelMetas.map { lm => lm.name -> lm.dataType } - lazy val EdgeType = ObjectType(label.label, () => fields[GraphRepository, Any](edgeFields ++ connectedLabelFields: _*)) + lazy val EdgeType = ObjectType( + s"Label_${label.label}", + () => fields[GraphRepository, Any](edgeFields ++ connectedLabelFields: _*) + ) + lazy val edgeFields: List[Field[GraphRepository, Any]] = makePropFields(labelColumns ++ labelProps) lazy val edgeTypeField: Field[GraphRepository, Any] = Field( - label.label, + s"${label.label}", ListType(EdgeType), arguments = DirArg :: Nil, description = Some("edges"), @@ -236,7 +242,7 @@ class S2Type(repo: GraphRepository) { lazy val serviceFields: List[Field[GraphRepository, Any]] = repo.allServices.map { service => lazy val serviceFields = paddingDummyField(makeServiceField(service, repo.allLabels)) lazy val ServiceType = ObjectType( - service.serviceName, + s"Service_${service.serviceName}", fields[GraphRepository, Any](serviceFields: _*) ) @@ -251,38 +257,11 @@ class S2Type(repo: GraphRepository) { /** * arguments */ - lazy val addVertexArg = repo.allServices.map { service => - val columnFields = service.serviceColumns(false).map { serviceColumn => - - val columnMetas = serviceColumn.metas.filter(ColumnMeta.isValid).map { lm => - InputField(lm.name, OptionInputType(s2TypeToScalarType(lm.dataType))) - } - - lazy val InputPropsType = InputObjectType[Map[String, ScalarType[_]]]( - s"${service.serviceName}_${serviceColumn.columnName}_props", - description = "desc here", - () => if (columnMetas.isEmpty) List(DummyInputField) else columnMetas.toList - ) - - val tpe = InputObjectType[PartialServiceVertexParam]( - serviceColumn.columnName, - fields = List( - InputField("id", s2TypeToScalarType(serviceColumn.columnType)), - InputField("timestamp", OptionInputType(LongType)), - InputField("props", OptionInputType(InputPropsType)) - ) - ) - - InputField(serviceColumn.columnName, OptionInputType(tpe)) + lazy val addVertexArg = repo.allServices.flatMap { service => + service.serviceColumns(false).map { serviceColumn => + val inputPartialVertexParamType = makeInputPartialVertexParamType(service, serviceColumn) + Argument(serviceColumn.columnName, OptionInputType(inputPartialVertexParamType)) } - - val vertexParamType = InputObjectType[Vector[PartialServiceVertexParam]]( - s"${service.serviceName}_column", - description = "desc here", - fields = if (columnFields.isEmpty) List(DummyInputField) else columnFields.toList - ) - - Argument(service.serviceName, OptionInputType(vertexParamType)) } lazy val addVerticesArg = repo.allServices.flatMap { service => http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/ca35bb56/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/SangriaPlayJsonScalarType.scala ---------------------------------------------------------------------- diff --git a/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/SangriaPlayJsonScalarType.scala b/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/SangriaPlayJsonScalarType.scala index dcb3621..723392c 100644 --- a/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/SangriaPlayJsonScalarType.scala +++ b/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/SangriaPlayJsonScalarType.scala @@ -1,76 +1,76 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.s2graph.graphql.types - -import sangria.ast._ -import sangria.validation.ValueCoercionViolation - -// https://gist.github.com/OlegIlyenko/5b96f4b54f656aac226d3c4bc33fd2a6 - -object PlayJsonPolyType { - - import play.api.libs.json._ - import sangria.ast - import sangria.schema._ - - case object JsonCoercionViolation extends ValueCoercionViolation("Not valid JSON") - - def scalarTypeToJsValue(v: sangria.ast.Value): JsValue = v match { - case v: IntValue => JsNumber(v.value) - case v: BigIntValue => JsNumber(BigDecimal(v.value.bigInteger)) - case v: FloatValue => JsNumber(v.value) - case v: BigDecimalValue => JsNumber(v.value) - case v: StringValue => JsString(v.value) - case v: BooleanValue => JsBoolean(v.value) - case v: ListValue => JsNull - case v: VariableValue => JsNull - case v: NullValue => JsNull - case v: ObjectValue => JsNull - case _ => throw new RuntimeException("Error!") - } - - implicit val PolyType = ScalarType[JsValue]("Poly", - description = Some("Type Poly = String | Number | Boolean"), - coerceOutput = (value, _) â value match { - case JsString(s) => s - case JsNumber(n) => n - case JsBoolean(b) => b - case JsNull => null - case _ => value - }, - coerceUserInput = { - case v: String => Right(JsString(v)) - case v: Boolean => Right(JsBoolean(v)) - case v: Int => Right(JsNumber(v)) - case v: Long => Right(JsNumber(v)) - case v: Float => Right(JsNumber(v.toDouble)) - case v: Double => Right(JsNumber(v)) - case v: BigInt => Right(JsNumber(BigDecimal(v))) - case v: BigDecimal => Right(JsNumber(v)) - case _ => Left(JsonCoercionViolation) - }, - coerceInput = { - case value: ast.StringValue => Right(JsString(value.value)) - case value: ast.IntValue => Right(JsNumber(value.value)) - case value: ast.FloatValue => Right(JsNumber(value.value)) - case value: ast.BigIntValue => Right(JsNumber(BigDecimal(value.value.bigInteger))) - case _ => Left(JsonCoercionViolation) - }) -} +///* +// * Licensed to the Apache Software Foundation (ASF) under one +// * or more contributor license agreements. See the NOTICE file +// * distributed with this work for additional information +// * regarding copyright ownership. The ASF licenses this file +// * to you under the Apache License, Version 2.0 (the +// * "License"); you may not use this file except in compliance +// * with the License. You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, +// * software distributed under the License is distributed on an +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// * KIND, either express or implied. See the License for the +// * specific language governing permissions and limitations +// * under the License. +// */ +// +//package org.apache.s2graph.graphql.types +// +//import sangria.ast._ +//import sangria.validation.ValueCoercionViolation +// +//// https://gist.github.com/OlegIlyenko/5b96f4b54f656aac226d3c4bc33fd2a6 +// +//object PlayJsonPolyType { +// +// import play.api.libs.json._ +// import sangria.ast +// import sangria.schema._ +// +// case object JsonCoercionViolation extends ValueCoercionViolation("Not valid JSON") +// +// def scalarTypeToJsValue(v: sangria.ast.Value): JsValue = v match { +// case v: IntValue => JsNumber(v.value) +// case v: BigIntValue => JsNumber(BigDecimal(v.value.bigInteger)) +// case v: FloatValue => JsNumber(v.value) +// case v: BigDecimalValue => JsNumber(v.value) +// case v: StringValue => JsString(v.value) +// case v: BooleanValue => JsBoolean(v.value) +// case v: ListValue => JsNull +// case v: VariableValue => JsNull +// case v: NullValue => JsNull +// case v: ObjectValue => JsNull +// case _ => throw new RuntimeException("Error!") +// } +// +// implicit val PolyType = ScalarType[JsValue]("Poly", +// description = Some("Type Poly = String | Number | Boolean"), +// coerceOutput = (value, _) â value match { +// case JsString(s) => s +// case JsNumber(n) => n +// case JsBoolean(b) => b +// case JsNull => null +// case _ => value +// }, +// coerceUserInput = { +// case v: String => Right(JsString(v)) +// case v: Boolean => Right(JsBoolean(v)) +// case v: Int => Right(JsNumber(v)) +// case v: Long => Right(JsNumber(v)) +// case v: Float => Right(JsNumber(v.toDouble)) +// case v: Double => Right(JsNumber(v)) +// case v: BigInt => Right(JsNumber(BigDecimal(v))) +// case v: BigDecimal => Right(JsNumber(v)) +// case _ => Left(JsonCoercionViolation) +// }, +// coerceInput = { +// case value: ast.StringValue => Right(JsString(value.value)) +// case value: ast.IntValue => Right(JsNumber(value.value)) +// case value: ast.FloatValue => Right(JsNumber(value.value)) +// case value: ast.BigIntValue => Right(JsNumber(BigDecimal(value.value.bigInteger))) +// case _ => Left(JsonCoercionViolation) +// }) +//} http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/ca35bb56/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/package.scala ---------------------------------------------------------------------- diff --git a/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/package.scala b/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/package.scala index 1cbf130..8bfb706 100644 --- a/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/package.scala +++ b/s2graphql/src/main/scala/org/apache/s2graph/graphql/types/package.scala @@ -50,7 +50,7 @@ package object types { } val MutateResponseType = deriveObjectType[GraphRepository, MutateResponse]( - ObjectTypeName("MutateResponse"), + ObjectTypeName("MutateGraphElement"), ObjectTypeDescription("desc here"), AddFields( Field("isSuccess", BooleanType, resolve = c => c.value.isSuccess) @@ -58,7 +58,7 @@ package object types { ) val DataTypeType = EnumType( - "DataType", + "Enum_DataType", description = Option("desc here"), values = List( EnumValue("string", value = "string"), @@ -70,7 +70,7 @@ package object types { ) val DirectionType = EnumType( - "Direction", + "Enum_Direction", description = Option("desc here"), values = List( EnumValue("out", value = "out"), @@ -89,7 +89,7 @@ package object types { ) val InputIndexType = InputObjectType[Index]( - "Index", + "Input_Index", description = "desc here", fields = List( InputField("name", StringType), @@ -98,7 +98,7 @@ package object types { ) val InputPropType = InputObjectType[Prop]( - "Prop", + "Input_Prop", description = "desc here", fields = List( InputField("name", StringType), @@ -109,7 +109,7 @@ package object types { ) val CompressionAlgorithmType = EnumType( - "CompressionAlgorithm", + "Enum_CompressionAlgorithm", description = Option("desc here"), values = List( EnumValue("gz", description = Option("desc here"), value = "gz"), @@ -118,7 +118,7 @@ package object types { ) val ConsistencyLevelType = EnumType( - "ConsistencyList", + "Enum_Consistency", description = Option("desc here"), values = List( EnumValue("weak", description = Option("desc here"), value = "weak"), http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/ca35bb56/s2graphql/src/test/resources/application.conf ---------------------------------------------------------------------- diff --git a/s2graphql/src/test/resources/application.conf b/s2graphql/src/test/resources/application.conf index 5fb2552..d070a59 100644 --- a/s2graphql/src/test/resources/application.conf +++ b/s2graphql/src/test/resources/application.conf @@ -15,4 +15,19 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -# \ No newline at end of file +# +akka { + loggers = ["akka.event.slf4j.Slf4jLogger"] + event-handlers = ["akka.event.slf4j.Slf4jEventHandler"] + loglevel = "INFO" +} + +db.default.url="jdbc:h2:file:./var/metastore;MODE=MYSQL", +db.default.password = sa +db.default.user = sa +s2graph.storage.backend = rocks + +rocks.storage.file.path = rocks_db +rocks.storage.mode = production +rocks.storage.ttl = -1 +rocks.storage.read.only = false \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/ca35bb56/s2graphql/src/test/scala/org/apache/s2graph/graphql/ArgumentParseTest.scala ---------------------------------------------------------------------- diff --git a/s2graphql/src/test/scala/org/apache/s2graph/graphql/ArgumentParseTest.scala b/s2graphql/src/test/scala/org/apache/s2graph/graphql/ArgumentParseTest.scala deleted file mode 100644 index a1c076a..0000000 --- a/s2graphql/src/test/scala/org/apache/s2graph/graphql/ArgumentParseTest.scala +++ /dev/null @@ -1,18 +0,0 @@ -package org.apache.s2graph.graphql - -import org.scalatest.{FunSuite, Matchers} -import play.api.libs.json.{JsObject, JsString, Json} -import sangria.ast.Document - -import scala.concurrent.Await -import scala.concurrent.duration._ -import scala.concurrent.ExecutionContext.Implicits.global -import sangria.macros._ -import sangria.execution.Executor -import sangria.execution.deferred.DeferredResolver - -class ArgumentParseTest extends FunSuite with Matchers { - test("parseAddPropsToServiceColumn") { - true - } -} http://git-wip-us.apache.org/repos/asf/incubator-s2graph/blob/ca35bb56/s2graphql/src/test/scala/org/apache/s2graph/graphql/SchemaTest.scala ---------------------------------------------------------------------- diff --git a/s2graphql/src/test/scala/org/apache/s2graph/graphql/SchemaTest.scala b/s2graphql/src/test/scala/org/apache/s2graph/graphql/SchemaTest.scala new file mode 100644 index 0000000..6ff3d02 --- /dev/null +++ b/s2graphql/src/test/scala/org/apache/s2graph/graphql/SchemaTest.scala @@ -0,0 +1,191 @@ +package org.apache.s2graph.graphql + +import com.typesafe.config.{Config, ConfigFactory} +import org.apache.s2graph.core.Management.JsonModel.Prop +import org.apache.s2graph.core.mysqls.{Label, Service} +import org.apache.s2graph.core.{Management, S2Graph} +import org.apache.s2graph.core.rest.RequestParser +import org.apache.s2graph.graphql.repository.GraphRepository +import org.scalatest.{BeforeAndAfterAll, FunSuite, Matchers} +import play.api.libs.json.{JsObject, JsString, Json} +import sangria.ast.Document + +import scala.concurrent.Await +import scala.concurrent.duration._ +import scala.concurrent.ExecutionContext.Implicits.global +import sangria.macros._ +import sangria.execution.Executor +import sangria.execution.deferred.DeferredResolver +import sangria.parser.QueryParser +import sangria.renderer.SchemaRenderer + +import scala.util._ + +class SchemaTest extends FunSuite with Matchers with BeforeAndAfterAll { + var graph: S2Graph = _ + var parser: RequestParser = _ + var management: Management = _ + var config: Config = _ + var s2Repository: GraphRepository = _ + + override def beforeAll = { + config = ConfigFactory.load() + graph = new S2Graph(config)(scala.concurrent.ExecutionContext.Implicits.global) + management = new Management(graph) + parser = new RequestParser(graph) + s2Repository = new GraphRepository(graph) + + // Init test data + val serviceName = "kakao" + val labelName = "friends" + val columnName = "user" + + Management.deleteService(serviceName) + val serviceTry: Try[Service] = + management.createService( + serviceName, + "localhost", + s"${serviceName}_table", + 1, + None + ) + + val serviceColumnTry = serviceTry.map { _ => + management.createServiceColumn( + serviceName, + columnName, + "string", + List( + Prop("age", "0", "int"), + Prop("gender", "", "string") + ) + ) + } + + Management.deleteLabel(labelName) + val labelTry: Try[Label] = + management.createLabel( + labelName, + serviceName, columnName, "string", + serviceName, columnName, "string", + true, serviceName, + Nil, + Seq(Prop("score", "0", "int")), + "strong" + ) + + val isPrepared = List(serviceTry, serviceColumnTry, labelTry).forall(_.isSuccess) + + require(isPrepared, "should created metadata") + } + + override def afterAll(): Unit = { + graph.shutdown(true) + } + + test("s2 schema") { + val s2Schema = new SchemaDef(s2Repository).S2GraphSchema + println(SchemaRenderer.renderSchema(s2Schema)) + + true + } + + test("s2 schema should has types") { + val s2Schema = new SchemaDef(s2Repository).S2GraphSchema + + val Success(query) = QueryParser.parse( + """ + query IntrospectionTypeQuery { + __schema { + types { + name + } + } + } + """) + + val expected: Map[String, Map[String, Map[String, Vector[Map[String, String]]]]] = + Map("data" -> + Map("__schema" -> + Map("types" -> Vector( + Map("name" -> "Enum_CompressionAlgorithm"), + Map("name" -> "Enum_Consistency"), + Map("name" -> "Enum_DataType"), + Map("name" -> "Enum_Direction"), + + Map("name" -> "MutateLabel"), + Map("name" -> "MutateGraphElement"), + Map("name" -> "MutateService"), + Map("name" -> "MutateServiceColumn"), + + Map("name" -> "Input_Service"), + Map("name" -> "Input_Index"), + Map("name" -> "Input_Prop"), + Map("name" -> "Input_Label_Props"), + Map("name" -> "Input_Column"), + Map("name" -> "Input_Column_Props"), + + Map("name" -> "ColumnMeta"), + Map("name" -> "LabelMeta"), + + Map("name" -> "Label"), + Map("name" -> "LabelIndex"), + + Map("name" -> "Service"), + Map("name" -> "ServiceColumn"), + + Map("name" -> "Input_friends_edge_mutate"), + Map("name" -> "Input_friends_edge_props"), + + Map("name" -> "Input_friends_props"), + + Map("name" -> "Input_Service_ServiceColumn"), + Map("name" -> "Input_Service_ServiceColumn_Props"), + + Map("name" -> "Input_kakao_user"), + Map("name" -> "Input_kakao_user_vertex_mutate"), + Map("name" -> "Input_kakao_user_vertex_props"), + + Map("name" -> "Enum_Service"), + Map("name" -> "Enum_Label"), + Map("name" -> "Enum_kakao_ServiceColumn"), + + Map("name" -> "Service_kakao"), + Map("name" -> "Label_friends"), + + // root object type + Map("name" -> "Query"), + Map("name" -> "QueryManagement"), + Map("name" -> "Mutation"), + Map("name" -> "MutationManagement"), + + // graphql internal type + Map("name" -> "__Directive"), + Map("name" -> "__DirectiveLocation"), + Map("name" -> "__EnumValue"), + Map("name" -> "__Field"), + Map("name" -> "__InputValue"), + Map("name" -> "__Schema"), + Map("name" -> "__Type"), + Map("name" -> "__TypeKind"), + Map("name" -> "Boolean"), + Map("name" -> "Int"), + Map("name" -> "Long"), + Map("name" -> "String")) + ) + ) + ) + + + val ret = Await.result(Executor.execute(s2Schema, query, s2Repository), Duration("10 sec")) + val maps = ret.asInstanceOf[Map[String, Map[String, Map[String, Vector[Map[String, String]]]]]]("data")("__schema")("types") + + val expectedSet = (expected("data")("__schema")("types").flatMap(_.values.headOption).toSet) + val retSet = (maps.flatMap(_.values.headOption).toSet) + + println(expectedSet -- retSet) + println(retSet -- expectedSet) + + retSet should be(expectedSet) + } +}
