github.com/nakagami/firebirdsql@v0.9.10/xsqlvar.go (about) 1 /******************************************************************************* 2 The MIT License (MIT) 3 4 Copyright (c) 2013-2020 Hajime Nakagami 5 6 Permission is hereby granted, free of charge, to any person obtaining a copy of 7 this software and associated documentation files (the "Software"), to deal in 8 the Software without restriction, including without limitation the rights to 9 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 10 the Software, and to permit persons to whom the Software is furnished to do so, 11 subject to the following conditions: 12 13 The above copyright notice and this permission notice shall be included in all 14 copies or substantial portions of the Software. 15 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 *******************************************************************************/ 23 24 package firebirdsql 25 26 import ( 27 "bytes" 28 "encoding/binary" 29 "github.com/shopspring/decimal" 30 "golang.org/x/text/encoding/charmap" 31 "golang.org/x/text/encoding/japanese" 32 "golang.org/x/text/encoding/korean" 33 "golang.org/x/text/encoding/simplifiedchinese" 34 "golang.org/x/text/encoding/traditionalchinese" 35 "math" 36 "math/big" 37 "reflect" 38 "strings" 39 "time" 40 ) 41 42 const ( 43 SQL_TYPE_TEXT = 452 44 SQL_TYPE_VARYING = 448 45 SQL_TYPE_SHORT = 500 46 SQL_TYPE_LONG = 496 47 SQL_TYPE_FLOAT = 482 48 SQL_TYPE_DOUBLE = 480 49 SQL_TYPE_D_FLOAT = 530 50 SQL_TYPE_TIMESTAMP = 510 51 SQL_TYPE_BLOB = 520 52 SQL_TYPE_ARRAY = 540 53 SQL_TYPE_QUAD = 550 54 SQL_TYPE_TIME = 560 55 SQL_TYPE_DATE = 570 56 SQL_TYPE_INT64 = 580 57 SQL_TYPE_INT128 = 32752 58 SQL_TYPE_TIMESTAMP_TZ = 32754 59 SQL_TYPE_TIME_TZ = 32756 60 SQL_TYPE_DEC_FIXED = 32758 61 SQL_TYPE_DEC64 = 32760 62 SQL_TYPE_DEC128 = 32762 63 SQL_TYPE_BOOLEAN = 32764 64 SQL_TYPE_NULL = 32766 65 ) 66 67 var xsqlvarTypeLength = map[int]int{ 68 SQL_TYPE_TEXT: -1, 69 SQL_TYPE_VARYING: -1, 70 SQL_TYPE_SHORT: 4, 71 SQL_TYPE_LONG: 4, 72 SQL_TYPE_FLOAT: 4, 73 SQL_TYPE_TIME: 4, 74 SQL_TYPE_DATE: 4, 75 SQL_TYPE_DOUBLE: 8, 76 SQL_TYPE_TIMESTAMP: 8, 77 SQL_TYPE_BLOB: 8, 78 SQL_TYPE_ARRAY: 8, 79 SQL_TYPE_QUAD: 8, 80 SQL_TYPE_INT64: 8, 81 SQL_TYPE_INT128: 16, 82 SQL_TYPE_TIMESTAMP_TZ: 10, 83 SQL_TYPE_TIME_TZ: 6, 84 SQL_TYPE_DEC64: 8, 85 SQL_TYPE_DEC128: 16, 86 SQL_TYPE_DEC_FIXED: 16, 87 SQL_TYPE_BOOLEAN: 1, 88 } 89 90 var xsqlvarTypeDisplayLength = map[int]int{ 91 SQL_TYPE_TEXT: -1, 92 SQL_TYPE_VARYING: -1, 93 SQL_TYPE_SHORT: 6, 94 SQL_TYPE_LONG: 11, 95 SQL_TYPE_FLOAT: 17, 96 SQL_TYPE_TIME: 11, 97 SQL_TYPE_DATE: 10, 98 SQL_TYPE_DOUBLE: 17, 99 SQL_TYPE_TIMESTAMP: 22, 100 SQL_TYPE_BLOB: 0, 101 SQL_TYPE_ARRAY: -1, 102 SQL_TYPE_QUAD: 20, 103 SQL_TYPE_INT64: 20, 104 SQL_TYPE_INT128: 20, 105 SQL_TYPE_TIMESTAMP_TZ: 28, 106 SQL_TYPE_TIME_TZ: 17, 107 SQL_TYPE_DEC64: 16, 108 SQL_TYPE_DEC128: 34, 109 SQL_TYPE_DEC_FIXED: 34, 110 SQL_TYPE_BOOLEAN: 5, 111 } 112 113 var xsqlvarTypeName = map[int]string{ 114 SQL_TYPE_TEXT: "TEXT", 115 SQL_TYPE_VARYING: "VARYING", 116 SQL_TYPE_SHORT: "SHORT", 117 SQL_TYPE_LONG: "LONG", 118 SQL_TYPE_FLOAT: "FLOAT", 119 SQL_TYPE_TIME: "TIME", 120 SQL_TYPE_DATE: "DATE", 121 SQL_TYPE_DOUBLE: "DOUBLE", 122 SQL_TYPE_TIMESTAMP: "TIMESTAMP", 123 SQL_TYPE_BLOB: "BLOB", 124 SQL_TYPE_ARRAY: "ARRAY", 125 SQL_TYPE_QUAD: "QUAD", 126 SQL_TYPE_INT64: "INT64", 127 SQL_TYPE_INT128: "INT128", 128 SQL_TYPE_TIMESTAMP_TZ: "TIMESTAMP WITH TIMEZONE", 129 SQL_TYPE_TIME_TZ: "TIME WITH TIMEZONE", 130 SQL_TYPE_DEC64: "DECFLOAT(16)", 131 SQL_TYPE_DEC128: "DECFLOAT(34)", 132 SQL_TYPE_DEC_FIXED: "DECFIXED", 133 SQL_TYPE_BOOLEAN: "BOOLEAN", 134 } 135 136 type xSQLVAR struct { 137 sqltype int 138 sqlscale int 139 sqlsubtype int 140 sqllen int 141 null_ok bool 142 fieldname string 143 relname string 144 ownname string 145 aliasname string 146 } 147 148 func (x *xSQLVAR) ioLength() int { 149 if x.sqltype == SQL_TYPE_TEXT { 150 return x.sqllen 151 } 152 return xsqlvarTypeLength[x.sqltype] 153 } 154 155 func (x *xSQLVAR) displayLength() int { 156 if x.sqltype == SQL_TYPE_TEXT || x.sqltype == SQL_TYPE_VARYING { 157 return x.sqllen 158 } 159 return xsqlvarTypeDisplayLength[x.sqltype] 160 } 161 162 func (x *xSQLVAR) hasPrecisionScale() bool { 163 return (x.sqltype == SQL_TYPE_SHORT || x.sqltype == SQL_TYPE_LONG || x.sqltype == SQL_TYPE_QUAD || x.sqltype == SQL_TYPE_INT64 || x.sqltype == SQL_TYPE_INT128 || x.sqltype == SQL_TYPE_DEC64 || x.sqltype == SQL_TYPE_DEC128 || x.sqltype == SQL_TYPE_DEC_FIXED) && x.sqlscale != 0 164 } 165 166 func (x *xSQLVAR) typename() string { 167 return xsqlvarTypeName[x.sqltype] 168 } 169 170 func (x *xSQLVAR) scantype() reflect.Type { 171 switch x.sqltype { 172 case SQL_TYPE_TEXT: 173 return reflect.TypeOf("") 174 case SQL_TYPE_VARYING: 175 return reflect.TypeOf("") 176 case SQL_TYPE_SHORT: 177 if x.sqlscale != 0 { 178 return reflect.TypeOf(decimal.Decimal{}) 179 } 180 return reflect.TypeOf(int16(0)) 181 case SQL_TYPE_LONG: 182 if x.sqlscale != 0 { 183 return reflect.TypeOf(decimal.Decimal{}) 184 } 185 return reflect.TypeOf(int32(0)) 186 case SQL_TYPE_INT64: 187 if x.sqlscale != 0 { 188 return reflect.TypeOf(decimal.Decimal{}) 189 } 190 return reflect.TypeOf(int64(0)) 191 case SQL_TYPE_INT128: 192 return reflect.TypeOf(big.Int{}) 193 case SQL_TYPE_DATE: 194 return reflect.TypeOf(time.Time{}) 195 case SQL_TYPE_TIME: 196 return reflect.TypeOf(time.Time{}) 197 case SQL_TYPE_TIMESTAMP: 198 return reflect.TypeOf(time.Time{}) 199 case SQL_TYPE_FLOAT: 200 return reflect.TypeOf(float32(0)) 201 case SQL_TYPE_DOUBLE: 202 return reflect.TypeOf(float64(0)) 203 case SQL_TYPE_BOOLEAN: 204 return reflect.TypeOf(false) 205 case SQL_TYPE_BLOB: 206 return reflect.TypeOf([]byte{}) 207 case SQL_TYPE_TIMESTAMP_TZ: 208 return reflect.TypeOf(time.Time{}) 209 case SQL_TYPE_TIME_TZ: 210 return reflect.TypeOf(time.Time{}) 211 case SQL_TYPE_DEC64: 212 return reflect.TypeOf(decimal.Decimal{}) 213 case SQL_TYPE_DEC128: 214 return reflect.TypeOf(decimal.Decimal{}) 215 case SQL_TYPE_DEC_FIXED: 216 return reflect.TypeOf(decimal.Decimal{}) 217 } 218 return reflect.TypeOf(nil) 219 } 220 221 func (x *xSQLVAR) _parseTimezone(raw_value []byte) *time.Location { 222 timezone := getTimezoneNameByID(int(bytes_to_buint16(raw_value))) 223 tz, _ := time.LoadLocation(timezone) 224 return tz 225 } 226 227 func (x *xSQLVAR) _parseDate(raw_value []byte) (int, int, int) { 228 nday := int(bytes_to_bint32(raw_value)) + 678882 229 century := (4*nday - 1) / 146097 230 nday = 4*nday - 1 - 146097*century 231 day := nday / 4 232 233 nday = (4*day + 3) / 1461 234 day = 4*day + 3 - 1461*nday 235 day = (day + 4) / 4 236 237 month := (5*day - 3) / 153 238 day = 5*day - 3 - 153*month 239 day = (day + 5) / 5 240 year := 100*century + nday 241 if month < 10 { 242 month += 3 243 } else { 244 month -= 9 245 year++ 246 } 247 return year, month, day 248 } 249 250 func (x *xSQLVAR) _parseTime(raw_value []byte) (int, int, int, int) { 251 n := int(bytes_to_bint32(raw_value)) 252 s := n / 10000 253 m := s / 60 254 h := m / 60 255 m = m % 60 256 s = s % 60 257 return h, m, s, (n % 10000) * 100000 258 } 259 260 func (x *xSQLVAR) parseDate(raw_value []byte, timezone string) time.Time { 261 tz := time.Local 262 if timezone != "" { 263 tz, _ = time.LoadLocation(timezone) 264 } 265 year, month, day := x._parseDate(raw_value) 266 return time.Date(year, time.Month(month), day, 0, 0, 0, 0, tz) 267 } 268 269 func (x *xSQLVAR) parseTime(raw_value []byte, timezone string) time.Time { 270 tz := time.Local 271 if timezone != "" { 272 tz, _ = time.LoadLocation(timezone) 273 } 274 h, m, s, n := x._parseTime(raw_value) 275 now := time.Now() 276 zone, offset := time.Date(now.Year(), now.Month(), now.Day(), h, m, s, n, tz).Zone() 277 return time.Date(0, time.Month(1), 1, h, m, s, n, time.FixedZone(zone, offset)) 278 } 279 280 func (x *xSQLVAR) parseTimestamp(raw_value []byte, timezone string) time.Time { 281 tz := time.Local 282 if timezone != "" { 283 tz, _ = time.LoadLocation(timezone) 284 } 285 286 year, month, day := x._parseDate(raw_value[:4]) 287 h, m, s, n := x._parseTime(raw_value[4:8]) 288 return time.Date(year, time.Month(month), day, h, m, s, n, tz) 289 } 290 291 func (x *xSQLVAR) parseTimeTz(raw_value []byte) time.Time { 292 h, m, s, n := x._parseTime(raw_value[:4]) 293 tz := x._parseTimezone(raw_value[4:6]) 294 loc := x._parseTimezone(raw_value[6:8]) 295 now := time.Now() 296 t := time.Date(now.Year(), now.Month(), now.Day(), h, m, s, n, tz).In(loc) 297 zone, offset := t.Zone() 298 return time.Date(0, time.Month(1), 1, t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), time.FixedZone(zone, offset)) 299 } 300 301 func (x *xSQLVAR) parseTimestampTz(raw_value []byte) time.Time { 302 year, month, day := x._parseDate(raw_value[:4]) 303 h, m, s, n := x._parseTime(raw_value[4:8]) 304 tz := x._parseTimezone(raw_value[8:10]) 305 offset := x._parseTimezone(raw_value[10:12]) 306 return time.Date(year, time.Month(month), day, h, m, s, n, tz).In(offset) 307 } 308 309 func (x *xSQLVAR) parseString(raw_value []byte, charset string) interface{} { 310 if x.sqlsubtype == 1 { // OCTETS 311 return raw_value 312 } 313 switch charset { 314 case "OCTETS": 315 return raw_value 316 case "UNICODE_FSS", "UTF8": 317 return bytes.NewBuffer(raw_value).String() 318 case "SJIS_0208": 319 dec := japanese.ShiftJIS.NewDecoder() 320 v, _ := dec.Bytes(raw_value) 321 return string(v) 322 case "EUCJ_0208": 323 dec := japanese.EUCJP.NewDecoder() 324 v, _ := dec.Bytes(raw_value) 325 return string(v) 326 case "ISO8859_1": 327 dec := charmap.ISO8859_1.NewDecoder() 328 v, _ := dec.Bytes(raw_value) 329 return string(v) 330 case "ISO8859_2": 331 dec := charmap.ISO8859_2.NewDecoder() 332 v, _ := dec.Bytes(raw_value) 333 return string(v) 334 case "ISO8859_3": 335 dec := charmap.ISO8859_3.NewDecoder() 336 v, _ := dec.Bytes(raw_value) 337 return string(v) 338 case "ISO8859_4": 339 dec := charmap.ISO8859_5.NewDecoder() 340 v, _ := dec.Bytes(raw_value) 341 return string(v) 342 case "ISO8859_5": 343 dec := charmap.ISO8859_5.NewDecoder() 344 v, _ := dec.Bytes(raw_value) 345 return string(v) 346 case "ISO8859_6": 347 dec := charmap.ISO8859_6.NewDecoder() 348 v, _ := dec.Bytes(raw_value) 349 return string(v) 350 case "ISO8859_7": 351 dec := charmap.ISO8859_7.NewDecoder() 352 v, _ := dec.Bytes(raw_value) 353 return string(v) 354 case "ISO8859_8": 355 dec := charmap.ISO8859_8.NewDecoder() 356 v, _ := dec.Bytes(raw_value) 357 return string(v) 358 case "ISO8859_9": 359 dec := charmap.ISO8859_9.NewDecoder() 360 v, _ := dec.Bytes(raw_value) 361 return string(v) 362 case "ISO8859_13": 363 dec := charmap.ISO8859_13.NewDecoder() 364 v, _ := dec.Bytes(raw_value) 365 return string(v) 366 case "KSC_5601": 367 dec := korean.EUCKR.NewDecoder() 368 v, _ := dec.Bytes(raw_value) 369 return string(v) 370 case "WIN1250": 371 dec := charmap.Windows1250.NewDecoder() 372 v, _ := dec.Bytes(raw_value) 373 return string(v) 374 case "WIN1251": 375 dec := charmap.Windows1251.NewDecoder() 376 v, _ := dec.Bytes(raw_value) 377 return string(v) 378 case "WIN1252": 379 dec := charmap.Windows1252.NewDecoder() 380 v, _ := dec.Bytes(raw_value) 381 return string(v) 382 case "WIN1253": 383 dec := charmap.Windows1252.NewDecoder() 384 v, _ := dec.Bytes(raw_value) 385 return string(v) 386 case "WIN1254": 387 dec := charmap.Windows1252.NewDecoder() 388 v, _ := dec.Bytes(raw_value) 389 return string(v) 390 case "BIG_5": 391 dec := traditionalchinese.Big5.NewDecoder() 392 v, _ := dec.Bytes(raw_value) 393 return string(v) 394 case "GB_2312": 395 dec := simplifiedchinese.HZGB2312.NewDecoder() 396 v, _ := dec.Bytes(raw_value) 397 return string(v) 398 case "WIN1255": 399 dec := charmap.Windows1255.NewDecoder() 400 v, _ := dec.Bytes(raw_value) 401 return string(v) 402 case "WIN1256": 403 dec := charmap.Windows1256.NewDecoder() 404 v, _ := dec.Bytes(raw_value) 405 return string(v) 406 case "WIN1257": 407 dec := charmap.Windows1257.NewDecoder() 408 v, _ := dec.Bytes(raw_value) 409 return string(v) 410 case "KOI8R": 411 dec := charmap.KOI8R.NewDecoder() 412 v, _ := dec.Bytes(raw_value) 413 return string(v) 414 case "KOI8U": 415 dec := charmap.KOI8U.NewDecoder() 416 v, _ := dec.Bytes(raw_value) 417 return string(v) 418 case "WIN1258": 419 dec := charmap.Windows1258.NewDecoder() 420 v, _ := dec.Bytes(raw_value) 421 return string(v) 422 default: 423 return raw_value 424 } 425 } 426 427 func (x *xSQLVAR) value(raw_value []byte, timezone string, charset string) (v interface{}, err error) { 428 switch x.sqltype { 429 case SQL_TYPE_TEXT: 430 if x.sqlsubtype == 1 || charset == "None" { // OCTETS 431 v = raw_value 432 } else { 433 v = x.parseString(raw_value, charset) 434 switch v.(type) { 435 case string: 436 v = strings.TrimRight(v.(string), " ") 437 case []uint8: 438 v = strings.TrimRight(string(v.([]uint8)), " ") 439 } 440 } 441 case SQL_TYPE_VARYING: 442 if x.sqlsubtype == 1 { // OCTETS 443 v = raw_value 444 } else { 445 v = x.parseString(raw_value, charset) 446 } 447 case SQL_TYPE_SHORT: 448 i16 := int16(bytes_to_bint32(raw_value)) 449 if x.sqlscale > 0 { 450 v = int64(i16) * int64(math.Pow10(x.sqlscale)) 451 } else if x.sqlscale < 0 { 452 v = decimal.New(int64(i16), int32(x.sqlscale)) 453 } else { 454 v = i16 455 } 456 case SQL_TYPE_LONG: 457 i32 := bytes_to_bint32(raw_value) 458 if x.sqlscale > 0 { 459 v = int64(i32) * int64(math.Pow10(x.sqlscale)) 460 } else if x.sqlscale < 0 { 461 v = decimal.New(int64(i32), int32(x.sqlscale)) 462 } else { 463 v = i32 464 } 465 case SQL_TYPE_INT64: 466 i64 := bytes_to_bint64(raw_value) 467 if x.sqlscale > 0 { 468 v = i64 * int64(math.Pow10(x.sqlscale)) 469 } else if x.sqlscale < 0 { 470 v = decimal.New(int64(i64), int32(x.sqlscale)) 471 } else { 472 v = i64 473 } 474 case SQL_TYPE_INT128: 475 var isNegative bool 476 477 // when raw_value[0] is > 127, then subtract 255 in every index 478 if raw_value[0] > 127 { 479 for i := range raw_value { 480 if raw_value[i] < 255 { 481 raw_value[i] = 255 - raw_value[i] 482 } else { 483 raw_value[i] -= 255 484 } 485 } 486 isNegative = true 487 } 488 489 // reverse 490 for i, j := 0, len(raw_value)-1; i < j; i, j = i+1, j-1 { 491 raw_value[i], raw_value[j] = raw_value[j], raw_value[i] 492 } 493 494 // variable to return 495 var x = new(big.Int) 496 497 for i := len(raw_value) - 1; i >= 0; i-- { 498 if raw_value[i] == 0 { 499 continue 500 } 501 502 // get the 2^(i*8) in big.Float 503 var t = new(big.Float).SetFloat64(math.Pow(2, float64(i*8))) 504 505 // convert the float to int 506 var xx *big.Int 507 xx, _ = t.Int(xx) 508 509 // mul with the value in raw_value 510 xx.Mul(xx, big.NewInt(int64(raw_value[i]))) 511 512 // add to x 513 x.Add(x, xx) 514 } 515 516 // when negative, add 1 and mul -1 517 if isNegative { 518 x.Add(x, big.NewInt(1)) 519 x.Mul(x, big.NewInt(-1)) 520 } 521 v = x 522 case SQL_TYPE_DATE: 523 v = x.parseDate(raw_value, timezone) 524 case SQL_TYPE_TIME: 525 v = x.parseTime(raw_value, timezone) 526 case SQL_TYPE_TIMESTAMP: 527 v = x.parseTimestamp(raw_value, timezone) 528 case SQL_TYPE_TIME_TZ: 529 v = x.parseTimeTz(raw_value) 530 case SQL_TYPE_TIMESTAMP_TZ: 531 v = x.parseTimestampTz(raw_value) 532 case SQL_TYPE_FLOAT: 533 var f32 float32 534 b := bytes.NewReader(raw_value) 535 err = binary.Read(b, binary.BigEndian, &f32) 536 v = f32 537 case SQL_TYPE_DOUBLE: 538 b := bytes.NewReader(raw_value) 539 var f64 float64 540 err = binary.Read(b, binary.BigEndian, &f64) 541 v = f64 542 case SQL_TYPE_BOOLEAN: 543 v = raw_value[0] != 0 544 case SQL_TYPE_BLOB: 545 v = raw_value 546 case SQL_TYPE_DEC_FIXED: 547 v = decimalFixedToDecimal(raw_value, int32(x.sqlscale)) 548 case SQL_TYPE_DEC64: 549 v = decimal64ToDecimal(raw_value) 550 case SQL_TYPE_DEC128: 551 v = decimal128ToDecimal(raw_value) 552 } 553 return 554 } 555 556 func calcBlr(xsqlda []xSQLVAR) []byte { 557 // Calculate BLR from XSQLVAR array. 558 ln := len(xsqlda) * 2 559 blr := make([]byte, (ln*4)+8) 560 blr[0] = 5 561 blr[1] = 2 562 blr[2] = 4 563 blr[3] = 0 564 blr[4] = byte(ln & 255) 565 blr[5] = byte(ln >> 8) 566 n := 6 567 568 for _, x := range xsqlda { 569 sqlscale := x.sqlscale 570 if sqlscale < 0 { 571 sqlscale += 256 572 } 573 switch x.sqltype { 574 case SQL_TYPE_VARYING: 575 blr[n] = 37 576 blr[n+1] = byte(x.sqllen & 255) 577 blr[n+2] = byte(x.sqllen >> 8) 578 n += 3 579 case SQL_TYPE_TEXT: 580 blr[n] = 14 581 blr[n+1] = byte(x.sqllen & 255) 582 blr[n+2] = byte(x.sqllen >> 8) 583 n += 3 584 case SQL_TYPE_LONG: 585 blr[n] = 8 586 blr[n+1] = byte(sqlscale) 587 n += 2 588 case SQL_TYPE_SHORT: 589 blr[n] = 7 590 blr[n+1] = byte(sqlscale) 591 n += 2 592 case SQL_TYPE_INT64: 593 blr[n] = 16 594 blr[n+1] = byte(sqlscale) 595 n += 2 596 case SQL_TYPE_INT128: 597 blr[n] = 26 598 blr[n+1] = byte(sqlscale) 599 n += 2 600 case SQL_TYPE_QUAD: 601 blr[n] = 9 602 blr[n+1] = byte(sqlscale) 603 n += 2 604 case SQL_TYPE_DEC_FIXED: // OBSOLATED 605 blr[n] = 26 606 blr[n+1] = byte(sqlscale) 607 n += 2 608 case SQL_TYPE_DOUBLE: 609 blr[n] = 27 610 n++ 611 case SQL_TYPE_FLOAT: 612 blr[n] = 10 613 n++ 614 case SQL_TYPE_D_FLOAT: 615 blr[n] = 11 616 n++ 617 case SQL_TYPE_DATE: 618 blr[n] = 12 619 n++ 620 case SQL_TYPE_TIME: 621 blr[n] = 13 622 n++ 623 case SQL_TYPE_TIMESTAMP: 624 blr[n] = 35 625 n++ 626 case SQL_TYPE_BLOB: 627 blr[n] = 9 628 blr[n+1] = 0 629 n += 2 630 case SQL_TYPE_ARRAY: 631 blr[n] = 9 632 blr[n+1] = 0 633 n += 2 634 case SQL_TYPE_BOOLEAN: 635 blr[n] = 23 636 n++ 637 case SQL_TYPE_DEC64: 638 blr[n] = 24 639 n++ 640 case SQL_TYPE_DEC128: 641 blr[n] = 25 642 n++ 643 case SQL_TYPE_TIME_TZ: 644 blr[n] = 28 645 n++ 646 case SQL_TYPE_TIMESTAMP_TZ: 647 blr[n] = 29 648 n++ 649 } 650 // [blr_short, 0] 651 blr[n] = 7 652 blr[n+1] = 0 653 n += 2 654 } 655 // [blr_end, blr_eoc] 656 blr[n] = 255 657 blr[n+1] = 76 658 n += 2 659 660 return blr[:n] 661 }