-
Notifications
You must be signed in to change notification settings - Fork 181
Support spath with dynamic fields #5058
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
2e50f6d
4a49d04
bca7443
e285fbf
54073d7
ef79687
29ee620
cd041e1
f43e504
f9c7583
5725f2d
aae572a
9ef0bda
8a618f6
9449233
600809e
d34616d
91a06f4
fec8f4b
e5cec4d
f7ea5dd
ced9c37
cacc0ae
dbb1ff4
55e15ec
eb9bd69
7204de1
b5b114d
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 |
|---|---|---|
|
|
@@ -75,6 +75,8 @@ | |
| */ | ||
| public class FieldResolutionVisitor extends AbstractNodeVisitor<Node, FieldResolutionContext> { | ||
|
|
||
| private static final String ALL_FIELDS = "*"; | ||
|
|
||
| /** | ||
| * Analyzes PPL query plan to determine required fields at each node. | ||
| * | ||
|
|
@@ -110,10 +112,10 @@ private void acceptAndVerifyNodeVisited(Node node, FieldResolutionContext contex | |
|
|
||
| @Override | ||
| public Node visitProject(Project node, FieldResolutionContext context) { | ||
| boolean isSelectAll = | ||
| node.getProjectList().stream().anyMatch(expr -> expr instanceof AllFields); | ||
| boolean isSingleSelectAll = | ||
| node.getProjectList().size() == 1 && node.getProjectList().get(0) instanceof AllFields; | ||
|
|
||
| if (isSelectAll) { | ||
| if (isSingleSelectAll) { | ||
| visitChildren(node, context); | ||
| } else { | ||
| Set<String> projectFields = new HashSet<>(); | ||
|
|
@@ -179,15 +181,14 @@ public Node visitSpath(SPath node, FieldResolutionContext context) { | |
| return visitEval(node.rewriteAsEval(), context); | ||
| } else { | ||
| // set requirements for spath command; | ||
| context.setResult(node, context.getCurrentRequirements()); | ||
| FieldResolutionResult requirements = context.getCurrentRequirements(); | ||
| if (requirements.hasWildcards()) { | ||
| context.setResult(node, requirements); | ||
| if (requirements.hasPartialWildcards()) { | ||
| throw new IllegalArgumentException( | ||
| "Spath command cannot extract arbitrary fields. Please project fields explicitly by" | ||
| + " fields command without wildcard or stats command."); | ||
| "Spath command cannot be used with partial wildcard such as `prefix*`."); | ||
| } | ||
|
|
||
| context.pushRequirements(context.getCurrentRequirements().or(Set.of(node.getInField()))); | ||
| context.pushRequirements(requirements.or(Set.of(node.getInField()))); | ||
| visitChildren(node, context); | ||
| context.popRequirements(); | ||
| return node; | ||
|
|
@@ -237,6 +238,8 @@ private Set<String> extractFieldsFromExpression(UnresolvedExpression expr) { | |
|
|
||
| if (expr instanceof Field field) { | ||
| fields.add(field.getField().toString()); | ||
| } else if (expr instanceof AllFields) { | ||
| fields.add(ALL_FIELDS); | ||
| } else if (expr instanceof QualifiedName name) { | ||
| fields.add(name.toString()); | ||
| } else if (expr instanceof Alias alias) { | ||
|
|
@@ -490,43 +493,56 @@ public Node visitStreamWindow(StreamWindow node, FieldResolutionContext context) | |
|
|
||
| @Override | ||
| public Node visitFillNull(FillNull node, FieldResolutionContext context) { | ||
| if (node.isAgainstAllFields()) { | ||
| throw new IllegalArgumentException("Fields need to be specified with fillnull command"); | ||
| } | ||
| Set<String> fields = new HashSet<>(); | ||
| node.getFields().forEach(field -> fields.addAll(extractFieldsFromExpression(field))); | ||
|
|
||
| context.pushRequirements(context.getCurrentRequirements().or(fields)); | ||
| visitChildren(node, context); | ||
| context.popRequirements(); | ||
| return node; | ||
| } | ||
|
|
||
| @Override | ||
| public Node visitAppendCol(AppendCol node, FieldResolutionContext context) { | ||
| visitChildren(node, context); | ||
| return node; | ||
| throw new IllegalArgumentException( | ||
| "AppendCol command cannot be used together with spath command"); | ||
|
Comment on lines
+510
to
+511
Collaborator
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 visitor is not generic and only for spath?
Collaborator
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. The error message is specific for |
||
| } | ||
|
|
||
| @Override | ||
| public Node visitAppend(Append node, FieldResolutionContext context) { | ||
| // dispatch requirements to subsearch and main | ||
| acceptAndVerifyNodeVisited(node.getSubSearch(), context); | ||
| visitChildren(node, context); | ||
| return node; | ||
| } | ||
|
|
||
| @Override | ||
| public Node visitMultisearch(Multisearch node, FieldResolutionContext context) { | ||
| visitChildren(node, context); | ||
| return node; | ||
| throw new IllegalArgumentException( | ||
| "Multisearch command cannot be used together with spath command"); | ||
| } | ||
|
|
||
| @Override | ||
| public Node visitLookup(Lookup node, FieldResolutionContext context) { | ||
| visitChildren(node, context); | ||
| return node; | ||
| throw new IllegalArgumentException("Lookup command cannot be used together with spath command"); | ||
| } | ||
|
|
||
| @Override | ||
| public Node visitValues(Values node, FieldResolutionContext context) { | ||
| visitChildren(node, context); | ||
| return node; | ||
| throw new IllegalArgumentException("Values command cannot be used together with spath command"); | ||
| } | ||
|
|
||
| @Override | ||
| public Node visitReplace(Replace node, FieldResolutionContext context) { | ||
| Set<String> fields = new HashSet<>(); | ||
| node.getFieldList().forEach(field -> fields.addAll(extractFieldsFromExpression(field))); | ||
|
|
||
| context.pushRequirements(context.getCurrentRequirements().or(fields)); | ||
| visitChildren(node, context); | ||
| context.popRequirements(); | ||
| return node; | ||
| } | ||
|
|
||
|
|
@@ -619,6 +635,10 @@ private Set<String> extractFieldsFromAggregation(UnresolvedExpression expr) { | |
| } | ||
| } | ||
| } | ||
| return fields; | ||
| return excludeAllFieldsWildcard(fields); | ||
| } | ||
|
|
||
| private Set<String> excludeAllFieldsWildcard(Set<String> fields) { | ||
| return fields.stream().filter(f -> !f.equals(ALL_FIELDS)).collect(Collectors.toSet()); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -63,6 +63,10 @@ public List<Field> getFields() { | |
| return getReplacementPairs().stream().map(Pair::getLeft).toList(); | ||
| } | ||
|
|
||
| public boolean isAgainstAllFields() { | ||
|
Collaborator
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. I'm not clear when we should call this? Any PPL command doesn't allow
Collaborator
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. When |
||
| return !replacementForAll.isEmpty() && getReplacementPairs().isEmpty(); | ||
| } | ||
|
|
||
| @Override | ||
| public FillNull attach(UnresolvedPlan child) { | ||
| this.child = child; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.