-
Notifications
You must be signed in to change notification settings - Fork 618
[client-v2] Adding JSON support with predefined paths #2531
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
Changes from all commits
771441e
25d8c60
df769cc
97c5517
37ec609
6ace772
74bb966
70a905a
1bc5b01
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,11 +37,9 @@ | |
|
|
||
| import java.io.Serializable; | ||
| import java.lang.reflect.Array; | ||
| import java.math.BigInteger; | ||
| import java.time.OffsetDateTime; | ||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
| import java.util.Collection; | ||
| import java.util.Collections; | ||
| import java.util.Comparator; | ||
| import java.util.HashMap; | ||
|
|
@@ -51,6 +49,7 @@ | |
| import java.util.Objects; | ||
| import java.util.Set; | ||
| import java.util.TimeZone; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| /** | ||
| * This class represents a column defined in database. | ||
|
|
@@ -72,6 +71,7 @@ public final class ClickHouseColumn implements Serializable { | |
| private static final String KEYWORD_MAP = ClickHouseDataType.Map.name(); | ||
| private static final String KEYWORD_NESTED = ClickHouseDataType.Nested.name(); | ||
| private static final String KEYWORD_VARIANT = ClickHouseDataType.Variant.name(); | ||
| private static final String KEYWORD_JSON = ClickHouseDataType.JSON.name(); | ||
|
|
||
| private int columnCount; | ||
| private int columnIndex; | ||
|
|
@@ -90,6 +90,7 @@ public final class ClickHouseColumn implements Serializable { | |
| private List<ClickHouseColumn> nested; | ||
| private List<String> parameters; | ||
| private ClickHouseEnum enumConstants; | ||
| private Map<String, ClickHouseColumn> jsonPredefinedPaths; | ||
|
|
||
| private int arrayLevel; | ||
| private ClickHouseColumn arrayBaseColumn; | ||
|
|
@@ -504,6 +505,23 @@ protected static int readColumn(String args, int startIndex, int len, String nam | |
| } | ||
| } | ||
| } | ||
| } else if (args.startsWith(KEYWORD_JSON, i)) { | ||
| int index = args.indexOf('(', i + KEYWORD_JSON.length()); | ||
| if (index > i) { | ||
| i = ClickHouseUtils.skipBrackets(args, index, len, '('); | ||
| String originalTypeName = args.substring(startIndex, i); | ||
| List<ClickHouseColumn> nestedColumns = new ArrayList<>(); | ||
|
|
||
| List<String> parameters = new ArrayList<>(); | ||
| parseJSONColumn(args.substring(index + 1, i - 1), nestedColumns, parameters); | ||
| nestedColumns.sort(Comparator.comparing(o -> o.getDataType().name())); | ||
| column = new ClickHouseColumn(ClickHouseDataType.JSON, name, originalTypeName, nullable, lowCardinality, | ||
| parameters, nestedColumns); | ||
| column.jsonPredefinedPaths = nestedColumns.stream().collect(Collectors.toMap(ClickHouseColumn::getColumnName, | ||
| c -> c)); | ||
| fixedLength = false; | ||
| estimatedLength++; | ||
| } | ||
| } | ||
|
|
||
| if (column == null) { | ||
|
|
@@ -658,6 +676,54 @@ public static List<ClickHouseColumn> parse(String args) { | |
| return Collections.unmodifiableList(c); | ||
| } | ||
|
|
||
| public static final String JSON_MAX_PATHS_PARAM = "max_dynamic_paths"; | ||
| public static final String JSON_MAX_DYN_TYPES_PARAM = "max_dynamic_types"; | ||
| public static final String JSON_SKIP_MARKER = "SKIP"; | ||
|
|
||
| public static void parseJSONColumn(String args, List<ClickHouseColumn> nestedColumns, List<String> parameters) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't it deserve a dedicated set of tests?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This part is tested via integration tests. I think no need to duplicate same in unit. |
||
| if (args == null || args.isEmpty()) { | ||
| return; | ||
| } | ||
|
|
||
| String name = null; | ||
| ClickHouseColumn column = null; | ||
| StringBuilder builder = new StringBuilder(); | ||
| int i =0; | ||
chernser marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| int len = args.length(); | ||
| while (i < len) { | ||
| char ch = args.charAt(i); | ||
| if (Character.isWhitespace(ch)) { | ||
| i++; | ||
| continue; | ||
| } | ||
|
|
||
| if (name == null) { // column name | ||
| i = ClickHouseUtils.readNameOrQuotedString(args, i, len, builder) - 1; | ||
| name = builder.toString(); | ||
| if (name.startsWith(JSON_SKIP_MARKER)) { | ||
| name = null; // skip parameters | ||
| i = ClickHouseUtils.skipContentsUntil(args, i, len, ',') - 1; | ||
| } else if ( name.startsWith(JSON_MAX_PATHS_PARAM) || name.startsWith(JSON_MAX_DYN_TYPES_PARAM)) { | ||
chernser marked this conversation as resolved.
Show resolved
Hide resolved
chernser marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| parameters.add(name); | ||
| name = null; | ||
| i = ClickHouseUtils.skipContentsUntil(args, i, len, ',') - 1; | ||
chernser marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| builder.setLength(0); | ||
| } else if (column == null) { // now type | ||
| LinkedList<ClickHouseColumn> colList = new LinkedList<>(); | ||
| i = readColumn(args, i, len, name, colList) - 1; | ||
| column = colList.getFirst(); | ||
| nestedColumns.add(column); | ||
| } else { // prepare for next column | ||
| i = ClickHouseUtils.skipContentsUntil(args, i, len, ',') - 1; | ||
| name = null; | ||
| column = null; | ||
| } | ||
|
|
||
| i++; | ||
| } | ||
| } | ||
|
|
||
| public ClickHouseColumn(ClickHouseDataType dataType, String columnName, String originalTypeName, boolean nullable, | ||
| boolean lowCardinality, List<String> parameters, List<ClickHouseColumn> nestedColumns) { | ||
| this(dataType, columnName, originalTypeName, nullable, lowCardinality, parameters, nestedColumns, ClickHouseEnum.EMPTY); | ||
|
|
@@ -954,6 +1020,10 @@ public ClickHouseAggregateFunction getAggregateFunction() { | |
| return aggFuncType; | ||
| } | ||
|
|
||
| public Map<String, ClickHouseColumn> getJsonPredefinedPaths() { | ||
| return jsonPredefinedPaths; | ||
| } | ||
|
|
||
| public ClickHouseArraySequence newArrayValue(ClickHouseDataConfig config) { | ||
| int level = arrayLevel; | ||
| ClickHouseArraySequence value; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The line continuation should be properly aligned. The lambda parameter
c -> con the next line should be aligned with the method call parameters.