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]

Reply via email to