-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcolumn.go
More file actions
131 lines (114 loc) · 2.43 KB
/
column.go
File metadata and controls
131 lines (114 loc) · 2.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package msi
import (
"encoding/binary"
"fmt"
"github.com/asalih/go-mscfb"
)
const (
COL_FIELD_SIZE_MASK int32 = 0xff
COL_LOCALIZABLE_BIT int32 = 0x200
COL_STRING_BIT int32 = 0x800
COL_NULLABLE_BIT int32 = 0x1000
COL_PRIMARY_KEY_BIT int32 = 0x2000
COL_VALID_BIT int32 = 0x100
COL_NONBINARY_BIT int32 = 0x400
)
type ColumnType int
const (
ColumnTypeInt16 ColumnType = iota
ColumnTypeInt32
ColumnTypeStr
)
func ColumnTypeFromBitField(typeBits int32) (ColumnType, int, error) {
fieldSize := int(typeBits & COL_FIELD_SIZE_MASK)
if typeBits&COL_STRING_BIT != 0 {
return ColumnTypeStr, fieldSize, nil
} else if fieldSize == 4 {
return ColumnTypeInt32, fieldSize, nil
} else if fieldSize == 2 {
return ColumnTypeInt16, fieldSize, nil
} else if fieldSize == 1 {
return ColumnTypeInt16, fieldSize, nil
}
return -1, 0, fmt.Errorf("invalid column type bits: %x", typeBits)
}
func (c ColumnType) Width(longStringRefs bool) uint64 {
switch c {
case ColumnTypeInt16:
return 2
case ColumnTypeInt32:
return 4
case ColumnTypeStr:
if longStringRefs {
return 3
}
return 2
}
return 0
}
func (c ColumnType) ReadValue(stream *mscfb.Stream, longStringRefs bool) (*ValueRef, error) {
switch c {
case ColumnTypeInt16:
var value int16
err := binary.Read(stream, binary.LittleEndian, &value)
if err != nil {
return nil, err
}
if value == 0 {
return &ValueRef{IsNull: true}, nil
}
return &ValueRef{
IsInt: true,
Value: int(value ^ -0x8000),
}, nil
case ColumnTypeInt32:
var value int32
err := binary.Read(stream, binary.LittleEndian, &value)
if err != nil {
return nil, err
}
if value == 0 {
return &ValueRef{IsNull: true}, nil
}
return &ValueRef{
IsInt: true,
Value: int(value ^ -0x8000_0000),
}, nil
case ColumnTypeStr:
var value StringRef
rd, err := value.Read(stream, longStringRefs)
if err != nil {
return nil, err
}
if rd.Num == 0 {
return &ValueRef{
IsNull: true,
}, nil
}
return &ValueRef{
IsStr: true,
Value: rd,
}, nil
}
return nil, nil
}
type valueRange struct {
Min int32
Max int32
}
type foreignKey struct {
TableName string
ColumnIndex int32
}
type Column struct {
Name string
ColumnType ColumnType
ColumnStringSize int
IsLocalizable bool
IsNullable bool
IsPrimarykey bool
ValueRange valueRange
ForeignKey foreignKey
Category Category
EnumValues []string
}