korlov42 commented on code in PR #2047:
URL: https://github.com/apache/ignite-3/pull/2047#discussion_r1221592072
##########
modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteTypeCoercion.java:
##########
@@ -392,13 +587,135 @@ private static SqlNode castTo(SqlNode node, RelDataType
type) {
}
/**
- * A context in which {@link IgniteTypeCoercion#getWiderTypeFor(List,
boolean)} is being called.
+ * Validates dynamic parameters in binary comparison operation.
+ */
+ private void validateBinaryComparisonCoercion(SqlCallBinding binding,
RelDataType leftType,
+ RelDataType rightType, IgniteSqlValidator validator) {
+
+ SqlNode lhs = binding.operand(0);
+ SqlNode rhs = binding.operand(1);
+
+ if (lhs instanceof SqlDynamicParam) {
+ validateOperand((SqlDynamicParam) lhs, rightType,
binding.getOperator(), validator);
+ }
+
+ if (rhs instanceof SqlDynamicParam) {
+ validateOperand((SqlDynamicParam) rhs, leftType,
binding.getOperator(), validator);
+ }
+ }
+
+ /**
+ * Validates dynamic parameter as a call operand or in assignment.
+ */
+ private void validateCoerceOperand(SqlCall call, SqlDynamicParam
dynamicParam, RelDataType targetType,
+ ContextType ctxType, IgniteSqlValidator validator) {
+
+ if (ctxType == ContextType.INSERT || ctxType == ContextType.MODIFY) {
+ // Treat ROW operator as the same way as assignment.
+ validateAssignment(dynamicParam, targetType, ctxType, validator);
+ } else if (ctxType == ContextType.IN) {
+ // Use IN operation instead of ROW operator for errors.
+ validateOperand(dynamicParam, targetType, SqlStdOperatorTable.IN,
validator);
+ } else {
+ validateOperand(dynamicParam, targetType, call.getOperator(),
validator);
+ }
+ }
+
+ /**
+ * Validates dynamic parameter type in SET operation or in assignment
(UPDATE/INSERT).
+ */
+ private boolean validateCoerceColumn(SqlDynamicParam dynamicParam,
RelDataType targetType,
+ IgniteSqlValidator validator) {
+
+ ContextType ctxType = contextStack.get().currentContext();
+
+ // This method throws and error in case of INSERT/UPDATE, as
+ // We throw error here because SqlValidatorImpl::checkTypeAssignment
ignores Dynamic Params when type coercion fails.
+ //
+ // For set operations we rely on the fact SetopOperandTypeChecker is
going to raise appropriate exception,
+ // because CalciteResource::columnTypeMismatchInSetop requires a name
of a set operation
+ // (and we have no such information here).
+
+ if (ctxType == ContextType.SET_OP) {
+ RelDataType paramType =
validator.getDynamicParamType(dynamicParam);
+ return
IgniteTypeSystem.INSTANCE.typeFamiliesAreCompatible(typeFactory, targetType,
paramType);
+ } else {
+ validateAssignment(dynamicParam, targetType, ctxType, validator);
+ return true;
+ }
+ }
+
+ private void validateAssignment(SqlDynamicParam node, RelDataType
targetType, ContextType ctxType, IgniteSqlValidator validator) {
+
+ RelDataType paramType = validator.getDynamicParamType(node);
+ boolean compatible =
IgniteTypeSystem.INSTANCE.typeFamiliesAreCompatible(typeFactory, targetType,
paramType);
+ if (compatible) {
+ return;
+ }
+
+ if (ctxType == ContextType.INSERT) {
+ // Throw the same error if T1 and T2 are not compatible:
+ //
+ // 1) INSERT INTO (t1_col) VALUES (<T2>)
+ // 2) INSERT in not match arm of MERGE statement.
+ //
+ var ex =
RESOURCE.incompatibleValueType(SqlStdOperatorTable.VALUES.getName());
+ throw SqlUtil.newContextException(node.getParserPosition(), ex);
+ } else {
+ // Error for UPDATE in both standalone UPDATE and WHEN MATCHED arm
of MERGE statements.
+
+ String paramTypeString = paramType.toString();
+ String targetTypeString = targetType.toString();
+
+ var ex =
IgniteResource.INSTANCE.assignmentRequiresExplicitCast(paramTypeString,
targetTypeString);
+ throw SqlUtil.newContextException(node.getParserPosition(), ex);
+ }
+ }
+
+ private void validateOperand(SqlDynamicParam node, RelDataType targetType,
SqlOperator operator, IgniteSqlValidator validator) {
Review Comment:
I'm not sure if type coercion should do any validation
--
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]