Open YangKeao opened 3 weeks ago
A workaround is to specify the collation explicitly in both DDL and DQL:
create table `t` (data json DEFAULT NULL, KEY idx((cast(json_extract(data, '$.test') as char(64)) collate utf8mb4_bin )));
explain select /*+ USE_INDEX(t, idx) */ * from t where cast(json_extract(data, '$.test') as char(64)) collate utf8mb4_bin = 'a';
It's because for the DDL, the column type is regarded as utf8mb4_0900_ai_ci
(according to the configuration of client), but the expression is recorded as a pure string.
When we are loading the schema, the expression is loaded as utf8mb4_bin
collation. Therefore, it cannot pass the following condition in collectGenerateColumn
:
if col != nil && col.GetType(ectx).PartialEqual(col.VirtualExpr.GetType(ectx), lp.SCtx().GetSessionVars().EnableUnsafeSubstitute) {
exprToColumn[col.VirtualExpr] = col
}
The column type doesn't partial equal the type of col.VirtualExpr
.
One possible fix is to re-build the expression with the user's session context, rather than using the expression in schema directly.
It would be easy to fix this situation, but IMO the best fix is to remove col.VirtualExpr
, and make it a function to generate an expression from the user's session context. Cache is also needed to make it faster.
Bug Report
Please answer these questions before submitting your issue. Thanks!
1. Minimal reproduce step (Required)
2. What did you expect to see? (Required)
3. What did you see instead (Required)
4. What is your TiDB version? (Required)