github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/soliton/codec/codec.go (about) 1 // Copyright 2020 WHTCORPS INC, 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 14 package codec 15 16 import ( 17 "bytes" 18 "encoding/binary" 19 "fmt" 20 "hash" 21 "io" 22 "time" 23 "unsafe" 24 25 "github.com/whtcorpsinc/errors" 26 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 27 "github.com/whtcorpsinc/BerolinaSQL/terror" 28 "github.com/whtcorpsinc/milevadb/stochastikctx/stmtctx" 29 "github.com/whtcorpsinc/milevadb/types" 30 "github.com/whtcorpsinc/milevadb/types/json" 31 "github.com/whtcorpsinc/milevadb/soliton/chunk" 32 "github.com/whtcorpsinc/milevadb/soliton/defCauslate" 33 "github.com/whtcorpsinc/milevadb/soliton/replog" 34 ) 35 36 // First byte in the encoded value which specifies the encoding type. 37 const ( 38 NilFlag byte = 0 39 bytesFlag byte = 1 40 compactBytesFlag byte = 2 41 intFlag byte = 3 42 uintFlag byte = 4 43 floatFlag byte = 5 44 decimalFlag byte = 6 45 durationFlag byte = 7 46 varintFlag byte = 8 47 uvarintFlag byte = 9 48 jsonFlag byte = 10 49 maxFlag byte = 250 50 ) 51 52 const ( 53 sizeUint64 = unsafe.Sizeof(uint64(0)) 54 sizeFloat64 = unsafe.Sizeof(float64(0)) 55 ) 56 57 func preRealloc(b []byte, vals []types.Causet, comparable bool) []byte { 58 var size int 59 for i := range vals { 60 switch vals[i].HoTT() { 61 case types.HoTTInt64, types.HoTTUint64, types.HoTTMysqlEnum, types.HoTTMysqlSet, types.HoTTMysqlBit, types.HoTTBinaryLiteral: 62 size += sizeInt(comparable) 63 case types.HoTTString, types.HoTTBytes: 64 size += sizeBytes(vals[i].GetBytes(), comparable) 65 case types.HoTTMysqlTime, types.HoTTMysqlDuration, types.HoTTFloat32, types.HoTTFloat64: 66 size += 9 67 case types.HoTTNull, types.HoTTMinNotNull, types.HoTTMaxValue: 68 size += 1 69 case types.HoTTMysqlJSON: 70 size += 2 + len(vals[i].GetBytes()) 71 case types.HoTTMysqlDecimal: 72 size += 1 + types.MyDecimalStructSize 73 default: 74 return b 75 } 76 } 77 return reallocBytes(b, size) 78 } 79 80 // encode will encode a causet and append it to a byte slice. If comparable is true, the encoded bytes can be sorted as it's original order. 81 // If hash is true, the encoded bytes can be checked equal as it's original value. 82 func encode(sc *stmtctx.StatementContext, b []byte, vals []types.Causet, comparable bool) (_ []byte, err error) { 83 b = preRealloc(b, vals, comparable) 84 for i, length := 0, len(vals); i < length; i++ { 85 switch vals[i].HoTT() { 86 case types.HoTTInt64: 87 b = encodeSignedInt(b, vals[i].GetInt64(), comparable) 88 case types.HoTTUint64: 89 b = encodeUnsignedInt(b, vals[i].GetUint64(), comparable) 90 case types.HoTTFloat32, types.HoTTFloat64: 91 b = append(b, floatFlag) 92 b = EncodeFloat(b, vals[i].GetFloat64()) 93 case types.HoTTString: 94 b = encodeString(b, vals[i], comparable) 95 case types.HoTTBytes: 96 b = encodeBytes(b, vals[i].GetBytes(), comparable) 97 case types.HoTTMysqlTime: 98 b = append(b, uintFlag) 99 b, err = EncodeMyALLEGROSQLTime(sc, vals[i].GetMysqlTime(), allegrosql.TypeUnspecified, b) 100 if err != nil { 101 return b, err 102 } 103 case types.HoTTMysqlDuration: 104 // duration may have negative value, so we cannot use String to encode directly. 105 b = append(b, durationFlag) 106 b = EncodeInt(b, int64(vals[i].GetMysqlDuration().Duration)) 107 case types.HoTTMysqlDecimal: 108 b = append(b, decimalFlag) 109 b, err = EncodeDecimal(b, vals[i].GetMysqlDecimal(), vals[i].Length(), vals[i].Frac()) 110 if terror.ErrorEqual(err, types.ErrTruncated) { 111 err = sc.HandleTruncate(err) 112 } else if terror.ErrorEqual(err, types.ErrOverflow) { 113 err = sc.HandleOverflow(err, err) 114 } 115 case types.HoTTMysqlEnum: 116 b = encodeUnsignedInt(b, uint64(vals[i].GetMysqlEnum().ToNumber()), comparable) 117 case types.HoTTMysqlSet: 118 b = encodeUnsignedInt(b, uint64(vals[i].GetMysqlSet().ToNumber()), comparable) 119 case types.HoTTMysqlBit, types.HoTTBinaryLiteral: 120 // We don't need to handle errors here since the literal is ensured to be able to causetstore in uint64 in convertToMysqlBit. 121 var val uint64 122 val, err = vals[i].GetBinaryLiteral().ToInt(sc) 123 terror.Log(errors.Trace(err)) 124 b = encodeUnsignedInt(b, val, comparable) 125 case types.HoTTMysqlJSON: 126 b = append(b, jsonFlag) 127 j := vals[i].GetMysqlJSON() 128 b = append(b, j.TypeCode) 129 b = append(b, j.Value...) 130 case types.HoTTNull: 131 b = append(b, NilFlag) 132 case types.HoTTMinNotNull: 133 b = append(b, bytesFlag) 134 case types.HoTTMaxValue: 135 b = append(b, maxFlag) 136 default: 137 return b, errors.Errorf("unsupport encode type %d", vals[i].HoTT()) 138 } 139 } 140 141 return b, errors.Trace(err) 142 } 143 144 // EstimateValueSize uses to estimate the value size of the encoded values. 145 func EstimateValueSize(sc *stmtctx.StatementContext, val types.Causet) (int, error) { 146 l := 0 147 switch val.HoTT() { 148 case types.HoTTInt64: 149 l = valueSizeOfSignedInt(val.GetInt64()) 150 case types.HoTTUint64: 151 l = valueSizeOfUnsignedInt(val.GetUint64()) 152 case types.HoTTFloat32, types.HoTTFloat64, types.HoTTMysqlTime, types.HoTTMysqlDuration: 153 l = 9 154 case types.HoTTString, types.HoTTBytes: 155 l = valueSizeOfBytes(val.GetBytes()) 156 case types.HoTTMysqlDecimal: 157 l = valueSizeOfDecimal(val.GetMysqlDecimal(), val.Length(), val.Frac()) + 1 158 case types.HoTTMysqlEnum: 159 l = valueSizeOfUnsignedInt(uint64(val.GetMysqlEnum().ToNumber())) 160 case types.HoTTMysqlSet: 161 l = valueSizeOfUnsignedInt(uint64(val.GetMysqlSet().ToNumber())) 162 case types.HoTTMysqlBit, types.HoTTBinaryLiteral: 163 val, err := val.GetBinaryLiteral().ToInt(sc) 164 terror.Log(errors.Trace(err)) 165 l = valueSizeOfUnsignedInt(val) 166 case types.HoTTMysqlJSON: 167 l = 2 + len(val.GetMysqlJSON().Value) 168 case types.HoTTNull, types.HoTTMinNotNull, types.HoTTMaxValue: 169 l = 1 170 default: 171 return l, errors.Errorf("unsupported encode type %d", val.HoTT()) 172 } 173 return l, nil 174 } 175 176 // EncodeMyALLEGROSQLTime encodes causet of `HoTTMysqlTime` to []byte. 177 func EncodeMyALLEGROSQLTime(sc *stmtctx.StatementContext, t types.Time, tp byte, b []byte) (_ []byte, err error) { 178 // Encoding timestamp need to consider timezone. If it's not in UTC, transform to UTC first. 179 // This is compatible with `PBToExpr > convertTime`, and interlock assumes the passed timestamp is in UTC as well. 180 if tp == allegrosql.TypeUnspecified { 181 tp = t.Type() 182 } 183 if tp == allegrosql.TypeTimestamp && sc.TimeZone != time.UTC { 184 err = t.ConvertTimeZone(sc.TimeZone, time.UTC) 185 if err != nil { 186 return nil, err 187 } 188 } 189 var v uint64 190 v, err = t.ToPackedUint() 191 if err != nil { 192 return nil, err 193 } 194 b = EncodeUint(b, v) 195 return b, nil 196 } 197 198 func encodeString(b []byte, val types.Causet, comparable bool) []byte { 199 if defCauslate.NewDefCauslationEnabled() && comparable { 200 return encodeBytes(b, defCauslate.GetDefCauslator(val.DefCauslation()).Key(val.GetString()), true) 201 } 202 return encodeBytes(b, val.GetBytes(), comparable) 203 } 204 205 func encodeBytes(b []byte, v []byte, comparable bool) []byte { 206 if comparable { 207 b = append(b, bytesFlag) 208 b = EncodeBytes(b, v) 209 } else { 210 b = append(b, compactBytesFlag) 211 b = EncodeCompactBytes(b, v) 212 } 213 return b 214 } 215 216 func valueSizeOfBytes(v []byte) int { 217 return valueSizeOfSignedInt(int64(len(v))) + len(v) 218 } 219 220 func sizeBytes(v []byte, comparable bool) int { 221 if comparable { 222 reallocSize := (len(v)/encGroupSize + 1) * (encGroupSize + 1) 223 return 1 + reallocSize 224 } 225 reallocSize := binary.MaxVarintLen64 + len(v) 226 return 1 + reallocSize 227 } 228 229 func encodeSignedInt(b []byte, v int64, comparable bool) []byte { 230 if comparable { 231 b = append(b, intFlag) 232 b = EncodeInt(b, v) 233 } else { 234 b = append(b, varintFlag) 235 b = EncodeVarint(b, v) 236 } 237 return b 238 } 239 240 func valueSizeOfSignedInt(v int64) int { 241 if v < 0 { 242 v = 0 - v - 1 243 } 244 // Flag occupy 1 bit and at lease 1 bit. 245 size := 2 246 v = v >> 6 247 for v > 0 { 248 size++ 249 v = v >> 7 250 } 251 return size 252 } 253 254 func encodeUnsignedInt(b []byte, v uint64, comparable bool) []byte { 255 if comparable { 256 b = append(b, uintFlag) 257 b = EncodeUint(b, v) 258 } else { 259 b = append(b, uvarintFlag) 260 b = EncodeUvarint(b, v) 261 } 262 return b 263 } 264 265 func valueSizeOfUnsignedInt(v uint64) int { 266 // Flag occupy 1 bit and at lease 1 bit. 267 size := 2 268 v = v >> 7 269 for v > 0 { 270 size++ 271 v = v >> 7 272 } 273 return size 274 } 275 276 func sizeInt(comparable bool) int { 277 if comparable { 278 return 9 279 } 280 return 1 + binary.MaxVarintLen64 281 } 282 283 // EncodeKey appends the encoded values to byte slice b, returns the appended 284 // slice. It guarantees the encoded value is in ascending order for comparison. 285 // For Decimal type, causet must set causet's length and frac. 286 func EncodeKey(sc *stmtctx.StatementContext, b []byte, v ...types.Causet) ([]byte, error) { 287 return encode(sc, b, v, true) 288 } 289 290 // EncodeValue appends the encoded values to byte slice b, returning the appended 291 // slice. It does not guarantee the order for comparison. 292 func EncodeValue(sc *stmtctx.StatementContext, b []byte, v ...types.Causet) ([]byte, error) { 293 return encode(sc, b, v, false) 294 } 295 296 func encodeHashChunkRowIdx(sc *stmtctx.StatementContext, event chunk.Row, tp *types.FieldType, idx int) (flag byte, b []byte, err error) { 297 if event.IsNull(idx) { 298 flag = NilFlag 299 return 300 } 301 switch tp.Tp { 302 case allegrosql.TypeTiny, allegrosql.TypeShort, allegrosql.TypeInt24, allegrosql.TypeLong, allegrosql.TypeLonglong, allegrosql.TypeYear: 303 flag = uvarintFlag 304 if !allegrosql.HasUnsignedFlag(tp.Flag) && event.GetInt64(idx) < 0 { 305 flag = varintFlag 306 } 307 b = event.GetRaw(idx) 308 case allegrosql.TypeFloat: 309 flag = floatFlag 310 f := float64(event.GetFloat32(idx)) 311 // For negative zero. In memory, 0 is [0, 0, 0, 0, 0, 0, 0, 0] and -0 is [0, 0, 0, 0, 0, 0, 0, 128]. 312 // It makes -0's hash val different from 0's. 313 if f == 0 { 314 f = 0 315 } 316 b = (*[unsafe.Sizeof(f)]byte)(unsafe.Pointer(&f))[:] 317 case allegrosql.TypeDouble: 318 flag = floatFlag 319 f := event.GetFloat64(idx) 320 // For negative zero. In memory, 0 is [0, 0, 0, 0, 0, 0, 0, 0] and -0 is [0, 0, 0, 0, 0, 0, 0, 128]. 321 // It makes -0's hash val different from 0's. 322 if f == 0 { 323 f = 0 324 } 325 b = (*[unsafe.Sizeof(f)]byte)(unsafe.Pointer(&f))[:] 326 case allegrosql.TypeVarchar, allegrosql.TypeVarString, allegrosql.TypeString, allegrosql.TypeBlob, allegrosql.TypeTinyBlob, allegrosql.TypeMediumBlob, allegrosql.TypeLongBlob: 327 flag = compactBytesFlag 328 b = event.GetBytes(idx) 329 b = ConvertByDefCauslation(b, tp) 330 case allegrosql.TypeDate, allegrosql.TypeDatetime, allegrosql.TypeTimestamp: 331 flag = uintFlag 332 t := event.GetTime(idx) 333 // Encoding timestamp need to consider timezone. 334 // If it's not in UTC, transform to UTC first. 335 if t.Type() == allegrosql.TypeTimestamp && sc.TimeZone != time.UTC { 336 err = t.ConvertTimeZone(sc.TimeZone, time.UTC) 337 if err != nil { 338 return 339 } 340 } 341 var v uint64 342 v, err = t.ToPackedUint() 343 if err != nil { 344 return 345 } 346 b = (*[unsafe.Sizeof(v)]byte)(unsafe.Pointer(&v))[:] 347 case allegrosql.TypeDuration: 348 flag = durationFlag 349 // duration may have negative value, so we cannot use String to encode directly. 350 b = event.GetRaw(idx) 351 case allegrosql.TypeNewDecimal: 352 flag = decimalFlag 353 // If hash is true, we only consider the original value of this decimal and ignore it's precision. 354 dec := event.GetMyDecimal(idx) 355 b, err = dec.ToHashKey() 356 if err != nil { 357 return 358 } 359 case allegrosql.TypeEnum: 360 flag = compactBytesFlag 361 v := uint64(event.GetEnum(idx).ToNumber()) 362 str := tp.Elems[v-1] 363 b = ConvertByDefCauslation(replog.Slice(str), tp) 364 case allegrosql.TypeSet: 365 flag = compactBytesFlag 366 v := uint64(event.GetSet(idx).ToNumber()) 367 str := tp.Elems[v-1] 368 b = ConvertByDefCauslation(replog.Slice(str), tp) 369 case allegrosql.TypeBit: 370 // We don't need to handle errors here since the literal is ensured to be able to causetstore in uint64 in convertToMysqlBit. 371 flag = uvarintFlag 372 v, err1 := types.BinaryLiteral(event.GetBytes(idx)).ToInt(sc) 373 terror.Log(errors.Trace(err1)) 374 b = (*[unsafe.Sizeof(v)]byte)(unsafe.Pointer(&v))[:] 375 case allegrosql.TypeJSON: 376 flag = jsonFlag 377 b = event.GetBytes(idx) 378 default: 379 return 0, nil, errors.Errorf("unsupport defCausumn type for encode %d", tp.Tp) 380 } 381 return 382 } 383 384 // HashChunkDeferredCausets writes the encoded value of each event's defCausumn, which of index `defCausIdx`, to h. 385 func HashChunkDeferredCausets(sc *stmtctx.StatementContext, h []hash.Hash64, chk *chunk.Chunk, tp *types.FieldType, defCausIdx int, buf []byte, isNull []bool) (err error) { 386 return HashChunkSelected(sc, h, chk, tp, defCausIdx, buf, isNull, nil, false) 387 } 388 389 // HashChunkSelected writes the encoded value of selected event's defCausumn, which of index `defCausIdx`, to h. 390 // sel indicates which rows are selected. If it is nil, all rows are selected. 391 func HashChunkSelected(sc *stmtctx.StatementContext, h []hash.Hash64, chk *chunk.Chunk, tp *types.FieldType, defCausIdx int, buf []byte, 392 isNull, sel []bool, ignoreNull bool) (err error) { 393 var b []byte 394 defCausumn := chk.DeferredCauset(defCausIdx) 395 rows := chk.NumRows() 396 switch tp.Tp { 397 case allegrosql.TypeTiny, allegrosql.TypeShort, allegrosql.TypeInt24, allegrosql.TypeLong, allegrosql.TypeLonglong, allegrosql.TypeYear: 398 i64s := defCausumn.Int64s() 399 for i, v := range i64s { 400 if sel != nil && !sel[i] { 401 continue 402 } 403 if defCausumn.IsNull(i) { 404 buf[0], b = NilFlag, nil 405 isNull[i] = !ignoreNull 406 } else { 407 buf[0] = uvarintFlag 408 if !allegrosql.HasUnsignedFlag(tp.Flag) && v < 0 { 409 buf[0] = varintFlag 410 } 411 b = defCausumn.GetRaw(i) 412 } 413 414 // As the golang doc described, `Hash.Write` never returns an error. 415 // See https://golang.org/pkg/hash/#Hash 416 _, _ = h[i].Write(buf) 417 _, _ = h[i].Write(b) 418 } 419 case allegrosql.TypeFloat: 420 f32s := defCausumn.Float32s() 421 for i, f := range f32s { 422 if sel != nil && !sel[i] { 423 continue 424 } 425 if defCausumn.IsNull(i) { 426 buf[0], b = NilFlag, nil 427 isNull[i] = !ignoreNull 428 } else { 429 buf[0] = floatFlag 430 d := float64(f) 431 // For negative zero. In memory, 0 is [0, 0, 0, 0, 0, 0, 0, 0] and -0 is [0, 0, 0, 0, 0, 0, 0, 128]. 432 // It makes -0's hash val different from 0's. 433 if d == 0 { 434 d = 0 435 } 436 b = (*[sizeFloat64]byte)(unsafe.Pointer(&d))[:] 437 } 438 439 // As the golang doc described, `Hash.Write` never returns an error. 440 // See https://golang.org/pkg/hash/#Hash 441 _, _ = h[i].Write(buf) 442 _, _ = h[i].Write(b) 443 } 444 case allegrosql.TypeDouble: 445 f64s := defCausumn.Float64s() 446 for i, f := range f64s { 447 if sel != nil && !sel[i] { 448 continue 449 } 450 if defCausumn.IsNull(i) { 451 buf[0], b = NilFlag, nil 452 isNull[i] = !ignoreNull 453 } else { 454 buf[0] = floatFlag 455 // For negative zero. In memory, 0 is [0, 0, 0, 0, 0, 0, 0, 0] and -0 is [0, 0, 0, 0, 0, 0, 0, 128]. 456 // It makes -0's hash val different from 0's. 457 if f == 0 { 458 f = 0 459 } 460 b = (*[sizeFloat64]byte)(unsafe.Pointer(&f))[:] 461 } 462 463 // As the golang doc described, `Hash.Write` never returns an error. 464 // See https://golang.org/pkg/hash/#Hash 465 _, _ = h[i].Write(buf) 466 _, _ = h[i].Write(b) 467 } 468 case allegrosql.TypeVarchar, allegrosql.TypeVarString, allegrosql.TypeString, allegrosql.TypeBlob, allegrosql.TypeTinyBlob, allegrosql.TypeMediumBlob, allegrosql.TypeLongBlob: 469 for i := 0; i < rows; i++ { 470 if sel != nil && !sel[i] { 471 continue 472 } 473 if defCausumn.IsNull(i) { 474 buf[0], b = NilFlag, nil 475 isNull[i] = !ignoreNull 476 } else { 477 buf[0] = compactBytesFlag 478 b = defCausumn.GetBytes(i) 479 b = ConvertByDefCauslation(b, tp) 480 } 481 482 // As the golang doc described, `Hash.Write` never returns an error. 483 // See https://golang.org/pkg/hash/#Hash 484 _, _ = h[i].Write(buf) 485 _, _ = h[i].Write(b) 486 } 487 case allegrosql.TypeDate, allegrosql.TypeDatetime, allegrosql.TypeTimestamp: 488 ts := defCausumn.Times() 489 for i, t := range ts { 490 if sel != nil && !sel[i] { 491 continue 492 } 493 if defCausumn.IsNull(i) { 494 buf[0], b = NilFlag, nil 495 isNull[i] = !ignoreNull 496 } else { 497 buf[0] = uintFlag 498 // Encoding timestamp need to consider timezone. 499 // If it's not in UTC, transform to UTC first. 500 if t.Type() == allegrosql.TypeTimestamp && sc.TimeZone != time.UTC { 501 err = t.ConvertTimeZone(sc.TimeZone, time.UTC) 502 if err != nil { 503 return 504 } 505 } 506 var v uint64 507 v, err = t.ToPackedUint() 508 if err != nil { 509 return 510 } 511 b = (*[sizeUint64]byte)(unsafe.Pointer(&v))[:] 512 } 513 514 // As the golang doc described, `Hash.Write` never returns an error. 515 // See https://golang.org/pkg/hash/#Hash 516 _, _ = h[i].Write(buf) 517 _, _ = h[i].Write(b) 518 } 519 case allegrosql.TypeDuration: 520 for i := 0; i < rows; i++ { 521 if sel != nil && !sel[i] { 522 continue 523 } 524 if defCausumn.IsNull(i) { 525 buf[0], b = NilFlag, nil 526 isNull[i] = !ignoreNull 527 } else { 528 buf[0] = durationFlag 529 // duration may have negative value, so we cannot use String to encode directly. 530 b = defCausumn.GetRaw(i) 531 } 532 533 // As the golang doc described, `Hash.Write` never returns an error. 534 // See https://golang.org/pkg/hash/#Hash 535 _, _ = h[i].Write(buf) 536 _, _ = h[i].Write(b) 537 } 538 case allegrosql.TypeNewDecimal: 539 ds := defCausumn.Decimals() 540 for i, d := range ds { 541 if sel != nil && !sel[i] { 542 continue 543 } 544 if defCausumn.IsNull(i) { 545 buf[0], b = NilFlag, nil 546 isNull[i] = !ignoreNull 547 } else { 548 buf[0] = decimalFlag 549 // If hash is true, we only consider the original value of this decimal and ignore it's precision. 550 b, err = d.ToHashKey() 551 if err != nil { 552 return 553 } 554 } 555 556 // As the golang doc described, `Hash.Write` never returns an error. 557 // See https://golang.org/pkg/hash/#Hash 558 _, _ = h[i].Write(buf) 559 _, _ = h[i].Write(b) 560 } 561 case allegrosql.TypeEnum: 562 for i := 0; i < rows; i++ { 563 if sel != nil && !sel[i] { 564 continue 565 } 566 if defCausumn.IsNull(i) { 567 buf[0], b = NilFlag, nil 568 isNull[i] = !ignoreNull 569 } else { 570 buf[0] = compactBytesFlag 571 v := uint64(defCausumn.GetEnum(i).ToNumber()) 572 str := tp.Elems[v-1] 573 b = ConvertByDefCauslation(replog.Slice(str), tp) 574 } 575 576 // As the golang doc described, `Hash.Write` never returns an error. 577 // See https://golang.org/pkg/hash/#Hash 578 _, _ = h[i].Write(buf) 579 _, _ = h[i].Write(b) 580 } 581 case allegrosql.TypeSet: 582 for i := 0; i < rows; i++ { 583 if sel != nil && !sel[i] { 584 continue 585 } 586 if defCausumn.IsNull(i) { 587 buf[0], b = NilFlag, nil 588 isNull[i] = !ignoreNull 589 } else { 590 buf[0] = compactBytesFlag 591 v := uint64(defCausumn.GetSet(i).ToNumber()) 592 str := tp.Elems[v-1] 593 b = ConvertByDefCauslation(replog.Slice(str), tp) 594 } 595 596 // As the golang doc described, `Hash.Write` never returns an error. 597 // See https://golang.org/pkg/hash/#Hash 598 _, _ = h[i].Write(buf) 599 _, _ = h[i].Write(b) 600 } 601 case allegrosql.TypeBit: 602 for i := 0; i < rows; i++ { 603 if sel != nil && !sel[i] { 604 continue 605 } 606 if defCausumn.IsNull(i) { 607 buf[0], b = NilFlag, nil 608 isNull[i] = !ignoreNull 609 } else { 610 // We don't need to handle errors here since the literal is ensured to be able to causetstore in uint64 in convertToMysqlBit. 611 buf[0] = uvarintFlag 612 v, err1 := types.BinaryLiteral(defCausumn.GetBytes(i)).ToInt(sc) 613 terror.Log(errors.Trace(err1)) 614 b = (*[sizeUint64]byte)(unsafe.Pointer(&v))[:] 615 } 616 617 // As the golang doc described, `Hash.Write` never returns an error. 618 // See https://golang.org/pkg/hash/#Hash 619 _, _ = h[i].Write(buf) 620 _, _ = h[i].Write(b) 621 } 622 case allegrosql.TypeJSON: 623 for i := 0; i < rows; i++ { 624 if sel != nil && !sel[i] { 625 continue 626 } 627 if defCausumn.IsNull(i) { 628 buf[0], b = NilFlag, nil 629 isNull[i] = !ignoreNull 630 } else { 631 buf[0] = jsonFlag 632 b = defCausumn.GetBytes(i) 633 } 634 635 // As the golang doc described, `Hash.Write` never returns an error.. 636 // See https://golang.org/pkg/hash/#Hash 637 _, _ = h[i].Write(buf) 638 _, _ = h[i].Write(b) 639 } 640 case allegrosql.TypeNull: 641 for i := 0; i < rows; i++ { 642 if sel != nil && !sel[i] { 643 continue 644 } 645 isNull[i] = !ignoreNull 646 buf[0] = NilFlag 647 _, _ = h[i].Write(buf) 648 } 649 default: 650 return errors.Errorf("unsupport defCausumn type for encode %d", tp.Tp) 651 } 652 return 653 } 654 655 // HashChunkRow writes the encoded values to w. 656 // If two rows are logically equal, it will generate the same bytes. 657 func HashChunkRow(sc *stmtctx.StatementContext, w io.Writer, event chunk.Row, allTypes []*types.FieldType, defCausIdx []int, buf []byte) (err error) { 658 var b []byte 659 for _, idx := range defCausIdx { 660 buf[0], b, err = encodeHashChunkRowIdx(sc, event, allTypes[idx], idx) 661 if err != nil { 662 return errors.Trace(err) 663 } 664 _, err = w.Write(buf) 665 if err != nil { 666 return 667 } 668 _, err = w.Write(b) 669 if err != nil { 670 return 671 } 672 } 673 return err 674 } 675 676 // EqualChunkRow returns a boolean reporting whether row1 and row2 677 // with their types and defCausumn index are logically equal. 678 func EqualChunkRow(sc *stmtctx.StatementContext, 679 row1 chunk.Row, allTypes1 []*types.FieldType, defCausIdx1 []int, 680 row2 chunk.Row, allTypes2 []*types.FieldType, defCausIdx2 []int, 681 ) (bool, error) { 682 for i := range defCausIdx1 { 683 idx1, idx2 := defCausIdx1[i], defCausIdx2[i] 684 flag1, b1, err := encodeHashChunkRowIdx(sc, row1, allTypes1[idx1], idx1) 685 if err != nil { 686 return false, errors.Trace(err) 687 } 688 flag2, b2, err := encodeHashChunkRowIdx(sc, row2, allTypes2[idx2], idx2) 689 if err != nil { 690 return false, errors.Trace(err) 691 } 692 if !(flag1 == flag2 && bytes.Equal(b1, b2)) { 693 return false, nil 694 } 695 } 696 return true, nil 697 } 698 699 // Decode decodes values from a byte slice generated with EncodeKey or EncodeValue 700 // before. 701 // size is the size of decoded causet slice. 702 func Decode(b []byte, size int) ([]types.Causet, error) { 703 if len(b) < 1 { 704 return nil, errors.New("invalid encoded key") 705 } 706 707 var ( 708 err error 709 values = make([]types.Causet, 0, size) 710 ) 711 712 for len(b) > 0 { 713 var d types.Causet 714 b, d, err = DecodeOne(b) 715 if err != nil { 716 return nil, errors.Trace(err) 717 } 718 719 values = append(values, d) 720 } 721 722 return values, nil 723 } 724 725 // DecodeRange decodes the range values from a byte slice that generated by EncodeKey. 726 // It handles some special values like `MinNotNull` and `MaxValueCauset`. 727 // loc can be nil and only used in when the corresponding type is `allegrosql.TypeTimestamp`. 728 func DecodeRange(b []byte, size int, idxDeferredCausetTypes []byte, loc *time.Location) ([]types.Causet, []byte, error) { 729 if len(b) < 1 { 730 return nil, b, errors.New("invalid encoded key: length of key is zero") 731 } 732 733 var ( 734 err error 735 values = make([]types.Causet, 0, size) 736 ) 737 738 i := 0 739 for len(b) > 1 { 740 var d types.Causet 741 if idxDeferredCausetTypes == nil { 742 b, d, err = DecodeOne(b) 743 } else { 744 if i >= len(idxDeferredCausetTypes) { 745 return values, b, errors.New("invalid length of index's defCausumns") 746 } 747 if idxDeferredCausetTypes[i] == allegrosql.TypeDatetime || idxDeferredCausetTypes[i] == allegrosql.TypeTimestamp || idxDeferredCausetTypes[i] == allegrosql.TypeDate { 748 b, d, err = DecodeAsDateTime(b, idxDeferredCausetTypes[i], loc) 749 } else { 750 b, d, err = DecodeOne(b) 751 } 752 } 753 if err != nil { 754 return values, b, errors.Trace(err) 755 } 756 values = append(values, d) 757 i++ 758 } 759 760 if len(b) == 1 { 761 switch b[0] { 762 case NilFlag: 763 values = append(values, types.Causet{}) 764 case bytesFlag: 765 values = append(values, types.MinNotNullCauset()) 766 // `maxFlag + 1` for PrefixNext 767 case maxFlag, maxFlag + 1: 768 values = append(values, types.MaxValueCauset()) 769 default: 770 return values, b, errors.Errorf("invalid encoded key flag %v", b[0]) 771 } 772 } 773 return values, nil, nil 774 } 775 776 // DecodeOne decodes on causet from a byte slice generated with EncodeKey or EncodeValue. 777 func DecodeOne(b []byte) (remain []byte, d types.Causet, err error) { 778 if len(b) < 1 { 779 return nil, d, errors.New("invalid encoded key") 780 } 781 flag := b[0] 782 b = b[1:] 783 switch flag { 784 case intFlag: 785 var v int64 786 b, v, err = DecodeInt(b) 787 d.SetInt64(v) 788 case uintFlag: 789 var v uint64 790 b, v, err = DecodeUint(b) 791 d.SetUint64(v) 792 case varintFlag: 793 var v int64 794 b, v, err = DecodeVarint(b) 795 d.SetInt64(v) 796 case uvarintFlag: 797 var v uint64 798 b, v, err = DecodeUvarint(b) 799 d.SetUint64(v) 800 case floatFlag: 801 var v float64 802 b, v, err = DecodeFloat(b) 803 d.SetFloat64(v) 804 case bytesFlag: 805 var v []byte 806 b, v, err = DecodeBytes(b, nil) 807 d.SetBytes(v) 808 case compactBytesFlag: 809 var v []byte 810 b, v, err = DecodeCompactBytes(b) 811 d.SetBytes(v) 812 case decimalFlag: 813 var ( 814 dec *types.MyDecimal 815 precision, frac int 816 ) 817 b, dec, precision, frac, err = DecodeDecimal(b) 818 if err == nil { 819 d.SetMysqlDecimal(dec) 820 d.SetLength(precision) 821 d.SetFrac(frac) 822 } 823 case durationFlag: 824 var r int64 825 b, r, err = DecodeInt(b) 826 if err == nil { 827 // use max fsp, let outer to do round manually. 828 v := types.Duration{Duration: time.Duration(r), Fsp: types.MaxFsp} 829 d.SetMysqlDuration(v) 830 } 831 case jsonFlag: 832 var size int 833 size, err = json.PeekBytesAsJSON(b) 834 if err != nil { 835 return b, d, err 836 } 837 j := json.BinaryJSON{TypeCode: b[0], Value: b[1:size]} 838 d.SetMysqlJSON(j) 839 b = b[size:] 840 case NilFlag: 841 default: 842 return b, d, errors.Errorf("invalid encoded key flag %v", flag) 843 } 844 if err != nil { 845 return b, d, errors.Trace(err) 846 } 847 return b, d, nil 848 } 849 850 // DecodeAsDateTime decodes on causet from []byte of `HoTTMysqlTime`. 851 func DecodeAsDateTime(b []byte, tp byte, loc *time.Location) (remain []byte, d types.Causet, err error) { 852 if len(b) < 1 { 853 return nil, d, errors.New("invalid encoded key") 854 } 855 flag := b[0] 856 b = b[1:] 857 switch flag { 858 case uintFlag: 859 var v uint64 860 b, v, err = DecodeUint(b) 861 if err != nil { 862 return b, d, err 863 } 864 t := types.NewTime(types.ZeroCoreTime, tp, 0) 865 err = t.FromPackedUint(v) 866 if err == nil { 867 if tp == allegrosql.TypeTimestamp && !t.IsZero() && loc != nil { 868 err = t.ConvertTimeZone(time.UTC, loc) 869 if err != nil { 870 return b, d, err 871 } 872 } 873 d.SetMysqlTime(t) 874 } 875 default: 876 return b, d, errors.Errorf("invalid encoded key flag %v", flag) 877 } 878 if err != nil { 879 return b, d, errors.Trace(err) 880 } 881 return b, d, nil 882 } 883 884 // CutOne cuts the first encoded value from b. 885 // It will return the first encoded item and the remains as byte slice. 886 func CutOne(b []byte) (data []byte, remain []byte, err error) { 887 l, err := peek(b) 888 if err != nil { 889 return nil, nil, errors.Trace(err) 890 } 891 return b[:l], b[l:], nil 892 } 893 894 // CutDeferredCausetID cuts the defCausumn ID from b. 895 // It will return the remains as byte slice and defCausumn ID 896 func CutDeferredCausetID(b []byte) (remain []byte, n int64, err error) { 897 if len(b) < 1 { 898 return nil, 0, errors.New("invalid encoded key") 899 } 900 // skip the flag 901 b = b[1:] 902 return DecodeVarint(b) 903 } 904 905 // SetRawValues set raw causet values from a event data. 906 func SetRawValues(data []byte, values []types.Causet) error { 907 for i := 0; i < len(values); i++ { 908 l, err := peek(data) 909 if err != nil { 910 return errors.Trace(err) 911 } 912 values[i].SetRaw(data[:l:l]) 913 data = data[l:] 914 } 915 return nil 916 } 917 918 // peek peeks the first encoded value from b and returns its length. 919 func peek(b []byte) (length int, err error) { 920 if len(b) < 1 { 921 return 0, errors.New("invalid encoded key") 922 } 923 flag := b[0] 924 length++ 925 b = b[1:] 926 var l int 927 switch flag { 928 case NilFlag: 929 case intFlag, uintFlag, floatFlag, durationFlag: 930 // Those types are stored in 8 bytes. 931 l = 8 932 case bytesFlag: 933 l, err = peekBytes(b) 934 case compactBytesFlag: 935 l, err = peekCompactBytes(b) 936 case decimalFlag: 937 l, err = types.DecimalPeak(b) 938 case varintFlag: 939 l, err = peekVarint(b) 940 case uvarintFlag: 941 l, err = peekUvarint(b) 942 case jsonFlag: 943 l, err = json.PeekBytesAsJSON(b) 944 default: 945 return 0, errors.Errorf("invalid encoded key flag %v", flag) 946 } 947 if err != nil { 948 return 0, errors.Trace(err) 949 } 950 length += l 951 return 952 } 953 954 func peekBytes(b []byte) (int, error) { 955 offset := 0 956 for { 957 if len(b) < offset+encGroupSize+1 { 958 return 0, errors.New("insufficient bytes to decode value") 959 } 960 // The byte slice is encoded into many groups. 961 // For each group, there are 8 bytes for data and 1 byte for marker. 962 marker := b[offset+encGroupSize] 963 padCount := encMarker - marker 964 offset += encGroupSize + 1 965 // When padCount is not zero, it means we get the end of the byte slice. 966 if padCount != 0 { 967 break 968 } 969 } 970 return offset, nil 971 } 972 973 func peekCompactBytes(b []byte) (int, error) { 974 // Get length. 975 v, n := binary.Varint(b) 976 vi := int(v) 977 if n < 0 { 978 return 0, errors.New("value larger than 64 bits") 979 } else if n == 0 { 980 return 0, errors.New("insufficient bytes to decode value") 981 } 982 if len(b) < vi+n { 983 return 0, errors.Errorf("insufficient bytes to decode value, expected length: %v", n) 984 } 985 return n + vi, nil 986 } 987 988 func peekVarint(b []byte) (int, error) { 989 _, n := binary.Varint(b) 990 if n < 0 { 991 return 0, errors.New("value larger than 64 bits") 992 } 993 return n, nil 994 } 995 996 func peekUvarint(b []byte) (int, error) { 997 _, n := binary.Uvarint(b) 998 if n < 0 { 999 return 0, errors.New("value larger than 64 bits") 1000 } 1001 return n, nil 1002 } 1003 1004 // CausetDecoder is used to decode value to chunk. 1005 type CausetDecoder struct { 1006 chk *chunk.Chunk 1007 timezone *time.Location 1008 1009 // buf is only used for DecodeBytes to avoid the cost of makeslice. 1010 buf []byte 1011 } 1012 1013 // NewCausetDecoder creates a CausetDecoder. 1014 func NewCausetDecoder(chk *chunk.Chunk, timezone *time.Location) *CausetDecoder { 1015 return &CausetDecoder{ 1016 chk: chk, 1017 timezone: timezone, 1018 } 1019 } 1020 1021 // DecodeOne decodes one value to chunk and returns the remained bytes. 1022 func (causetDecoder *CausetDecoder) DecodeOne(b []byte, defCausIdx int, ft *types.FieldType) (remain []byte, err error) { 1023 if len(b) < 1 { 1024 return nil, errors.New("invalid encoded key") 1025 } 1026 chk := causetDecoder.chk 1027 flag := b[0] 1028 b = b[1:] 1029 switch flag { 1030 case intFlag: 1031 var v int64 1032 b, v, err = DecodeInt(b) 1033 if err != nil { 1034 return nil, errors.Trace(err) 1035 } 1036 appendIntToChunk(v, chk, defCausIdx, ft) 1037 case uintFlag: 1038 var v uint64 1039 b, v, err = DecodeUint(b) 1040 if err != nil { 1041 return nil, errors.Trace(err) 1042 } 1043 err = appendUintToChunk(v, chk, defCausIdx, ft, causetDecoder.timezone) 1044 case varintFlag: 1045 var v int64 1046 b, v, err = DecodeVarint(b) 1047 if err != nil { 1048 return nil, errors.Trace(err) 1049 } 1050 appendIntToChunk(v, chk, defCausIdx, ft) 1051 case uvarintFlag: 1052 var v uint64 1053 b, v, err = DecodeUvarint(b) 1054 if err != nil { 1055 return nil, errors.Trace(err) 1056 } 1057 err = appendUintToChunk(v, chk, defCausIdx, ft, causetDecoder.timezone) 1058 case floatFlag: 1059 var v float64 1060 b, v, err = DecodeFloat(b) 1061 if err != nil { 1062 return nil, errors.Trace(err) 1063 } 1064 appendFloatToChunk(v, chk, defCausIdx, ft) 1065 case bytesFlag: 1066 b, causetDecoder.buf, err = DecodeBytes(b, causetDecoder.buf) 1067 if err != nil { 1068 return nil, errors.Trace(err) 1069 } 1070 chk.AppendBytes(defCausIdx, causetDecoder.buf) 1071 case compactBytesFlag: 1072 var v []byte 1073 b, v, err = DecodeCompactBytes(b) 1074 if err != nil { 1075 return nil, errors.Trace(err) 1076 } 1077 chk.AppendBytes(defCausIdx, v) 1078 case decimalFlag: 1079 var dec *types.MyDecimal 1080 var frac int 1081 b, dec, _, frac, err = DecodeDecimal(b) 1082 if err != nil { 1083 return nil, errors.Trace(err) 1084 } 1085 if ft.Decimal != types.UnspecifiedLength && frac > ft.Decimal { 1086 to := new(types.MyDecimal) 1087 err := dec.Round(to, ft.Decimal, types.ModeHalfEven) 1088 if err != nil { 1089 return nil, errors.Trace(err) 1090 } 1091 dec = to 1092 } 1093 chk.AppendMyDecimal(defCausIdx, dec) 1094 case durationFlag: 1095 var r int64 1096 b, r, err = DecodeInt(b) 1097 if err != nil { 1098 return nil, errors.Trace(err) 1099 } 1100 v := types.Duration{Duration: time.Duration(r), Fsp: int8(ft.Decimal)} 1101 chk.AppendDuration(defCausIdx, v) 1102 case jsonFlag: 1103 var size int 1104 size, err = json.PeekBytesAsJSON(b) 1105 if err != nil { 1106 return nil, errors.Trace(err) 1107 } 1108 chk.AppendJSON(defCausIdx, json.BinaryJSON{TypeCode: b[0], Value: b[1:size]}) 1109 b = b[size:] 1110 case NilFlag: 1111 chk.AppendNull(defCausIdx) 1112 default: 1113 return nil, errors.Errorf("invalid encoded key flag %v", flag) 1114 } 1115 if err != nil { 1116 return nil, errors.Trace(err) 1117 } 1118 return b, nil 1119 } 1120 1121 func appendIntToChunk(val int64, chk *chunk.Chunk, defCausIdx int, ft *types.FieldType) { 1122 switch ft.Tp { 1123 case allegrosql.TypeDuration: 1124 v := types.Duration{Duration: time.Duration(val), Fsp: int8(ft.Decimal)} 1125 chk.AppendDuration(defCausIdx, v) 1126 default: 1127 chk.AppendInt64(defCausIdx, val) 1128 } 1129 } 1130 1131 func appendUintToChunk(val uint64, chk *chunk.Chunk, defCausIdx int, ft *types.FieldType, loc *time.Location) error { 1132 switch ft.Tp { 1133 case allegrosql.TypeDate, allegrosql.TypeDatetime, allegrosql.TypeTimestamp: 1134 t := types.NewTime(types.ZeroCoreTime, ft.Tp, int8(ft.Decimal)) 1135 var err error 1136 err = t.FromPackedUint(val) 1137 if err != nil { 1138 return errors.Trace(err) 1139 } 1140 if ft.Tp == allegrosql.TypeTimestamp && !t.IsZero() { 1141 err = t.ConvertTimeZone(time.UTC, loc) 1142 if err != nil { 1143 return errors.Trace(err) 1144 } 1145 } 1146 chk.AppendTime(defCausIdx, t) 1147 case allegrosql.TypeEnum: 1148 // ignore error deliberately, to read empty enum value. 1149 enum, err := types.ParseEnumValue(ft.Elems, val) 1150 if err != nil { 1151 enum = types.Enum{} 1152 } 1153 chk.AppendEnum(defCausIdx, enum) 1154 case allegrosql.TypeSet: 1155 set, err := types.ParseSetValue(ft.Elems, val) 1156 if err != nil { 1157 return errors.Trace(err) 1158 } 1159 chk.AppendSet(defCausIdx, set) 1160 case allegrosql.TypeBit: 1161 byteSize := (ft.Flen + 7) >> 3 1162 chk.AppendBytes(defCausIdx, types.NewBinaryLiteralFromUint(val, byteSize)) 1163 default: 1164 chk.AppendUint64(defCausIdx, val) 1165 } 1166 return nil 1167 } 1168 1169 func appendFloatToChunk(val float64, chk *chunk.Chunk, defCausIdx int, ft *types.FieldType) { 1170 if ft.Tp == allegrosql.TypeFloat { 1171 chk.AppendFloat32(defCausIdx, float32(val)) 1172 } else { 1173 chk.AppendFloat64(defCausIdx, val) 1174 } 1175 } 1176 1177 // HashGroupKey encodes each event of this defCausumn and append encoded data into buf. 1178 // Only use in the aggregate interlock. 1179 func HashGroupKey(sc *stmtctx.StatementContext, n int, defCaus *chunk.DeferredCauset, buf [][]byte, ft *types.FieldType) ([][]byte, error) { 1180 var err error 1181 switch ft.EvalType() { 1182 case types.ETInt: 1183 i64s := defCaus.Int64s() 1184 for i := 0; i < n; i++ { 1185 if defCaus.IsNull(i) { 1186 buf[i] = append(buf[i], NilFlag) 1187 } else { 1188 buf[i] = encodeSignedInt(buf[i], i64s[i], false) 1189 } 1190 } 1191 case types.ETReal: 1192 f64s := defCaus.Float64s() 1193 for i := 0; i < n; i++ { 1194 if defCaus.IsNull(i) { 1195 buf[i] = append(buf[i], NilFlag) 1196 } else { 1197 buf[i] = append(buf[i], floatFlag) 1198 buf[i] = EncodeFloat(buf[i], f64s[i]) 1199 } 1200 } 1201 case types.ETDecimal: 1202 ds := defCaus.Decimals() 1203 for i := 0; i < n; i++ { 1204 if defCaus.IsNull(i) { 1205 buf[i] = append(buf[i], NilFlag) 1206 } else { 1207 buf[i] = append(buf[i], decimalFlag) 1208 buf[i], err = EncodeDecimal(buf[i], &ds[i], ft.Flen, ft.Decimal) 1209 if terror.ErrorEqual(err, types.ErrTruncated) { 1210 err = sc.HandleTruncate(err) 1211 } else if terror.ErrorEqual(err, types.ErrOverflow) { 1212 err = sc.HandleOverflow(err, err) 1213 } 1214 if err != nil { 1215 return nil, err 1216 } 1217 } 1218 } 1219 case types.ETDatetime, types.ETTimestamp: 1220 ts := defCaus.Times() 1221 for i := 0; i < n; i++ { 1222 if defCaus.IsNull(i) { 1223 buf[i] = append(buf[i], NilFlag) 1224 } else { 1225 buf[i] = append(buf[i], uintFlag) 1226 buf[i], err = EncodeMyALLEGROSQLTime(sc, ts[i], allegrosql.TypeUnspecified, buf[i]) 1227 if err != nil { 1228 return nil, err 1229 } 1230 } 1231 } 1232 case types.ETDuration: 1233 ds := defCaus.GoDurations() 1234 for i := 0; i < n; i++ { 1235 if defCaus.IsNull(i) { 1236 buf[i] = append(buf[i], NilFlag) 1237 } else { 1238 buf[i] = append(buf[i], durationFlag) 1239 buf[i] = EncodeInt(buf[i], int64(ds[i])) 1240 } 1241 } 1242 case types.ETJson: 1243 for i := 0; i < n; i++ { 1244 if defCaus.IsNull(i) { 1245 buf[i] = append(buf[i], NilFlag) 1246 } else { 1247 buf[i] = append(buf[i], jsonFlag) 1248 j := defCaus.GetJSON(i) 1249 buf[i] = append(buf[i], j.TypeCode) 1250 buf[i] = append(buf[i], j.Value...) 1251 } 1252 } 1253 case types.ETString: 1254 for i := 0; i < n; i++ { 1255 if defCaus.IsNull(i) { 1256 buf[i] = append(buf[i], NilFlag) 1257 } else { 1258 buf[i] = encodeBytes(buf[i], ConvertByDefCauslation(defCaus.GetBytes(i), ft), false) 1259 } 1260 } 1261 default: 1262 return nil, errors.New(fmt.Sprintf("invalid eval type %v", ft.EvalType())) 1263 } 1264 return buf, nil 1265 } 1266 1267 // ConvertByDefCauslation converts these bytes according to its defCauslation. 1268 func ConvertByDefCauslation(raw []byte, tp *types.FieldType) []byte { 1269 defCauslator := defCauslate.GetDefCauslator(tp.DefCauslate) 1270 return defCauslator.Key(string(replog.String(raw))) 1271 } 1272 1273 // ConvertByDefCauslationStr converts this string according to its defCauslation. 1274 func ConvertByDefCauslationStr(str string, tp *types.FieldType) string { 1275 defCauslator := defCauslate.GetDefCauslator(tp.DefCauslate) 1276 return string(replog.String(defCauslator.Key(str))) 1277 }