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