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  }