Repository: pingcap/tidb (Go)

Issue:
The coercibility of the cast function is wrong
## Bug Report

Please answer these questions before submitting your issue. Thanks!

### 1. Minimal reproduce step (Required)

<!-- a step by step guide for reproducing the bug. -->
```
mysql> select Coercibility(cast("a" as char(12)));
+-------------------------------------+
| Coercibility(cast("a" as char(12))) |
+-------------------------------------+
|                                   4 |
+-------------------------------------+
1 row in set (0.00 sec)
```


### 2. What did you expect to see? (Required)
2
### 3. What did you see instead (Required)
4
### 4. What is your TiDB version? (Required)
master
<!-- Paste the output of SELECT tidb_version() -->




Discussion:
## Please edit this comment or add a new comment to complete the following information

### Not a bug

1. Remove the 'type/bug' label
2. Add notes to indicate why it is not a bug

### Duplicate bug

1. Add the 'type/duplicate' label
2. Add the link to the original bug

### Bug

Note: Make Sure that 'component', and 'severity' labels are added
Example for how to fill out the template: https://github.com/pingcap/tidb/issues/20100

#### 1. Root Cause Analysis (RCA) (optional) 
<!-- Write down the reason why this bug occurs -->

#### 2. Symptom (optional)

<!-- What will the user see when this bug occurs. The error message may be in the terminal, log or monitoring -->

#### 3. All Trigger Conditions (optional)

<!-- All the user scenarios that may trigger this bug -->

#### 4. Workaround (optional)

#### 5. Affected versions

<!--
In the format of [start_version:end_version], multiple version ranges are
accepted. If the bug only affects the unreleased version, please input:
"unreleased". For example:

Notes:
  1. Do not use any white spaces in '[]'.
  2. The range in '[]' is a closed interval
  3. The version format is `v$Major.$Minor.$Patch`, the $Majoy and $Minor
     number in a version range should be the same. [v3.0.1:v3.1.2] is
     invalid because the $Minor number of the version range is different.

Example 1: [v3.0.1:v3.0.5], [v4.0.1:v4.0.5]
Example 2: unreleased
-->

#### 6. Fixed versions

<!--
The first released version that contains this fix in each minor version. If the bug's affected version has been released, the fixed version should be a detailed version number; If the bug doesn't affect any released version, the fixed version can be "master";  

Example 1: v3.0.13, v4.0.5
Example 2: master
-->



Patch:
diff --git a/expression/collation.go b/expression/collation.go
index d8bae9f8c45c3..a7b1983a844d2 100644
--- a/expression/collation.go
+++ b/expression/collation.go
@@ -90,7 +90,7 @@ const (
 	CoercibilityExplicit Coercibility = 0
 	// CoercibilityNone is derived from the concatenation of two strings with different collations.
 	CoercibilityNone Coercibility = 1
-	// CoercibilityImplicit is derived from a column or a stored routine parameter or local variable.
+	// CoercibilityImplicit is derived from a column or a stored routine parameter or local variable or cast() function.
 	CoercibilityImplicit Coercibility = 2
 	// CoercibilitySysconst is derived from a “system constant” (the string returned by functions such as USER() or VERSION()).
 	CoercibilitySysconst Coercibility = 3
diff --git a/planner/core/expression_rewriter.go b/planner/core/expression_rewriter.go
index d61eb5344e985..8f17360b3677d 100644
--- a/planner/core/expression_rewriter.go
+++ b/planner/core/expression_rewriter.go
@@ -1056,6 +1056,10 @@ func (er *expressionRewriter) Leave(originInNode ast.Node) (retNode ast.Node, ok
 			return retNode, false
 		}
 
+		if v.Tp.EvalType() == types.ETString {
+			arg.SetCoercibility(expression.CoercibilityImplicit)
+		}
+
 		er.ctxStack[len(er.ctxStack)-1] = expression.BuildCastFunction(er.sctx, arg, v.Tp)
 		er.ctxNameStk[len(er.ctxNameStk)-1] = types.EmptyName
 	case *ast.PatternLikeExpr:


Test patch:
diff --git a/expression/integration_test.go b/expression/integration_test.go
index d479970160f03..c945106030568 100644
--- a/expression/integration_test.go
+++ b/expression/integration_test.go
@@ -8279,3 +8279,11 @@ func (s *testIntegrationSuite) TestIssue12205(c *C) {
 	tk.MustQuery("show warnings;").Check(
 		testkit.Rows("Warning 1292 Truncated incorrect time value: '18446744072635875000'"))
 }
+
+func (s *testIntegrationSuite2) TestCastCoer(c *C) {
+	tk := testkit.NewTestKit(c, s.store)
+
+	tk.MustQuery("select coercibility(binary('a'))").Check(testkit.Rows("2"))
+	tk.MustQuery("select coercibility(cast('a' as char(10)))").Check(testkit.Rows("2"))
+	tk.MustQuery("select coercibility(convert('abc', char(10)));").Check(testkit.Rows("2"))
+}