github.com/matrixorigin/matrixone@v1.2.0/pkg/container/nulls/nulls.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 nulls wrap up functions for the manipulation of bitmap library roaring.
    16  // MatrixOne uses nulls to store all NULL values in a column.
    17  // You can think of Nulls as a bitmap.
    18  package nulls
    19  
    20  import (
    21  	"fmt"
    22  	"unsafe"
    23  
    24  	"github.com/matrixorigin/matrixone/pkg/common/bitmap"
    25  	"golang.org/x/exp/constraints"
    26  )
    27  
    28  type Bitmap = Nulls
    29  
    30  type Nulls struct {
    31  	np bitmap.Bitmap
    32  }
    33  
    34  func (nsp *Nulls) Clone() *Nulls {
    35  	if nsp == nil {
    36  		return nil
    37  	}
    38  	var n Nulls
    39  	n.InitWith(nsp)
    40  	return &n
    41  }
    42  
    43  func (nsp *Nulls) InitWith(n *Nulls) {
    44  	nsp.np.InitWith(&n.np)
    45  }
    46  
    47  func (nsp *Nulls) InitWithSize(size int) {
    48  	nsp.np.InitWithSize(int64(size))
    49  }
    50  
    51  func NewWithSize(size int) *Nulls {
    52  	var n Nulls
    53  	n.InitWithSize(size)
    54  	return &n
    55  }
    56  
    57  func (nsp *Nulls) Reset() {
    58  	nsp.np.Reset()
    59  }
    60  
    61  func (nsp *Nulls) GetBitmap() *bitmap.Bitmap {
    62  	return &nsp.np
    63  }
    64  
    65  // Or performs union operation on Nulls nsp,m and store the result in r
    66  func Or(nsp, m, r *Nulls) {
    67  	if nsp.EmptyByFlag() && m.EmptyByFlag() {
    68  		r.Reset()
    69  	}
    70  
    71  	if !nsp.EmptyByFlag() {
    72  		r.np.Or(&nsp.np)
    73  	}
    74  
    75  	if !m.EmptyByFlag() {
    76  		r.np.Or(&m.np)
    77  	}
    78  }
    79  
    80  func (nsp *Nulls) Build(size int, rows ...uint64) {
    81  	nsp.InitWithSize(size)
    82  	Add(nsp, rows...)
    83  }
    84  func Build(size int, rows ...uint64) *Nulls {
    85  	var n Nulls
    86  	n.Build(size, rows...)
    87  	return &n
    88  }
    89  
    90  // Any returns true if any bit in the Nulls is set, otherwise it will return false.
    91  func Any(nsp *Nulls) bool {
    92  	if nsp == nil {
    93  		return false
    94  	}
    95  	return !nsp.np.IsEmpty()
    96  }
    97  
    98  func Ptr(nsp *Nulls) *uint64 {
    99  	if nsp == nil {
   100  		return nil
   101  	}
   102  	return nsp.np.Ptr()
   103  }
   104  
   105  // Size estimates the memory usage of the Nulls.
   106  func Size(nsp *Nulls) int {
   107  	if nsp == nil {
   108  		return 0
   109  	}
   110  	return int(nsp.np.Size())
   111  }
   112  
   113  func String(nsp *Nulls) string {
   114  	if nsp == nil || nsp.np.EmptyByFlag() {
   115  		return "[]"
   116  	}
   117  	return fmt.Sprintf("%v", nsp.np.ToArray())
   118  }
   119  
   120  func TryExpand(nsp *Nulls, size int) {
   121  	nsp.np.TryExpandWithSize(size)
   122  }
   123  
   124  // Contains returns true if the integer is contained in the Nulls
   125  func (nsp *Nulls) Contains(row uint64) bool {
   126  	return nsp != nil && !nsp.np.EmptyByFlag() && nsp.np.Contains(row)
   127  }
   128  
   129  func Contains(nsp *Nulls, row uint64) bool {
   130  	return nsp.Contains(row)
   131  }
   132  
   133  func (nsp *Nulls) Add(rows ...uint64) {
   134  	if nsp == nil || len(rows) == 0 {
   135  		return
   136  	}
   137  	TryExpand(nsp, int(rows[len(rows)-1])+1)
   138  	nsp.np.AddMany(rows)
   139  }
   140  
   141  func Add(nsp *Nulls, rows ...uint64) {
   142  	nsp.Add(rows...)
   143  }
   144  
   145  func (nsp *Nulls) AddRange(start, end uint64) {
   146  	if nsp != nil {
   147  		TryExpand(nsp, int(end+1))
   148  		nsp.np.AddRange(start, end)
   149  	}
   150  }
   151  
   152  func AddRange(nsp *Nulls, start, end uint64) {
   153  	nsp.AddRange(start, end)
   154  }
   155  
   156  func (nsp *Nulls) Del(rows ...uint64) {
   157  	if nsp != nil {
   158  		for _, row := range rows {
   159  			nsp.np.Remove(row)
   160  		}
   161  	}
   162  }
   163  
   164  func (nsp *Nulls) DelI64(rows ...int64) {
   165  	if nsp != nil {
   166  		for _, row := range rows {
   167  			nsp.np.Remove(uint64(row))
   168  		}
   169  	}
   170  }
   171  
   172  func Del(nsp *Nulls, rows ...uint64) {
   173  	nsp.Del(rows...)
   174  }
   175  
   176  // Set performs union operation on Nulls nsp,m and store the result in nsp
   177  func Set(nsp, m *Nulls) {
   178  	if !m.np.EmptyByFlag() {
   179  		nsp.np.Or(&m.np)
   180  	}
   181  }
   182  
   183  // FilterCount returns the number count that appears in both nsp and sel
   184  func FilterCount(nsp *Nulls, sels []int64) int {
   185  	var cnt int
   186  	if nsp.np.EmptyByFlag() || len(sels) == 0 {
   187  		return 0
   188  	}
   189  
   190  	// XXX WTF is this?  convert int64 to uint64?
   191  	var sp []uint64
   192  	if len(sels) > 0 {
   193  		sp = unsafe.Slice((*uint64)(unsafe.Pointer(&sels[0])), cap(sels))[:len(sels)]
   194  	}
   195  
   196  	for _, sel := range sp {
   197  		if nsp.np.Contains(sel) {
   198  			cnt++
   199  		}
   200  	}
   201  	return cnt
   202  }
   203  
   204  func RemoveRange(nsp *Nulls, start, end uint64) {
   205  	if !nsp.np.EmptyByFlag() {
   206  		nsp.np.RemoveRange(start, end)
   207  	}
   208  }
   209  
   210  // Range adds the numbers in nsp starting at start and ending at end to m.
   211  // `bias` represents the starting offset used for the Range Output
   212  // Always update in place.
   213  func Range(nsp *Nulls, start, end, bias uint64, m *Nulls) {
   214  	if nsp.np.EmptyByFlag() {
   215  		return
   216  	}
   217  
   218  	m.np.InitWithSize(int64(end + 1 - bias))
   219  	for ; start < end; start++ {
   220  		if nsp.np.Contains(start) {
   221  			m.np.Add(start - bias)
   222  		}
   223  	}
   224  }
   225  
   226  // XXX old API returns nsp, which is broken -- we update in place.
   227  func Filter(nsp *Nulls, sels []int64, negate bool) {
   228  	if nsp.np.EmptyByFlag() {
   229  		return
   230  	}
   231  
   232  	if negate {
   233  		oldLen := nsp.np.Len()
   234  		var bm bitmap.Bitmap
   235  		bm.InitWithSize(oldLen)
   236  		for oldIdx, newIdx, selIdx, sel := int64(0), 0, 0, sels[0]; oldIdx < oldLen; oldIdx++ {
   237  			if oldIdx != sel {
   238  				if nsp.np.Contains(uint64(oldIdx)) {
   239  					bm.Add(uint64(newIdx))
   240  				}
   241  				newIdx++
   242  			} else {
   243  				selIdx++
   244  				if selIdx >= len(sels) {
   245  					for idx := oldIdx + 1; idx < oldLen; idx++ {
   246  						if nsp.np.Contains(uint64(idx)) {
   247  							bm.Add(uint64(newIdx))
   248  						}
   249  						newIdx++
   250  					}
   251  					break
   252  				}
   253  				sel = sels[selIdx]
   254  			}
   255  		}
   256  		nsp.np.InitWith(&bm)
   257  	} else {
   258  		var bm bitmap.Bitmap
   259  		bm.InitWithSize(int64(len(sels)))
   260  		upperLimit := int64(nsp.np.Len())
   261  		for i, sel := range sels {
   262  			if sel >= upperLimit {
   263  				continue
   264  			}
   265  			if nsp.np.Contains(uint64(sel)) {
   266  				bm.Add(uint64(i))
   267  			}
   268  		}
   269  		nsp.np.InitWith(&bm)
   270  	}
   271  }
   272  
   273  // XXX This emptyFlag thing is broken -- it simply cannot be used concurrently.
   274  // Make any an alias of EmptyByFlag, otherwise there will be hell lots of race conditions.
   275  func (nsp *Nulls) Any() bool {
   276  	return nsp != nil && !nsp.np.EmptyByFlag()
   277  }
   278  
   279  func (nsp *Nulls) IsEmpty() bool {
   280  	return nsp == nil || nsp.np.IsEmpty()
   281  }
   282  
   283  func (nsp *Nulls) EmptyByFlag() bool {
   284  	return nsp == nil || nsp.np.EmptyByFlag()
   285  }
   286  
   287  func (nsp *Nulls) Set(row uint64) {
   288  	TryExpand(nsp, int(row)+1)
   289  	nsp.np.Add(row)
   290  }
   291  
   292  // Call it unset to match set.   Clear or reset are taken.
   293  func (nsp *Nulls) Unset(row uint64) {
   294  	if nsp != nil {
   295  		nsp.np.Remove(row)
   296  	}
   297  }
   298  
   299  // pop count
   300  func (nsp *Nulls) Count() int {
   301  	if nsp == nil {
   302  		return 0
   303  	}
   304  	return nsp.np.Count()
   305  }
   306  
   307  func (nsp *Nulls) Show() ([]byte, error) {
   308  	if nsp.np.EmptyByFlag() {
   309  		return nil, nil
   310  	}
   311  	return nsp.np.Marshal(), nil
   312  }
   313  
   314  func (nsp *Nulls) Read(data []byte) error {
   315  	if len(data) == 0 {
   316  		// don't we need to reset?   Or we always, Read into a blank Nulls?
   317  		// nsp.np.Reset()
   318  		return nil
   319  	}
   320  	nsp.np.Unmarshal(data)
   321  	return nil
   322  }
   323  
   324  func (nsp *Nulls) ReadNoCopy(data []byte) error {
   325  	if len(data) == 0 {
   326  		return nil
   327  	}
   328  	nsp.np.UnmarshalNoCopy(data)
   329  	return nil
   330  }
   331  
   332  // XXX This API is foundementally broken.  Depends on empty or not
   333  // this shit may or may not modify nsp.
   334  func (nsp *Nulls) Or(m *Nulls) *Nulls {
   335  	if m.np.EmptyByFlag() {
   336  		return nsp
   337  	}
   338  	if nsp.np.EmptyByFlag() {
   339  		return m
   340  	}
   341  
   342  	nsp.np.Or(&m.np)
   343  	return nsp
   344  }
   345  
   346  func (nsp *Nulls) IsSame(m *Nulls) bool {
   347  	if nsp == m {
   348  		return true
   349  	}
   350  	if nsp == nil || m == nil {
   351  		return false
   352  	}
   353  
   354  	return nsp.np.IsSame(&m.np)
   355  }
   356  
   357  func (nsp *Nulls) ToArray() []uint64 {
   358  	if nsp == nil || nsp.np.EmptyByFlag() {
   359  		return []uint64{}
   360  	}
   361  	return nsp.np.ToArray()
   362  }
   363  
   364  func (nsp *Nulls) ToI64Arrary() []int64 {
   365  	if nsp == nil || nsp.np.EmptyByFlag() {
   366  		return []int64{}
   367  	}
   368  	return nsp.np.ToI64Arrary()
   369  }
   370  
   371  func (nsp *Nulls) GetCardinality() int {
   372  	return nsp.Count()
   373  }
   374  
   375  func (nsp *Nulls) Foreach(fn func(uint64) bool) {
   376  	if nsp.IsEmpty() {
   377  		return
   378  	}
   379  	itr := nsp.np.Iterator()
   380  	for itr.HasNext() {
   381  		row := itr.Next()
   382  		if !fn(row) {
   383  			break
   384  		}
   385  	}
   386  }
   387  
   388  func (nsp *Nulls) Merge(o *Nulls) {
   389  	if o.Count() == 0 {
   390  		return
   391  	}
   392  	itr := o.np.Iterator()
   393  	for itr.HasNext() {
   394  		r := itr.Next()
   395  		nsp.Add(r)
   396  	}
   397  }
   398  
   399  func (nsp *Nulls) String() string {
   400  	if nsp.IsEmpty() {
   401  		return fmt.Sprintf("%v", []uint64{})
   402  	}
   403  	return nsp.np.String()
   404  }
   405  
   406  func ToArray[T constraints.Integer](nsp *Nulls) []T {
   407  	if nsp.IsEmpty() {
   408  		return []T{}
   409  	}
   410  	ret := make([]T, 0, nsp.Count())
   411  	it := nsp.np.Iterator()
   412  	for it.HasNext() {
   413  		r := it.Next()
   414  		ret = append(ret, T(r))
   415  	}
   416  	return ret
   417  }