imbajin commented on code in PR #3209: URL: https://github.com/apache/hugegraph/pull/3209#discussion_r4144176011
########## hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/graph/PropertiesDeserializer.java: ########## @@ -0,0 +1,102 @@ +/* + * 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.hugegraph.api.graph; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonMappingException; + +/** + * Reads the "properties" object of a vertex or edge body so that a JSON + * fraction keeps every digit: it becomes a BigDecimal instead of a double, + * which is what a DECIMAL property key needs and what every numeric key + * narrows through DataType.valueToNumber as before. Only property values Review Comment: ⚠️ The exact-number parser is applied only to graph element properties; schema userdata still uses Jackson’s default untyped numbers. A DECIMAL `~default_value` such as `0.1234567890123456789` therefore reaches `PropertyKeyAPI` as a `Double`, and `valueToDecimal()` can only reconstruct its already-rounded text. Please preserve fractional defaults as `BigDecimal` or reject numeric fractions and require strings, with an exact default-value case. ########## hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/DataType.java: ########## @@ -43,7 +45,14 @@ public enum DataType implements SerialEnum { TEXT(8, "text", String.class), BLOB(9, "blob", Blob.class), DATE(10, "date", Date.class), - UUID(11, "uuid", UUID.class); + UUID(11, "uuid", UUID.class), + /* + * Arbitrary-precision decimal (java.math.BigDecimal). Stored exactly; not a + * "number" in the isNumber() sense because it has no fixed-width, sortable + * encoding, so it can't be a sort key, a range/secondary index field or an + * OLAP range property. + */ + DECIMAL(12, "decimal", BigDecimal.class); Review Comment: 🧹 The PR body marks the `hugegraph-doc` data-type page as TODO and says it will be a separate PR; this diff has no docs files or paired link. Root `AGENTS.md` requires matching user-facing docs and a linked paired docs PR when website docs live separately. Please add the docs update or link the paired `hugegraph-doc` change and coordinate it with this feature. ########## hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/graph/PropertiesDeserializer.java: ########## @@ -0,0 +1,102 @@ +/* + * 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.hugegraph.api.graph; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonMappingException; + +/** + * Reads the "properties" object of a vertex or edge body so that a JSON + * fraction keeps every digit: it becomes a BigDecimal instead of a double, + * which is what a DECIMAL property key needs and what every numeric key + * narrows through DataType.valueToNumber as before. Only property values + * are read this way; the rest of the request body (job parameters, schema + * userdata, query options) keeps Jackson's default number types. + */ +public class PropertiesDeserializer extends JsonDeserializer<Map<String, Object>> { + + @Override + public Map<String, Object> deserialize(JsonParser parser, + DeserializationContext ctxt) + throws IOException { + JsonToken token = parser.currentToken(); + if (token == JsonToken.VALUE_NULL) { + return null; + } + if (token != JsonToken.START_OBJECT) { + throw JsonMappingException.from(parser, + "Expected an object for 'properties', but got " + token); + } + return readObject(parser); + } + + private static Map<String, Object> readObject(JsonParser parser) + throws IOException { + Map<String, Object> object = new LinkedHashMap<>(); + while (parser.nextToken() != JsonToken.END_OBJECT) { + String name = parser.currentName(); + parser.nextToken(); + object.put(name, readValue(parser)); + } + return object; + } + + private static List<Object> readArray(JsonParser parser) + throws IOException { + List<Object> array = new ArrayList<>(); + while (parser.nextToken() != JsonToken.END_ARRAY) { + array.add(readValue(parser)); + } + return array; + } + + private static Object readValue(JsonParser parser) throws IOException { + JsonToken token = parser.currentToken(); + switch (token) { + case START_OBJECT: + return readObject(parser); + case START_ARRAY: + return readArray(parser); + case VALUE_STRING: + return parser.getText(); + case VALUE_NUMBER_INT: + return parser.getNumberValue(); + case VALUE_NUMBER_FLOAT: + // Exact: the literal's digits, not the nearest double + return parser.getDecimalValue(); Review Comment: ⚠️ Vertex and edge list filters still parse query `properties` through `API.parseProperties(..., Map.class)`, where untyped fractional numbers become `Double`; `0.100000000000000001` is rounded to `0.1` before DECIMAL comparison. This parser only handles request-body properties. Please preserve filter precision or normalize each value against its schema type before building the traversal. ########## hugegraph-struct/src/main/java/org/apache/hugegraph/query/serializer/QueryAdapter.java: ########## @@ -48,8 +50,13 @@ public class QueryAdapter extends AbstractSerializerAdapter<Condition> { .build(); static boolean isPrimitive(Class clz) { + // Values whose class must travel with them: Gson reads an untyped Review Comment: ⚠️ This new class-tag handling preserves BigDecimal scale in `IN`/`NOT_IN` lists, but `Condition.RelationType.IN/NOT_IN` uses `Collection.contains`, which calls scale-sensitive `BigDecimal.equals`. A stored `1.0` therefore misses `P.within(new BigDecimal("1.00"))`, although scalar DECIMAL equality treats them as equal. Compare decimal collection members numerically. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
