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

Julian Hyde commented on CALCITE-7850:
--------------------------------------

It would be nice if RexSimplify made this simplification, but it’s not a bug 
that it doesn’t. I would only accept a fix that improves the general case (e.g. 
not just arrays, not just equals) and doesn’t have a quadratic running time (as 
a simplistic fix for this case would). 

> RexSimplify does not simplify "a = CAST(ARRAY[...]) AND a = CAST(ARRAY[...])" 
> to FALSE when the arrays differ
> -------------------------------------------------------------------------------------------------------------
>
>                 Key: CALCITE-7850
>                 URL: https://issues.apache.org/jira/browse/CALCITE-7850
>             Project: Calcite
>          Issue Type: Improvement
>          Components: core
>    Affects Versions: 1.42.0
>            Reporter: Vladimir Sitnikov
>            Priority: Major
>
> A filter on a {{VARCHAR ARRAY}} column that compares the column with two 
> different array constructors is not simplified to {{FALSE}}:
> {code:sql}
> select *
> from (values (cast(array['a', 'b'] as varchar array))) as t(u)
> where u = array['/flink.jpg', '/flink_1.jpg']
>   and u = array['/f.jpg', '/f_1.jpg']
> {code}
> After {{CoreRules.FILTER_REDUCE_EXPRESSIONS}} the plan keeps both conjuncts:
> {noformat}
> LogicalProject(U=[$0])
>   LogicalFilter(condition=[AND(=($0, CAST(ARRAY('/flink.jpg  ', 
> '/flink_1.jpg')):VARCHAR NOT NULL ARRAY NOT NULL), =($0, CAST(ARRAY('/f.jpg  
> ', '/f_1.jpg')):VARCHAR NOT NULL ARRAY NOT NULL))])
>     LogicalProject(U=[CAST(ARRAY('a', 'b')):VARCHAR NOT NULL ARRAY NOT NULL])
>       LogicalValues(tuples=[[{ 0 }]])
> {noformat}
> Each array constructor is cast to the column type, {{VARCHAR NOT NULL ARRAY 
> NOT NULL}}. The trailing spaces come from the {{CHAR(12)}} and {{CHAR(8)}} 
> element types of the constructors; the reproducer below uses unpadded 
> literals and fails the same way. This is the shape from FLINK-32188, which 
> CALCITE-5733 was filed for (see [this 
> comment|https://issues.apache.org/jira/browse/CALCITE-5733?focusedCommentId=17727467#comment-17727467]).
> When the array constructor already has the column type, no cast is added and 
> the filter is simplified: for an {{INTEGER ARRAY}} column, {{where u = 
> array[1,2] and u = array[2,3]}} becomes {{LogicalValues(tuples=[[]])}}, and 
> {{RexProgramTest.testSimplifyArrayEquality}} covers {{a = ARRAY[1,2] AND a = 
> ARRAY[2,3]}} since CALCITE-5733.
> *Expected:* the SQL above plans to {{LogicalValues(tuples=[[]])}}, and 
> {{RexSimplify}} in unknown-as-false mode simplifies the cast condition in the 
> test below to {{false}}, as it does for the uncast {{VARCHAR ARRAY}} 
> constructors in the same test.
> Add this test to {{RexProgramTest}}; it uses that class's helpers. On 
> 843f468405 (1.43.0-SNAPSHOT) the first assertion passes and the second fails:
> {code:java}
> @Test void testSimplifyCastArrayEquality() {
>   final RelDataType varcharArray = tArray(tVarchar());
>   final RexNode u = input(varcharArray, 0);
>   // Control: constructors of the column type, no cast
>   final RexNode b1 =
>       rexBuilder.makeCall(varcharArray, 
> SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR,
>           ImmutableList.of(literal("/flink.jpg"), literal("/flink_1.jpg")));
>   final RexNode b2 =
>       rexBuilder.makeCall(varcharArray, 
> SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR,
>           ImmutableList.of(literal("/f.jpg"), literal("/f_1.jpg")));
>   checkSimplifyFilter(and(eq(u, b1), eq(u, b2)), "false");
>   // Fails: constructors cast to the column type
>   final RexNode a1 =
>       rexBuilder.makeCast(varcharArray,
>           rexBuilder.makeCall(SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR,
>               literal("/flink.jpg"), literal("/flink_1.jpg")));
>   final RexNode a2 =
>       rexBuilder.makeCast(varcharArray,
>           rexBuilder.makeCall(SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR,
>               literal("/f.jpg"), literal("/f_1.jpg")));
>   checkSimplifyFilter(and(eq(u, a1), eq(u, a2)), "false");
> }
> {code}
> {noformat}
> java.lang.AssertionError: simplify(unknown as FALSE): AND(=($0, 
> CAST(ARRAY('/flink.jpg', '/flink_1.jpg')):VARCHAR NOT NULL ARRAY NOT NULL), 
> =($0, CAST(ARRAY('/f.jpg', '/f_1.jpg')):VARCHAR NOT NULL ARRAY NOT NULL))
> Expected: with toString() is "false"
>      but: toString() was "AND(=($0, CAST(ARRAY('/flink.jpg', 
> '/flink_1.jpg')):VARCHAR NOT NULL ARRAY NOT NULL), =($0, CAST(ARRAY('/f.jpg', 
> '/f_1.jpg')):VARCHAR NOT NULL ARRAY NOT NULL))"
> {noformat}
> *Possible cause (a guess; the report above stands without it):* 
> {{RexSimplify.isConstant}}, added in CALCITE-5733, accepts a literal or an 
> {{ARRAY}} or {{MULTISET}} constructor of constants, and rejects a {{CAST}} 
> around one. Accepting the cast is not enough by itself: a cast can map 
> different constructors to equal values, for example {{CAST(ARRAY[1.1] AS 
> INTEGER ARRAY)}} and {{CAST(ARRAY[1.2] AS INTEGER ARRAY)}} both evaluate to 
> {{ARRAY[1]}}, so the two constants have to be compared after the cast, not as 
> expressions.



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

Reply via email to