github.com/matrixorigin/matrixone@v0.7.0/pkg/common/hashmap/inthashmap.go (about) 1 // Copyright 2021 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package hashmap 16 17 import ( 18 "unsafe" 19 20 "github.com/matrixorigin/matrixone/pkg/common/mpool" 21 "github.com/matrixorigin/matrixone/pkg/container/hashtable" 22 "github.com/matrixorigin/matrixone/pkg/container/types" 23 "github.com/matrixorigin/matrixone/pkg/container/vector" 24 ) 25 26 func init() { 27 zeroUint64 = make([]uint64, UnitLimit) 28 zeroUint32 = make([]uint32, UnitLimit) 29 } 30 31 func NewIntHashMap(hasNull bool, ibucket, nbucket uint64, m *mpool.MPool) (*IntHashMap, error) { 32 mp := &hashtable.Int64HashMap{} 33 if err := mp.Init(m); err != nil { 34 return nil, err 35 } 36 return &IntHashMap{ 37 m: m, 38 rows: 0, 39 hasNull: hasNull, 40 ibucket: ibucket, 41 nbucket: nbucket, 42 keys: make([]uint64, UnitLimit), 43 keyOffs: make([]uint32, UnitLimit), 44 values: make([]uint64, UnitLimit), 45 zValues: make([]int64, UnitLimit), 46 hashes: make([]uint64, UnitLimit), 47 hashMap: mp, 48 }, nil 49 } 50 51 func (m *IntHashMap) NewIterator() *intHashMapIterator { 52 return &intHashMapIterator{ 53 mp: m, 54 m: m.m, 55 ibucket: m.ibucket, 56 nbucket: m.nbucket, 57 } 58 } 59 60 func (m *IntHashMap) HasNull() bool { 61 return m.hasNull 62 } 63 64 func (m *IntHashMap) Free() { 65 m.hashMap.Free(m.m) 66 } 67 68 func (m *IntHashMap) GroupCount() uint64 { 69 return m.rows 70 } 71 72 func (m *IntHashMap) AddGroup() { 73 m.rows++ 74 } 75 76 func (m *IntHashMap) AddGroups(rows uint64) { 77 m.rows += rows 78 } 79 80 func (m *IntHashMap) Size() int64 { 81 // TODO: add the size of the other IntHashMap parts 82 if m.hashMap == nil { 83 return 0 84 } 85 return m.hashMap.Size() 86 } 87 88 func (m *IntHashMap) Cardinality() uint64 { 89 return m.hashMap.Cardinality() 90 } 91 92 func (m *IntHashMap) encodeHashKeys(vecs []*vector.Vector, start, count int) { 93 for _, vec := range vecs { 94 switch vec.Typ.TypeSize() { 95 case 1: 96 fillKeys[uint8](m, vec, 1, start, count) 97 case 2: 98 fillKeys[uint16](m, vec, 2, start, count) 99 case 4: 100 fillKeys[uint32](m, vec, 4, start, count) 101 case 8: 102 fillKeys[uint64](m, vec, 8, start, count) 103 default: 104 fillStrKey(m, vec, start, count) 105 } 106 } 107 } 108 109 func fillKeys[T types.FixedSizeT](m *IntHashMap, vec *vector.Vector, size uint32, start int, n int) { 110 keys := m.keys 111 keyOffs := m.keyOffs 112 if !vec.GetNulls().Any() { 113 if m.hasNull { 114 for i := 0; i < n; i++ { 115 *(*int8)(unsafe.Add(unsafe.Pointer(&keys[i]), keyOffs[i])) = 0 116 ptr := (*T)(vector.GetPtrAt(vec, int64(i+start))) 117 *(*T)(unsafe.Add(unsafe.Pointer(&keys[i]), keyOffs[i]+1)) = *ptr 118 } 119 uint32AddScalar(1+size, keyOffs[:n], keyOffs[:n]) 120 } else { 121 for i := 0; i < n; i++ { 122 ptr := (*T)(vector.GetPtrAt(vec, int64(i+start))) 123 *(*T)(unsafe.Add(unsafe.Pointer(&keys[i]), keyOffs[i])) = *ptr 124 } 125 uint32AddScalar(size, keyOffs[:n], keyOffs[:n]) 126 } 127 } else { 128 nsp := vec.GetNulls() 129 if m.hasNull { 130 for i := 0; i < n; i++ { 131 if nsp.Contains(uint64(i + start)) { 132 *(*int8)(unsafe.Add(unsafe.Pointer(&keys[i]), keyOffs[i])) = 1 133 keyOffs[i]++ 134 } else { 135 *(*int8)(unsafe.Add(unsafe.Pointer(&keys[i]), keyOffs[i])) = 0 136 ptr := (*T)(vector.GetPtrAt(vec, int64(i+start))) 137 *(*T)(unsafe.Add(unsafe.Pointer(&keys[i]), keyOffs[i]+1)) = *ptr 138 keyOffs[i] += 1 + size 139 } 140 } 141 } else { 142 for i := 0; i < n; i++ { 143 if nsp.Contains(uint64(i + start)) { 144 m.zValues[i] = 0 145 continue 146 } 147 ptr := (*T)(vector.GetPtrAt(vec, int64(i+start))) 148 *(*T)(unsafe.Add(unsafe.Pointer(&keys[i]), keyOffs[i])) = *ptr 149 keyOffs[i] += size 150 } 151 } 152 } 153 } 154 155 func fillStrKey(m *IntHashMap, vec *vector.Vector, start int, n int) { 156 area := vec.GetArea() 157 vs := vector.MustTCols[types.Varlena](vec) 158 keys := m.keys 159 keyOffs := m.keyOffs 160 if !vec.GetNulls().Any() { 161 if m.hasNull { 162 for i := 0; i < n; i++ { 163 v := vs[i+start].GetByteSlice(area) 164 *(*int8)(unsafe.Add(unsafe.Pointer(&keys[i]), keyOffs[i])) = 0 165 copy(unsafe.Slice((*byte)(unsafe.Pointer(&keys[i])), 8)[m.keyOffs[i]+1:], v) 166 m.keyOffs[i] += uint32(len(v) + 1) 167 } 168 } else { 169 for i := 0; i < n; i++ { 170 v := vs[i+start].GetByteSlice(area) 171 copy(unsafe.Slice((*byte)(unsafe.Pointer(&keys[i])), 8)[m.keyOffs[i]:], v) 172 m.keyOffs[i] += uint32(len(v)) 173 } 174 } 175 } else { 176 nsp := vec.GetNulls() 177 if m.hasNull { 178 for i := 0; i < n; i++ { 179 v := vs[i+start].GetByteSlice(area) 180 if nsp.Contains(uint64(i + start)) { 181 *(*int8)(unsafe.Add(unsafe.Pointer(&keys[i]), keyOffs[i])) = 1 182 keyOffs[i]++ 183 } else { 184 *(*int8)(unsafe.Add(unsafe.Pointer(&keys[i]), keyOffs[i])) = 0 185 copy(unsafe.Slice((*byte)(unsafe.Pointer(&keys[i])), 8)[m.keyOffs[i]+1:], v) 186 m.keyOffs[i] += uint32(len(v) + 1) 187 } 188 } 189 } else { 190 for i := 0; i < n; i++ { 191 v := vs[i+start].GetByteSlice(area) 192 if nsp.Contains(uint64(i + start)) { 193 m.zValues[i] = 0 194 continue 195 } 196 copy(unsafe.Slice((*byte)(unsafe.Pointer(&keys[i])), 8)[m.keyOffs[i]:], v) 197 m.keyOffs[i] += uint32(len(v)) 198 } 199 } 200 } 201 } 202 203 func uint32AddScalar(x uint32, ys, rs []uint32) []uint32 { 204 for i, y := range ys { 205 rs[i] = x + y 206 } 207 return rs 208 }