compatible_shim.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. // Copyright 2020 PingCAP, Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. package errors
  14. import (
  15. "encoding/json"
  16. "strconv"
  17. "strings"
  18. )
  19. // class2RFCCode is used for compatible with old version of TiDB. When
  20. // marshal Error to json, old version of TiDB contain a 'class' field
  21. // which is represented for error class. In order to parse and convert
  22. // json to errors.Error, using this map to convert error class to RFC
  23. // error code text. here is reference:
  24. // https://github.com/pingcap/parser/blob/release-3.0/terror/terror.go#L58
  25. var class2RFCCode = map[int]string{
  26. 1: "autoid",
  27. 2: "ddl",
  28. 3: "domain",
  29. 4: "evaluator",
  30. 5: "executor",
  31. 6: "expression",
  32. 7: "admin",
  33. 8: "kv",
  34. 9: "meta",
  35. 10: "planner",
  36. 11: "parser",
  37. 12: "perfschema",
  38. 13: "privilege",
  39. 14: "schema",
  40. 15: "server",
  41. 16: "struct",
  42. 17: "variable",
  43. 18: "xeval",
  44. 19: "table",
  45. 20: "types",
  46. 21: "global",
  47. 22: "mocktikv",
  48. 23: "json",
  49. 24: "tikv",
  50. 25: "session",
  51. 26: "plugin",
  52. 27: "util",
  53. }
  54. var rfcCode2class map[string]int
  55. func init() {
  56. rfcCode2class = make(map[string]int)
  57. for k, v := range class2RFCCode {
  58. rfcCode2class[v] = k
  59. }
  60. }
  61. // MarshalJSON implements json.Marshaler interface.
  62. // aware that this function cannot save a 'registered' status,
  63. // since we cannot access the registry when unmarshaling,
  64. // and the original global registry would be removed here.
  65. // This function is reserved for compatibility.
  66. func (e *Error) MarshalJSON() ([]byte, error) {
  67. ec := strings.Split(string(e.codeText), ":")[0]
  68. return json.Marshal(&jsonError{
  69. Class: rfcCode2class[ec],
  70. Code: int(e.code),
  71. Msg: e.GetMsg(),
  72. RFCCode: string(e.codeText),
  73. })
  74. }
  75. // UnmarshalJSON implements json.Unmarshaler interface.
  76. // aware that this function cannot create a 'registered' error,
  77. // since we cannot access the registry in this context,
  78. // and the original global registry is removed.
  79. // This function is reserved for compatibility.
  80. func (e *Error) UnmarshalJSON(data []byte) error {
  81. tErr := &jsonError{}
  82. if err := json.Unmarshal(data, &tErr); err != nil {
  83. return Trace(err)
  84. }
  85. e.codeText = ErrCodeText(tErr.RFCCode)
  86. if tErr.RFCCode == "" && tErr.Class > 0 {
  87. e.codeText = ErrCodeText(class2RFCCode[tErr.Class] + ":" + strconv.Itoa(tErr.Code))
  88. }
  89. e.code = ErrCode(tErr.Code)
  90. e.message = tErr.Msg
  91. return nil
  92. }