Skip to content

Commit

Permalink
feat: add support of @fieldTypes in the json from new query engine
Browse files Browse the repository at this point in the history
  • Loading branch information
tglman committed Nov 23, 2023
1 parent 8902c29 commit a69005a
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.record.impl.ODocumentHelper;
import com.orientechnologies.orient.core.serialization.serializer.OJSONWriter;
import com.orientechnologies.orient.core.serialization.serializer.record.string.ORecordSerializerJSON;
import com.orientechnologies.orient.core.serialization.serializer.record.string.OFieldTypesString;
import com.orientechnologies.orient.core.serialization.serializer.record.string.ORecordSerializerJSON.FormatSettings;
import java.io.IOException;
import java.math.BigDecimal;
Expand Down Expand Up @@ -61,7 +61,7 @@ public void onAfterFetch(final ODocument rootRecord) {
jsonWriter.writeAttribute(
settings.indentLevel > -1 ? settings.indentLevel : 1,
true,
ORecordSerializerJSON.ATTRIBUTE_FIELD_TYPES,
OFieldTypesString.ATTRIBUTE_FIELD_TYPES,
sb.toString());
} catch (final IOException e) {
throw OException.wrapException(new OFetchException("Error writing field types"), e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public class ODocumentHelper {
public static final String ATTRIBUTE_TYPE = "@type";
public static final String ATTRIBUTE_SIZE = "@size";
public static final String ATTRIBUTE_FIELDS = "@fields";
public static final String ATTRIBUTE_FIELS_TYPES = "@fieldtypes";
public static final String ATTRIBUTE_RAW = "@raw";

public static interface ODbRelatedCall<T> {
Expand All @@ -109,6 +110,7 @@ public static Set<String> getReservedAttributes() {
retSet.add(ATTRIBUTE_SIZE);
retSet.add(ATTRIBUTE_FIELDS);
retSet.add(ATTRIBUTE_RAW);
retSet.add(ATTRIBUTE_FIELS_TYPES);
return retSet;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.orientechnologies.orient.core.serialization.serializer.record.string;

import com.orientechnologies.orient.core.metadata.schema.OType;
import java.util.HashMap;
import java.util.Map;

public class OFieldTypesString {

public static final String ATTRIBUTE_FIELD_TYPES = "@fieldTypes";

/**
* Parses the field type char returning the closer type. Default is STRING. b=binary if
* iValue.length() >= 4 b=byte if iValue.length() <= 3 s=short, l=long f=float d=double a=date
* t=datetime
*
* @param iValue Value to parse
* @param iCharType Char value indicating the type
* @return The closest type recognized
*/
public static OType getType(final String iValue, final char iCharType) {
if (iCharType == 'f') return OType.FLOAT;
else if (iCharType == 'c') return OType.DECIMAL;
else if (iCharType == 'l') return OType.LONG;
else if (iCharType == 'd') return OType.DOUBLE;
else if (iCharType == 'b') {
if (iValue.length() >= 1 && iValue.length() <= 3) return OType.BYTE;
else return OType.BINARY;
} else if (iCharType == 'a') return OType.DATE;
else if (iCharType == 't') return OType.DATETIME;
else if (iCharType == 's') return OType.SHORT;
else if (iCharType == 'e') return OType.EMBEDDEDSET;
else if (iCharType == 'g') return OType.LINKBAG;
else if (iCharType == 'z') return OType.LINKLIST;
else if (iCharType == 'm') return OType.LINKMAP;
else if (iCharType == 'x') return OType.LINK;
else if (iCharType == 'n') return OType.LINKSET;
else if (iCharType == 'u') return OType.CUSTOM;

return OType.STRING;
}

public static OType getOTypeFromChar(final char iCharType) {
if (iCharType == 'f') return OType.FLOAT;
else if (iCharType == 'c') return OType.DECIMAL;
else if (iCharType == 'l') return OType.LONG;
else if (iCharType == 'd') return OType.DOUBLE;
else if (iCharType == 'b') return OType.BINARY;
else if (iCharType == 'a') return OType.DATE;
else if (iCharType == 't') return OType.DATETIME;
else if (iCharType == 's') return OType.SHORT;
else if (iCharType == 'e') return OType.EMBEDDEDSET;
else if (iCharType == 'g') return OType.LINKBAG;
else if (iCharType == 'z') return OType.LINKLIST;
else if (iCharType == 'm') return OType.LINKMAP;
else if (iCharType == 'x') return OType.LINK;
else if (iCharType == 'n') return OType.LINKSET;
else if (iCharType == 'u') return OType.CUSTOM;

return OType.STRING;
}

public static Map<String, Character> loadFieldTypesV0(
Map<String, Character> fieldTypes, final String fieldValueAsString) {
// LOAD THE FIELD TYPE MAP
final String[] fieldTypesParts = fieldValueAsString.split(",");
if (fieldTypesParts.length > 0) {
if (fieldTypes == null) {
fieldTypes = new HashMap<>();
}
String[] part;
for (String f : fieldTypesParts) {
part = f.split("=");
if (part.length == 2) fieldTypes.put(part[0], part[1].charAt(0));
}
}
return fieldTypes;
}

public static Map<String, Character> loadFieldTypes(final String fieldValueAsString) {
Map<String, Character> fieldTypes = new HashMap<>();
loadFieldTypesV0(fieldTypes, fieldValueAsString);
return fieldTypes;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@
import com.orientechnologies.orient.core.Orient;
import com.orientechnologies.orient.core.db.ODatabaseRecordThreadLocal;
import com.orientechnologies.orient.core.db.document.ODatabaseDocument;
import com.orientechnologies.orient.core.db.record.*;
import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.db.record.ORecordLazyList;
import com.orientechnologies.orient.core.db.record.ORecordLazyMultiValue;
import com.orientechnologies.orient.core.db.record.ORecordLazySet;
import com.orientechnologies.orient.core.db.record.OTrackedList;
import com.orientechnologies.orient.core.db.record.OTrackedSet;
import com.orientechnologies.orient.core.db.record.ridbag.ORidBag;
import com.orientechnologies.orient.core.exception.OSerializationException;
import com.orientechnologies.orient.core.fetch.OFetchHelper;
Expand All @@ -43,19 +48,32 @@
import com.orientechnologies.orient.core.record.ORecord;
import com.orientechnologies.orient.core.record.ORecordInternal;
import com.orientechnologies.orient.core.record.ORecordStringable;
import com.orientechnologies.orient.core.record.impl.*;
import com.orientechnologies.orient.core.record.impl.OBlob;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.record.impl.ODocumentEmbedded;
import com.orientechnologies.orient.core.record.impl.ODocumentHelper;
import com.orientechnologies.orient.core.record.impl.ODocumentInternal;
import com.orientechnologies.orient.core.serialization.serializer.OJSONWriter;
import com.orientechnologies.orient.core.serialization.serializer.OStringSerializerHelper;
import com.orientechnologies.orient.core.util.ODateHelper;
import java.io.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.StringWriter;
import java.text.ParseException;
import java.util.*;
import java.util.Base64;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@SuppressWarnings("serial")
public class ORecordSerializerJSON extends ORecordSerializerStringAbstract {
public static final String NAME = "json";
public static final ORecordSerializerJSON INSTANCE = new ORecordSerializerJSON();
public static final String ATTRIBUTE_FIELD_TYPES = "@fieldTypes";
public static final char[] PARAMETER_SEPARATOR = new char[] {':', ','};
public static final int INITIAL_SIZE = 5000;
private static final Long MAX_INT = (long) Integer.MAX_VALUE;
Expand Down Expand Up @@ -219,8 +237,9 @@ public ORecord fromStringV0(
final String fieldValue = fields.get(i + 1);
final String fieldValueAsString = OIOUtils.getStringContent(fieldValue);

if (fieldName.equals(ATTRIBUTE_FIELD_TYPES) && record instanceof ODocument) {
fieldTypes = loadFieldTypesV0(fieldTypes, fieldValueAsString);
if (fieldName.equals(OFieldTypesString.ATTRIBUTE_FIELD_TYPES)
&& record instanceof ODocument) {
fieldTypes = OFieldTypesString.loadFieldTypesV0(fieldTypes, fieldValueAsString);
} else if (fieldName.equals(ODocumentHelper.ATTRIBUTE_TYPE)) {
if (record == null
|| ORecordInternal.getRecordType(record) != fieldValueAsString.charAt(0)) {
Expand Down Expand Up @@ -298,7 +317,8 @@ private void processRecordsV0(
return;
} else if (fieldName.equals(ODocumentHelper.ATTRIBUTE_TYPE)) {
return;
} else if (fieldName.equals(ATTRIBUTE_FIELD_TYPES) && record instanceof ODocument) {
} else if (fieldName.equals(OFieldTypesString.ATTRIBUTE_FIELD_TYPES)
&& record instanceof ODocument) {
return;
} else if (fieldName.equals("value") && !(record instanceof ODocument)) {
// RECORD VALUE(S)
Expand Down Expand Up @@ -367,7 +387,7 @@ else if (record instanceof OBlob) {
}

if (type == null && fieldTypes != null && fieldTypes.containsKey(fieldName))
type = ORecordSerializerStringAbstract.getType(fieldValue, fieldTypes.get(fieldName));
type = OFieldTypesString.getType(fieldValue, fieldTypes.get(fieldName));

if (v instanceof OTrackedSet<?>) {
if (OMultiValue.getFirstValue(v) instanceof OIdentifiable) type = OType.LINKSET;
Expand Down Expand Up @@ -487,21 +507,6 @@ private OType determineType(ODocument doc, String fieldName) {
return type;
}

private Map<String, Character> loadFieldTypesV0(
Map<String, Character> fieldTypes, final String fieldValueAsString) {
// LOAD THE FIELD TYPE MAP
final String[] fieldTypesParts = fieldValueAsString.split(",");
if (fieldTypesParts.length > 0) {
fieldTypes = new HashMap<>();
String[] part;
for (String f : fieldTypesParts) {
part = f.split("=");
if (part.length == 2) fieldTypes.put(part[0], part[1].charAt(0));
}
}
return fieldTypes;
}

@SuppressWarnings("unchecked")
private Object getValueV0(
final ODocument iRecord,
Expand All @@ -525,7 +530,7 @@ private Object getValueV0(
}

if (iType == null && iFieldTypes != null && iFieldTypes.containsKey(iFieldName))
iType = ORecordSerializerStringAbstract.getType(iFieldValue, iFieldTypes.get(iFieldName));
iType = OFieldTypesString.getType(iFieldValue, iFieldTypes.get(iFieldName));

if (iFieldValue.startsWith("{") && iFieldValue.endsWith("}")) {
// Json object
Expand Down Expand Up @@ -577,7 +582,7 @@ else if (iFieldValue.matches(".*[\\.Ee].*")) {

if (iFieldTypes != null) {
Character c = iFieldTypes.get(iFieldName);
if (c != null) iType = ORecordSerializerStringAbstract.getType(iFieldValueAsString, c);
if (c != null) iType = OFieldTypesString.getType(iFieldValueAsString, c);
}

if (iType == null) iType = OType.STRING;
Expand Down Expand Up @@ -670,13 +675,6 @@ private boolean canBeTrunkedToInt(Long v) {
return (v > 0) ? v.compareTo(MAX_INT) <= 0 : v.compareTo(MIN_INT) >= 0;
}

private boolean canBeTrunkedToFloat(Double v) {
// TODO not really correct check. Small numbers with high precision will be trunked while they
// shouldn't be

return (v > 0) ? v.compareTo(MAX_FLOAT) <= 0 : v.compareTo(MIN_FLOAT) >= 0;
}

/** OBJECT OR MAP. CHECK THE TYPE ATTRIBUTE TO KNOW IT. */
private Object getValueAsObjectOrMapV0(
ODocument iRecord,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,37 +387,6 @@ && new Double(new Double(dou).floatValue()).doubleValue() == dou) {
return OType.DOUBLE;
}

/**
* Parses the field type char returning the closer type. Default is STRING. b=binary if
* iValue.length() >= 4 b=byte if iValue.length() <= 3 s=short, l=long f=float d=double a=date
* t=datetime
*
* @param iValue Value to parse
* @param iCharType Char value indicating the type
* @return The closest type recognized
*/
public static OType getType(final String iValue, final char iCharType) {
if (iCharType == 'f') return OType.FLOAT;
else if (iCharType == 'c') return OType.DECIMAL;
else if (iCharType == 'l') return OType.LONG;
else if (iCharType == 'd') return OType.DOUBLE;
else if (iCharType == 'b') {
if (iValue.length() >= 1 && iValue.length() <= 3) return OType.BYTE;
else return OType.BINARY;
} else if (iCharType == 'a') return OType.DATE;
else if (iCharType == 't') return OType.DATETIME;
else if (iCharType == 's') return OType.SHORT;
else if (iCharType == 'e') return OType.EMBEDDEDSET;
else if (iCharType == 'g') return OType.LINKBAG;
else if (iCharType == 'z') return OType.LINKLIST;
else if (iCharType == 'm') return OType.LINKMAP;
else if (iCharType == 'x') return OType.LINK;
else if (iCharType == 'n') return OType.LINKSET;
else if (iCharType == 'u') return OType.CUSTOM;

return OType.STRING;
}

/**
* Parses a string returning the value with the closer type. Numbers by default are INTEGER if
* haven't decimal separator, otherwise FLOAT. To treat all the number types numbers are postponed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

import com.orientechnologies.orient.core.command.OCommandContext;
import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.metadata.schema.OType;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.record.impl.ODocumentHelper;
import com.orientechnologies.orient.core.serialization.serializer.record.string.OFieldTypesString;
import com.orientechnologies.orient.core.sql.executor.OResult;
import com.orientechnologies.orient.core.sql.executor.OResultInternal;
import java.util.ArrayList;
Expand Down Expand Up @@ -83,14 +85,34 @@ public ODocument toDocument(OIdentifiable source, OCommandContext ctx) {

private ODocument toDocument(OResult source, OCommandContext ctx, String className) {
ODocument retDoc = new ODocument(className);
Map<String, Character> types = null;
for (OJsonItem item : items) {
String name = item.getLeftValue();
if (name == null
|| ODocumentHelper.getReservedAttributes().contains(name.toLowerCase(Locale.ENGLISH))) {
if (name.equals(OFieldTypesString.ATTRIBUTE_FIELD_TYPES)) {
Object value = item.right.execute(source, ctx);
types = OFieldTypesString.loadFieldTypes(value.toString());
for (Map.Entry<String, Character> entry : types.entrySet()) {
OType t = OFieldTypesString.getOTypeFromChar(entry.getValue());
retDoc.setFieldType(entry.getKey(), t);
}
}
continue;
}
Object value = item.right.execute(source, ctx);
retDoc.field(name, value);
Character charType;
if (types != null) {
charType = types.get(name);
} else {
charType = null;
}
if (charType != null) {
OType t = OFieldTypesString.getOTypeFromChar(charType);
retDoc.setProperty(name, value, t);
} else {
retDoc.setProperty(name, value);
}
}
return retDoc;
}
Expand Down

0 comments on commit a69005a

Please sign in to comment.