1/* 2Copyright 2014 SAP SE 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15*/ 16 17package protocol 18 19import ( 20 "database/sql/driver" 21 "fmt" 22 "math" 23 "sort" 24 "time" 25 26 "github.com/SAP/go-hdb/internal/bufio" 27 "github.com/SAP/go-hdb/internal/unicode/cesu8" 28) 29 30var test uint32 31 32const ( 33 realNullValue uint32 = ^uint32(0) 34 doubleNullValue uint64 = ^uint64(0) 35) 36 37const noFieldName uint32 = 0xFFFFFFFF 38 39type uint32Slice []uint32 40 41func (p uint32Slice) Len() int { return len(p) } 42func (p uint32Slice) Less(i, j int) bool { return p[i] < p[j] } 43func (p uint32Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } 44func (p uint32Slice) sort() { sort.Sort(p) } 45 46type fieldNames map[uint32]string 47 48func newFieldNames() fieldNames { 49 return make(map[uint32]string) 50} 51 52func (f fieldNames) addOffset(offset uint32) { 53 if offset != noFieldName { 54 f[offset] = "" 55 } 56} 57 58func (f fieldNames) name(offset uint32) string { 59 if name, ok := f[offset]; ok { 60 return name 61 } 62 return "" 63} 64 65func (f fieldNames) setName(offset uint32, name string) { 66 f[offset] = name 67} 68 69func (f fieldNames) sortOffsets() []uint32 { 70 offsets := make([]uint32, 0, len(f)) 71 for k := range f { 72 offsets = append(offsets, k) 73 } 74 uint32Slice(offsets).sort() 75 return offsets 76} 77 78// FieldValues contains rows read from database. 79type FieldValues struct { 80 rows int 81 cols int 82 values []driver.Value 83} 84 85func newFieldValues() *FieldValues { 86 return &FieldValues{} 87} 88 89func (f *FieldValues) String() string { 90 return fmt.Sprintf("rows %d columns %d", f.rows, f.cols) 91} 92 93func (f *FieldValues) resize(rows, cols int) { 94 f.rows, f.cols = rows, cols 95 f.values = make([]driver.Value, rows*cols) 96} 97 98// NumRow returns the number of rows available in FieldValues. 99func (f *FieldValues) NumRow() int { 100 return f.rows 101} 102 103// Row fills the dest value slice with row data at index idx. 104func (f *FieldValues) Row(idx int, dest []driver.Value) { 105 copy(dest, f.values[idx*f.cols:(idx+1)*f.cols]) 106} 107 108const ( 109 tinyintFieldSize = 1 110 smallintFieldSize = 2 111 intFieldSize = 4 112 bigintFieldSize = 8 113 realFieldSize = 4 114 doubleFieldSize = 8 115 dateFieldSize = 4 116 timeFieldSize = 4 117 timestampFieldSize = dateFieldSize + timeFieldSize 118 longdateFieldSize = 8 119 seconddateFieldSize = 8 120 daydateFieldSize = 4 121 secondtimeFieldSize = 4 122 decimalFieldSize = 16 123 lobInputDescriptorSize = 9 124) 125 126func fieldSize(tc TypeCode, arg driver.NamedValue) (int, error) { 127 v := arg.Value 128 129 if v == nil { //HDB bug: secondtime null value --> see writeField 130 return 0, nil 131 } 132 133 switch tc { 134 case tcTinyint: 135 return tinyintFieldSize, nil 136 case tcSmallint: 137 return smallintFieldSize, nil 138 case tcInteger: 139 return intFieldSize, nil 140 case tcBigint: 141 return bigintFieldSize, nil 142 case tcReal: 143 return realFieldSize, nil 144 case tcDouble: 145 return doubleFieldSize, nil 146 case tcDate: 147 return dateFieldSize, nil 148 case tcTime: 149 return timeFieldSize, nil 150 case tcTimestamp: 151 return timestampFieldSize, nil 152 case tcLongdate: 153 return longdateFieldSize, nil 154 case tcSeconddate: 155 return seconddateFieldSize, nil 156 case tcDaydate: 157 return daydateFieldSize, nil 158 case tcSecondtime: 159 return secondtimeFieldSize, nil 160 case tcDecimal: 161 return decimalFieldSize, nil 162 case tcChar, tcVarchar, tcString: 163 switch v := v.(type) { 164 case []byte: 165 return bytesSize(len(v)) 166 case string: 167 return bytesSize(len(v)) 168 default: 169 outLogger.Fatalf("data type %s mismatch %T", tc, v) 170 } 171 case tcNchar, tcNvarchar, tcNstring: 172 switch v := v.(type) { 173 case []byte: 174 return bytesSize(cesu8.Size(v)) 175 case string: 176 return bytesSize(cesu8.StringSize(v)) 177 default: 178 outLogger.Fatalf("data type %s mismatch %T", tc, v) 179 } 180 case tcBinary, tcVarbinary: 181 v, ok := v.([]byte) 182 if !ok { 183 outLogger.Fatalf("data type %s mismatch %T", tc, v) 184 } 185 return bytesSize(len(v)) 186 case tcBlob, tcClob, tcNclob: 187 return lobInputDescriptorSize, nil 188 } 189 outLogger.Fatalf("data type %s not implemented", tc) 190 return 0, nil 191} 192 193func readField(session *Session, rd *bufio.Reader, tc TypeCode) (interface{}, error) { 194 195 switch tc { 196 197 case tcTinyint, tcSmallint, tcInteger, tcBigint: 198 199 if !rd.ReadBool() { //null value 200 return nil, nil 201 } 202 203 switch tc { 204 case tcTinyint: 205 return int64(rd.ReadB()), nil 206 case tcSmallint: 207 return int64(rd.ReadInt16()), nil 208 case tcInteger: 209 return int64(rd.ReadInt32()), nil 210 case tcBigint: 211 return rd.ReadInt64(), nil 212 } 213 214 case tcReal: 215 v := rd.ReadUint32() 216 if v == realNullValue { 217 return nil, nil 218 } 219 return float64(math.Float32frombits(v)), nil 220 221 case tcDouble: 222 v := rd.ReadUint64() 223 if v == doubleNullValue { 224 return nil, nil 225 } 226 return math.Float64frombits(v), nil 227 228 case tcDate: 229 year, month, day, null := readDate(rd) 230 if null { 231 return nil, nil 232 } 233 return time.Date(year, month, day, 0, 0, 0, 0, time.UTC), nil 234 235 // time read gives only seconds (cut), no milliseconds 236 case tcTime: 237 hour, minute, nanosecs, null := readTime(rd) 238 if null { 239 return nil, nil 240 } 241 return time.Date(1, 1, 1, hour, minute, 0, nanosecs, time.UTC), nil 242 243 case tcTimestamp: 244 year, month, day, dateNull := readDate(rd) 245 hour, minute, nanosecs, timeNull := readTime(rd) 246 if dateNull || timeNull { 247 return nil, nil 248 } 249 return time.Date(year, month, day, hour, minute, 0, nanosecs, time.UTC), nil 250 251 case tcLongdate: 252 time, null := readLongdate(rd) 253 if null { 254 return nil, nil 255 } 256 return time, nil 257 258 case tcSeconddate: 259 time, null := readSeconddate(rd) 260 if null { 261 return nil, nil 262 } 263 return time, nil 264 265 case tcDaydate: 266 time, null := readDaydate(rd) 267 if null { 268 return nil, nil 269 } 270 return time, nil 271 272 case tcSecondtime: 273 time, null := readSecondtime(rd) 274 if null { 275 return nil, nil 276 } 277 return time, nil 278 279 case tcDecimal: 280 b, null := readDecimal(rd) 281 if null { 282 return nil, nil 283 } 284 return b, nil 285 286 case tcChar, tcVarchar: 287 value, null := readBytes(rd) 288 if null { 289 return nil, nil 290 } 291 return value, nil 292 293 case tcNchar, tcNvarchar: 294 value, null := readUtf8(rd) 295 if null { 296 return nil, nil 297 } 298 return value, nil 299 300 case tcBinary, tcVarbinary: 301 value, null := readBytes(rd) 302 if null { 303 return nil, nil 304 } 305 return value, nil 306 307 case tcBlob, tcClob, tcNclob: 308 null, writer, err := readLob(session, rd, tc) 309 if null { 310 return nil, nil 311 } 312 return writer, err 313 } 314 315 outLogger.Fatalf("read field: type code %s not implemented", tc) 316 return nil, nil 317} 318 319func writeField(wr *bufio.Writer, tc TypeCode, arg driver.NamedValue) error { 320 v := arg.Value 321 //HDB bug: secondtime null value cannot be set by setting high byte 322 // trying so, gives 323 // SQL HdbError 1033 - error while parsing protocol: no such data type: type_code=192, index=2 324 325 // null value 326 //if v == nil && tc != tcSecondtime 327 if v == nil { 328 wr.WriteB(byte(tc) | 0x80) //set high bit 329 return nil 330 } 331 332 // type code 333 wr.WriteB(byte(tc)) 334 335 switch tc { 336 337 default: 338 outLogger.Fatalf("write field: type code %s not implemented", tc) 339 340 case tcTinyint, tcSmallint, tcInteger, tcBigint: 341 var i64 int64 342 343 switch v := v.(type) { 344 default: 345 return fmt.Errorf("invalid argument type %T", v) 346 347 case bool: 348 if v { 349 i64 = 1 350 } else { 351 i64 = 0 352 } 353 case int64: 354 i64 = v 355 } 356 357 switch tc { 358 case tcTinyint: 359 wr.WriteB(byte(i64)) 360 case tcSmallint: 361 wr.WriteInt16(int16(i64)) 362 case tcInteger: 363 wr.WriteInt32(int32(i64)) 364 case tcBigint: 365 wr.WriteInt64(i64) 366 } 367 368 case tcReal: 369 370 f64, ok := v.(float64) 371 if !ok { 372 return fmt.Errorf("invalid argument type %T", v) 373 } 374 wr.WriteFloat32(float32(f64)) 375 376 case tcDouble: 377 378 f64, ok := v.(float64) 379 if !ok { 380 return fmt.Errorf("invalid argument type %T", v) 381 } 382 wr.WriteFloat64(f64) 383 384 case tcDate: 385 t, ok := v.(time.Time) 386 if !ok { 387 return fmt.Errorf("invalid argument type %T", v) 388 } 389 writeDate(wr, t) 390 391 case tcTime: 392 t, ok := v.(time.Time) 393 if !ok { 394 return fmt.Errorf("invalid argument type %T", v) 395 } 396 writeTime(wr, t) 397 398 case tcTimestamp: 399 t, ok := v.(time.Time) 400 if !ok { 401 return fmt.Errorf("invalid argument type %T", v) 402 } 403 writeDate(wr, t) 404 writeTime(wr, t) 405 406 case tcLongdate: 407 t, ok := v.(time.Time) 408 if !ok { 409 return fmt.Errorf("invalid argument type %T", v) 410 } 411 writeLongdate(wr, t) 412 413 case tcSeconddate: 414 t, ok := v.(time.Time) 415 if !ok { 416 return fmt.Errorf("invalid argument type %T", v) 417 } 418 writeSeconddate(wr, t) 419 420 case tcDaydate: 421 t, ok := v.(time.Time) 422 if !ok { 423 return fmt.Errorf("invalid argument type %T", v) 424 } 425 writeDaydate(wr, t) 426 427 case tcSecondtime: 428 // HDB bug: write null value explicite 429 if v == nil { 430 wr.WriteInt32(86401) 431 return nil 432 } 433 t, ok := v.(time.Time) 434 if !ok { 435 return fmt.Errorf("invalid argument type %T", v) 436 } 437 writeSecondtime(wr, t) 438 439 case tcDecimal: 440 b, ok := v.([]byte) 441 if !ok { 442 return fmt.Errorf("invalid argument type %T", v) 443 } 444 if len(b) != 16 { 445 return fmt.Errorf("invalid argument length %d of type %T - expected %d", len(b), v, 16) 446 } 447 wr.Write(b) 448 449 case tcChar, tcVarchar, tcString: 450 switch v := v.(type) { 451 case []byte: 452 writeBytes(wr, v) 453 case string: 454 writeString(wr, v) 455 default: 456 return fmt.Errorf("invalid argument type %T", v) 457 } 458 459 case tcNchar, tcNvarchar, tcNstring: 460 switch v := v.(type) { 461 case []byte: 462 writeUtf8Bytes(wr, v) 463 case string: 464 writeUtf8String(wr, v) 465 default: 466 return fmt.Errorf("invalid argument type %T", v) 467 } 468 469 case tcBinary, tcVarbinary: 470 v, ok := v.([]byte) 471 if !ok { 472 return fmt.Errorf("invalid argument type %T", v) 473 } 474 writeBytes(wr, v) 475 476 case tcBlob, tcClob, tcNclob: 477 writeLob(wr) 478 } 479 480 return nil 481} 482 483// null values: most sig bit unset 484// year: unset second most sig bit (subtract 2^15) 485// --> read year as unsigned 486// month is 0-based 487// day is 1 byte 488func readDate(rd *bufio.Reader) (int, time.Month, int, bool) { 489 year := rd.ReadUint16() 490 null := ((year & 0x8000) == 0) //null value 491 year &= 0x3fff 492 month := rd.ReadInt8() 493 month++ 494 day := rd.ReadInt8() 495 return int(year), time.Month(month), int(day), null 496} 497 498// year: set most sig bit 499// month 0 based 500func writeDate(wr *bufio.Writer, t time.Time) { 501 //store in utc 502 utc := t.In(time.UTC) 503 504 year, month, day := utc.Date() 505 506 wr.WriteUint16(uint16(year) | 0x8000) 507 wr.WriteInt8(int8(month) - 1) 508 wr.WriteInt8(int8(day)) 509} 510 511func readTime(rd *bufio.Reader) (int, int, int, bool) { 512 hour := rd.ReadB() 513 null := (hour & 0x80) == 0 //null value 514 hour &= 0x7f 515 minute := rd.ReadInt8() 516 millisecs := rd.ReadUint16() 517 nanosecs := int(millisecs) * 1000000 518 return int(hour), int(minute), nanosecs, null 519} 520 521func writeTime(wr *bufio.Writer, t time.Time) { 522 //store in utc 523 utc := t.UTC() 524 525 wr.WriteB(byte(utc.Hour()) | 0x80) 526 wr.WriteInt8(int8(utc.Minute())) 527 millisecs := utc.Second()*1000 + utc.Round(time.Millisecond).Nanosecond()/1000000 528 wr.WriteUint16(uint16(millisecs)) 529} 530 531var zeroTime = time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC) 532 533func readLongdate(rd *bufio.Reader) (time.Time, bool) { 534 longdate := rd.ReadInt64() 535 if longdate == 3155380704000000001 { // null value 536 return zeroTime, true 537 } 538 return convertLongdateToTime(longdate), false 539} 540 541func writeLongdate(wr *bufio.Writer, t time.Time) { 542 wr.WriteInt64(convertTimeToLongdate(t)) 543} 544 545func readSeconddate(rd *bufio.Reader) (time.Time, bool) { 546 seconddate := rd.ReadInt64() 547 if seconddate == 315538070401 { // null value 548 return zeroTime, true 549 } 550 return convertSeconddateToTime(seconddate), false 551} 552 553func writeSeconddate(wr *bufio.Writer, t time.Time) { 554 wr.WriteInt64(convertTimeToSeconddate(t)) 555} 556 557func readDaydate(rd *bufio.Reader) (time.Time, bool) { 558 daydate := rd.ReadInt32() 559 if daydate == 3652062 { // null value 560 return zeroTime, true 561 } 562 return convertDaydateToTime(int64(daydate)), false 563} 564 565func writeDaydate(wr *bufio.Writer, t time.Time) { 566 wr.WriteInt32(int32(convertTimeToDayDate(t))) 567} 568 569func readSecondtime(rd *bufio.Reader) (time.Time, bool) { 570 secondtime := rd.ReadInt32() 571 if secondtime == 86401 { // null value 572 return zeroTime, true 573 } 574 return convertSecondtimeToTime(int(secondtime)), false 575} 576 577func writeSecondtime(wr *bufio.Writer, t time.Time) { 578 wr.WriteInt32(int32(convertTimeToSecondtime(t))) 579} 580 581// nanosecond: HDB - 7 digits precision (not 9 digits) 582func convertTimeToLongdate(t time.Time) int64 { 583 t = t.UTC() 584 return (((((((int64(convertTimeToDayDate(t))-1)*24)+int64(t.Hour()))*60)+int64(t.Minute()))*60)+int64(t.Second()))*10000000 + int64(t.Nanosecond()/100) + 1 585} 586 587func convertLongdateToTime(longdate int64) time.Time { 588 const dayfactor = 10000000 * 24 * 60 * 60 589 longdate-- 590 d := (longdate % dayfactor) * 100 591 t := convertDaydateToTime((longdate / dayfactor) + 1) 592 return t.Add(time.Duration(d)) 593} 594 595func convertTimeToSeconddate(t time.Time) int64 { 596 t = t.UTC() 597 return (((((int64(convertTimeToDayDate(t))-1)*24)+int64(t.Hour()))*60)+int64(t.Minute()))*60 + int64(t.Second()) + 1 598} 599 600func convertSeconddateToTime(seconddate int64) time.Time { 601 const dayfactor = 24 * 60 * 60 602 seconddate-- 603 d := (seconddate % dayfactor) * 1000000000 604 t := convertDaydateToTime((seconddate / dayfactor) + 1) 605 return t.Add(time.Duration(d)) 606} 607 608const julianHdb = 1721423 // 1 January 0001 00:00:00 (1721424) - 1 609 610func convertTimeToDayDate(t time.Time) int64 { 611 return int64(timeToJulianDay(t) - julianHdb) 612} 613 614func convertDaydateToTime(daydate int64) time.Time { 615 return julianDayToTime(int(daydate) + julianHdb) 616} 617 618func convertTimeToSecondtime(t time.Time) int { 619 t = t.UTC() 620 return (t.Hour()*60+t.Minute())*60 + t.Second() + 1 621} 622 623func convertSecondtimeToTime(secondtime int) time.Time { 624 return time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC).Add(time.Duration(int64(secondtime-1) * 1000000000)) 625} 626 627func readDecimal(rd *bufio.Reader) ([]byte, bool) { 628 b := make([]byte, 16) 629 rd.ReadFull(b) 630 if (b[15] & 0x70) == 0x70 { //null value (bit 4,5,6 set) 631 return nil, true 632 } 633 return b, false 634} 635 636// string / binary length indicators 637const ( 638 bytesLenIndNullValue byte = 255 639 bytesLenIndSmall byte = 245 640 bytesLenIndMedium byte = 246 641 bytesLenIndBig byte = 247 642) 643 644func bytesSize(size int) (int, error) { //size + length indicator 645 switch { 646 default: 647 return 0, fmt.Errorf("max string length %d exceeded %d", math.MaxInt32, size) 648 case size <= int(bytesLenIndSmall): 649 return size + 1, nil 650 case size <= math.MaxInt16: 651 return size + 3, nil 652 case size <= math.MaxInt32: 653 return size + 5, nil 654 } 655} 656 657func readBytesSize(rd *bufio.Reader) (int, bool) { 658 659 ind := rd.ReadB() //length indicator 660 661 switch { 662 663 default: 664 return 0, false 665 666 case ind == bytesLenIndNullValue: 667 return 0, true 668 669 case ind <= bytesLenIndSmall: 670 return int(ind), false 671 672 case ind == bytesLenIndMedium: 673 return int(rd.ReadInt16()), false 674 675 case ind == bytesLenIndBig: 676 return int(rd.ReadInt32()), false 677 678 } 679} 680 681func writeBytesSize(wr *bufio.Writer, size int) error { 682 switch { 683 684 default: 685 return fmt.Errorf("max argument length %d of string exceeded", size) 686 687 case size <= int(bytesLenIndSmall): 688 wr.WriteB(byte(size)) 689 case size <= math.MaxInt16: 690 wr.WriteB(bytesLenIndMedium) 691 wr.WriteInt16(int16(size)) 692 case size <= math.MaxInt32: 693 wr.WriteB(bytesLenIndBig) 694 wr.WriteInt32(int32(size)) 695 } 696 return nil 697} 698 699func readBytes(rd *bufio.Reader) ([]byte, bool) { 700 size, null := readBytesSize(rd) 701 if null { 702 return nil, true 703 } 704 b := make([]byte, size) 705 rd.ReadFull(b) 706 return b, false 707} 708 709func readUtf8(rd *bufio.Reader) ([]byte, bool) { 710 size, null := readBytesSize(rd) 711 if null { 712 return nil, true 713 } 714 b := rd.ReadCesu8(size) 715 return b, false 716} 717 718// strings with one byte length 719func readShortUtf8(rd *bufio.Reader) ([]byte, int) { 720 size := rd.ReadB() 721 b := rd.ReadCesu8(int(size)) 722 return b, int(size) 723} 724 725func writeBytes(wr *bufio.Writer, b []byte) { 726 writeBytesSize(wr, len(b)) 727 wr.Write(b) 728} 729 730func writeString(wr *bufio.Writer, s string) { 731 writeBytesSize(wr, len(s)) 732 wr.WriteString(s) 733} 734 735func writeUtf8Bytes(wr *bufio.Writer, b []byte) { 736 size := cesu8.Size(b) 737 writeBytesSize(wr, size) 738 wr.WriteCesu8(b) 739} 740 741func writeUtf8String(wr *bufio.Writer, s string) { 742 size := cesu8.StringSize(s) 743 writeBytesSize(wr, size) 744 wr.WriteStringCesu8(s) 745} 746 747func readLob(s *Session, rd *bufio.Reader, tc TypeCode) (bool, lobChunkWriter, error) { 748 rd.ReadInt8() // type code (is int here) 749 opt := rd.ReadInt8() 750 null := (lobOptions(opt) & loNullindicator) != 0 751 if null { 752 return true, nil, nil 753 } 754 eof := (lobOptions(opt) & loLastdata) != 0 755 rd.Skip(2) 756 757 charLen := rd.ReadInt64() 758 byteLen := rd.ReadInt64() 759 id := rd.ReadUint64() 760 chunkLen := rd.ReadInt32() 761 762 lobChunkWriter := newLobChunkWriter(tc.isCharBased(), s, locatorID(id), charLen, byteLen) 763 if err := lobChunkWriter.write(rd, int(chunkLen), eof); err != nil { 764 return null, lobChunkWriter, err 765 } 766 return null, lobChunkWriter, nil 767} 768 769// TODO: first write: add content? - actually no data transferred 770func writeLob(wr *bufio.Writer) { 771 wr.WriteB(0) 772 wr.WriteInt32(0) 773 wr.WriteInt32(0) 774} 775