[ 
https://issues.apache.org/jira/browse/CALCITE-7627?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18111483#comment-18111483
 ] 

zzwqqq commented on CALCITE-7627:
---------------------------------

One way to do this would be to give EnumerableTableModifyRule a planning-time 
Rex policy:

{code:java}
interface AssignmentPolicy {
  RexNode apply(AssignmentContext context);
}

interface AssignmentContext {
  RexBuilder rexBuilder();
  RexNode source();
  RelDataType targetType();
  void addCheck(RexNode condition, String message);
}
{code}

The rule would call the policy for each assigned column. The returned 
expression would be written to the target column. Checks added through addCheck 
would become:

{code}
THROW_UNLESS(IS_NOT_FALSE(condition), message)
{code}

in the EnumerableCalc condition.

For example, the bounded character check in the default policy would look 
roughly like this:

{code:java}
RexNode length =
    rexBuilder.makeCall(
        SqlStdOperatorTable.CHAR_LENGTH, source);
RexNode fits =
    rexBuilder.makeCall(
        SqlStdOperatorTable.LESS_THAN_OR_EQUAL,
        length,
        rexBuilder.makeExactLiteral(
            BigDecimal.valueOf(targetType.getPrecision())));

context.addCheck(fits, "Value exceeds " + targetType);
return source;
{code}

Binary targets would use OCTET_LENGTH instead. For an exact numeric assignment, 
the default policy would return a cast to the target type when one is needed.

Applications that need different behavior could provide another policy. It 
could delegate to the default policy, then add its own checks or return a 
different value expression. If the behavior needs custom Java code, the policy 
could emit a RexCall to an implementable function.

The Rex expressions would be placed in EnumerableCalc and go through the 
existing Enumerable code-generation path. The policy itself would only be used 
while building the plan.

Would this be the kind of hook and code-generation integration you had in mind?

> Enumerable DML should reject assignments that may lose data
> -----------------------------------------------------------
>
>                 Key: CALCITE-7627
>                 URL: https://issues.apache.org/jira/browse/CALCITE-7627
>             Project: Calcite
>          Issue Type: Bug
>            Reporter: zzwqqq
>            Assignee: zzwqqq
>            Priority: Major
>              Labels: pull-request-available
>
> Enumerable DML currently accepts some assignments that may lose data.
> One example is assigning a longer string to a shorter VARCHAR column:
> {code:sql}
> CREATE TABLE dept (deptno INTEGER NOT NULL, name VARCHAR(10));
> INSERT INTO dept
> VALUES (30, 'Engineering');
> {code}
> The Enumerable/server path can insert the value now. With their default 
> settings, PostgreSQL, MySQL, and Oracle reject this case:
> https://onecompiler.com/postgresql/44sf3dz68
> https://onecompiler.com/mysql/44sf3efz4
> https://onecompiler.com/oracle/44sf3ewmh
> The assignment should produce a runtime error rather than truncating or 
> accepting the value.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to