open-vault/vendor/github.com/SAP/go-hdb/internal/protocol/result.go
Jeff Mitchell 98b479ab58 Bump deps
2018-01-26 18:51:00 -05:00

296 lines
5.6 KiB
Go

/*
Copyright 2014 SAP SE
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package protocol
import (
"fmt"
"github.com/SAP/go-hdb/internal/bufio"
)
const (
resultsetIDSize = 8
)
type columnOptions int8
const (
coMandatory columnOptions = 0x01
coOptional columnOptions = 0x02
)
var columnOptionsText = map[columnOptions]string{
coMandatory: "mandatory",
coOptional: "optional",
}
func (k columnOptions) String() string {
t := make([]string, 0, len(columnOptionsText))
for option, text := range columnOptionsText {
if (k & option) != 0 {
t = append(t, text)
}
}
return fmt.Sprintf("%v", t)
}
//resultset id
type resultsetID struct {
id *uint64
}
func (id *resultsetID) kind() partKind {
return pkResultsetID
}
func (id *resultsetID) size() (int, error) {
return resultsetIDSize, nil
}
func (id *resultsetID) numArg() int {
return 1
}
func (id *resultsetID) setNumArg(int) {
//ignore - always 1
}
func (id *resultsetID) read(rd *bufio.Reader) error {
_id, err := rd.ReadUint64()
if err != nil {
return err
}
*id.id = _id
if trace {
outLogger.Printf("resultset id: %d", *id.id)
}
return nil
}
func (id *resultsetID) write(wr *bufio.Writer) error {
if err := wr.WriteUint64(*id.id); err != nil {
return err
}
if trace {
outLogger.Printf("resultset id: %d", *id.id)
}
return nil
}
const (
resultTableName = iota // used as index: start with 0
resultSchemaName
resultColumnName
resultColumnDisplayName
maxResultNames
)
type resultField struct {
columnOptions columnOptions
tc typeCode
fraction int16
length int16
tablenameOffset uint32
schemanameOffset uint32
columnnameOffset uint32
columnDisplaynameOffset uint32
}
func newResultField() *resultField {
return &resultField{}
}
func (f *resultField) String() string {
return fmt.Sprintf("columnsOptions %s typeCode %s fraction %d length %d tablenameOffset %d schemanameOffset %d columnnameOffset %d columnDisplaynameOffset %d",
f.columnOptions,
f.tc,
f.fraction,
f.length,
f.tablenameOffset,
f.schemanameOffset,
f.columnnameOffset,
f.columnDisplaynameOffset,
)
}
// Field interface
func (f *resultField) typeCode() typeCode {
return f.tc
}
func (f *resultField) typeLength() (int64, bool) {
if f.tc.isVariableLength() {
return int64(f.length), true
}
return 0, false
}
func (f *resultField) typePrecisionScale() (int64, int64, bool) {
if f.tc.isDecimalType() {
return int64(f.length), int64(f.fraction), true
}
return 0, 0, false
}
func (f *resultField) nullable() bool {
return f.columnOptions == coOptional
}
func (f *resultField) in() bool {
return false
}
func (f *resultField) out() bool {
return true
}
func (f *resultField) name(names map[uint32]string) string {
return names[f.columnDisplaynameOffset]
}
func (f *resultField) nameOffsets() []uint32 {
return []uint32{f.tablenameOffset, f.schemanameOffset, f.columnnameOffset, f.columnDisplaynameOffset}
}
//
func (f *resultField) read(rd *bufio.Reader) error {
var err error
if co, err := rd.ReadInt8(); err == nil {
f.columnOptions = columnOptions(co)
} else {
return err
}
if tc, err := rd.ReadInt8(); err == nil {
f.tc = typeCode(tc)
} else {
return err
}
if f.fraction, err = rd.ReadInt16(); err != nil {
return err
}
if f.length, err = rd.ReadInt16(); err != nil {
return err
}
if err := rd.Skip(2); err != nil { //filler
return err
}
if f.tablenameOffset, err = rd.ReadUint32(); err != nil {
return err
}
if f.schemanameOffset, err = rd.ReadUint32(); err != nil {
return err
}
if f.columnnameOffset, err = rd.ReadUint32(); err != nil {
return err
}
if f.columnDisplaynameOffset, err = rd.ReadUint32(); err != nil {
return err
}
return nil
}
//resultset metadata
type resultMetadata struct {
fieldSet *FieldSet
numArg int
}
func (r *resultMetadata) String() string {
return fmt.Sprintf("result metadata: %s", r.fieldSet.fields)
}
func (r *resultMetadata) kind() partKind {
return pkResultMetadata
}
func (r *resultMetadata) setNumArg(numArg int) {
r.numArg = numArg
}
func (r *resultMetadata) read(rd *bufio.Reader) error {
for i := 0; i < r.numArg; i++ {
field := newResultField()
if err := field.read(rd); err != nil {
return err
}
r.fieldSet.fields[i] = field
}
pos := uint32(0)
for _, offset := range r.fieldSet.nameOffsets() {
if diff := int(offset - pos); diff > 0 {
rd.Skip(diff)
}
b, size, err := readShortUtf8(rd)
if err != nil {
return err
}
r.fieldSet.names[offset] = string(b)
pos += uint32(1 + size)
}
if trace {
outLogger.Printf("read %s", r)
}
return nil
}
//resultset
type resultset struct {
numArg int
fieldSet *FieldSet
fieldValues *FieldValues
}
func (r *resultset) String() string {
return fmt.Sprintf("resultset: %s", r.fieldValues)
}
func (r *resultset) kind() partKind {
return pkResultset
}
func (r *resultset) setNumArg(numArg int) {
r.numArg = numArg
}
func (r *resultset) read(rd *bufio.Reader) error {
if err := r.fieldValues.read(r.numArg, r.fieldSet, rd); err != nil {
return err
}
if trace {
outLogger.Printf("read %s", r)
}
return nil
}