lkm commented on code in PR #15926:
URL: https://github.com/apache/druid/pull/15926#discussion_r1495325002
##########
processing/src/main/java/org/apache/druid/query/expression/NestedDataExpressions.java:
##########
@@ -99,6 +100,117 @@ public ExpressionType getOutputType(InputBindingInspector
inspector)
}
}
+ public static class JsonMergeExprMacro implements ExprMacroTable.ExprMacro
+ {
+ public static final String NAME = "json_merge";
+
+ private final ObjectMapper jsonMapper;
+
+ @Inject
+ public JsonMergeExprMacro(
+ @Json ObjectMapper jsonMapper
+ )
+ {
+ this.jsonMapper = jsonMapper;
+ }
+
+ @Override
+ public String name()
+ {
+ return NAME;
+ }
+
+ @Override
+ public Expr apply(List<Expr> args)
+ {
+ if (args.size() < 2) {
+ throw validationFailed("must have at least two arguments");
+ }
+
+ final class ParseJsonExpr extends
ExprMacroTable.BaseScalarMacroFunctionExpr
+ {
+ public ParseJsonExpr(List<Expr> args)
+ {
+ super(JsonMergeExprMacro.this, args);
+ }
+
+ @Override
+ public ExprEval eval(ObjectBinding bindings)
+ {
+ ExprEval arg = args.get(0).eval(bindings);
+ Object obj;
+
+ if (arg.value() == null) {
+ throw JsonMergeExprMacro.this.validationFailed(
+ "invalid input expected %s but got %s instead",
+ ExpressionType.STRING,
+ arg.type()
+ );
+ }
+
+ try {
+ obj = jsonMapper.readValue(getArgAsJson(arg), Object.class);
+ }
+ catch (JsonProcessingException e) {
+ throw JsonMergeExprMacro.this.processingFailed(e, "bad string
input [%s]", arg.asString());
+ }
+
+ ObjectReader updater = jsonMapper.readerForUpdating(obj);
+
+ for (int i = 1; i < args.size(); i++) {
+ ExprEval argSub = args.get(i).eval(bindings);
+
+ try {
+ String str = getArgAsJson(argSub);
+ if (str != null) {
+ obj = updater.readValue(str);
+ }
+ }
+ catch (JsonProcessingException e) {
+ throw JsonMergeExprMacro.this.processingFailed(e, "bad string
input [%s]", argSub.asString());
+ }
+ }
+
+ return ExprEval.ofComplex(ExpressionType.NESTED_DATA, obj);
+ }
+
+ @Nullable
+ @Override
+ public ExpressionType getOutputType(InputBindingInspector inspector)
+ {
+ return ExpressionType.NESTED_DATA;
+ }
+
+ private String getArgAsJson(ExprEval arg)
+ {
+ if (arg.value() == null) {
+ return null;
+ }
+
+ if (arg.type().is(ExprType.STRING)) {
+ return arg.asString();
+ }
+
+ if (arg.type().is(ExprType.COMPLEX)) {
+ try {
+ return jsonMapper.writeValueAsString(unwrap(arg));
+ }
+ catch (JsonProcessingException e) {
+ throw JsonMergeExprMacro.this.processingFailed(e, "bad complex
input [%s]", arg.asString());
+ }
+ }
Review Comment:
There isn't a way for the second parameter, because I'm using the Jackson
updater, but for the first there is. However, that leads to the first variable
being used again somehow on the second runs, that's the reason for the test
case `testJsonMergeOverflow()`. I'm not sure why this is happening but
essentially for the second run you get
`{"blah":"blahblah","blah2":"blahblah2"}`.
Happy to take any pointers here. I suspect I would need to copy the object
in memory to avoid the reference in which case I'm not sure how much of an
optimisation it really would be.
--
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]