clintropolis commented on code in PR #12968:
URL: https://github.com/apache/druid/pull/12968#discussion_r955528783
##########
sql/src/main/java/org/apache/druid/sql/calcite/expression/builtin/NestedDataOperatorConversions.java:
##########
@@ -395,24 +465,182 @@ public DruidExpression toDruidExpression(
)
);
}
- return DruidExpression.ofExpression(ColumnType.STRING, builder,
druidExpressions);
+ return DruidExpression.ofExpression(druidType, builder,
druidExpressions);
+ }
+
+ static SqlFunction buildFunction(String functionName, SqlTypeName typeName)
+ {
+ return OperatorConversions.operatorBuilder(functionName)
+ .operandTypeChecker(
+ OperandTypes.sequence(
+ "(expr,path)",
+ OperandTypes.family(SqlTypeFamily.ANY),
+
OperandTypes.family(SqlTypeFamily.STRING)
+ )
+ )
+ .returnTypeInference(
+ ReturnTypes.cascade(
+ opBinding ->
opBinding.getTypeFactory().createSqlType(typeName),
+ SqlTypeTransforms.FORCE_NULLABLE
+ )
+ )
+
.functionCategory(SqlFunctionCategory.USER_DEFINED_FUNCTION)
+ .build();
+ }
+ }
+
+ public static class JsonValueBigintOperatorConversion extends
JsonValueReturningTypeOperatorConversion
+ {
+ private static final SqlFunction FUNCTION =
buildFunction("JSON_VALUE_BIGINT", SqlTypeName.BIGINT);
+
+ public JsonValueBigintOperatorConversion()
+ {
+ super(FUNCTION, ColumnType.LONG);
+ }
+ }
+
+ public static class JsonValueDoubleOperatorConversion extends
JsonValueReturningTypeOperatorConversion
+ {
+ private static final SqlFunction FUNCTION =
buildFunction("JSON_VALUE_DOUBLE", SqlTypeName.DOUBLE);
+
+ public JsonValueDoubleOperatorConversion()
+ {
+ super(FUNCTION, ColumnType.DOUBLE);
}
}
- // calcite converts JSON_VALUE to JSON_VALUE_ANY so we have to wire that up
too...
- public static class JsonValueAnyOperatorConversion extends
AliasedOperatorConversion
+ public static class JsonValueStringOperatorConversion extends
JsonValueReturningTypeOperatorConversion
{
- private static final String FUNCTION_NAME =
StringUtils.toUpperCase("json_value_any");
+ private static final SqlFunction FUNCTION =
buildFunction("JSON_VALUE_VARCHAR", SqlTypeName.VARCHAR);
- public JsonValueAnyOperatorConversion()
+ public JsonValueStringOperatorConversion()
{
- super(new JsonValueOperatorConversion(), FUNCTION_NAME);
+ super(FUNCTION, ColumnType.STRING);
}
+ }
+
+ /**
+ * Calcites {@link org.apache.calcite.sql2rel.StandardConvertletTable}
translates JSON_VALUE
+ */
+ public static class JsonValueAnyOperatorConversion implements
SqlOperatorConversion
+ {
+ private static final SqlFunction FUNCTION =
+ OperatorConversions.operatorBuilder("JSON_VALUE_ANY")
+ .operandTypeChecker(
+ OperandTypes.or(
+ OperandTypes.sequence(
+ "(expr,path)",
+ OperandTypes.family(SqlTypeFamily.ANY),
+
OperandTypes.family(SqlTypeFamily.STRING)
+ ),
+ OperandTypes.family(
+ SqlTypeFamily.ANY,
+ SqlTypeFamily.CHARACTER,
+ SqlTypeFamily.ANY,
+ SqlTypeFamily.ANY,
+ SqlTypeFamily.ANY,
+ SqlTypeFamily.ANY,
+ SqlTypeFamily.ANY
+ )
+ )
+ )
+ .operandTypeInference((callBinding, returnType,
operandTypes) -> {
+ RelDataTypeFactory typeFactory =
callBinding.getTypeFactory();
+ if (operandTypes.length > 5) {
+ operandTypes[3] =
typeFactory.createSqlType(SqlTypeName.ANY);
+ operandTypes[5] =
typeFactory.createSqlType(SqlTypeName.ANY);
+ }
+ })
+ .returnTypeInference(
+ ReturnTypes.cascade(
+ opBinding ->
opBinding.getTypeFactory().createTypeWithNullability(
+ // STRING is the closest thing we have
to an ANY type
+ // however, this should really be using
SqlTypeName.ANY.. someday
+
opBinding.getTypeFactory().createSqlType(SqlTypeName.VARCHAR),
+ true
+ ),
+ SqlTypeTransforms.FORCE_NULLABLE
+ )
+ )
+ .functionCategory(SqlFunctionCategory.SYSTEM)
+ .build();
@Override
public SqlOperator calciteOperator()
{
- return SqlStdOperatorTable.JSON_VALUE_ANY;
+ return FUNCTION;
+ }
+
+ @Nullable
+ @Override
+ public DruidExpression toDruidExpression(
+ PlannerContext plannerContext,
+ RowSignature rowSignature,
+ RexNode rexNode
+ )
+ {
+ final RexCall call = (RexCall) rexNode;
+
+ // calcite parser can allow for a bunch of junk in here that we don't
care about right now, so the call looks
Review Comment:
I couldn't find an easy way, but it is certainly possible that I didn't try
everything yet. The reason being afaict the parser creates default values for
all of these arguments when it is making the sql function call, and so it
always first appears with 6 or 7 arguments and i wasn't too sure how to
distinguish them explicitly being there from them being generated.
I can play around a bit to see if I can detect it, or at least maybe expect
the default values that are generated and throw an error if they do not exist
--
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]