github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/sql/sem/tree/datum_alloc.go (about)

     1  // Copyright 2018 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package tree
    12  
    13  import (
    14  	"github.com/cockroachdb/cockroachdb-parser/pkg/geo/geopb"
    15  	"github.com/cockroachdb/cockroachdb-parser/pkg/util"
    16  )
    17  
    18  // DatumAlloc provides batch allocation of datum pointers, amortizing the cost
    19  // of the allocations.
    20  // NOTE: it *must* be passed in by a pointer.
    21  type DatumAlloc struct {
    22  	_ util.NoCopy
    23  
    24  	// AllocSize determines the number of objects allocated whenever we've used
    25  	// up previously allocated ones. This field is exported so that the caller
    26  	// could adjust it dynamically. If it is left unchanged by the caller, then
    27  	// it will be set to defaultDatumAllocSize automatically.
    28  	AllocSize int
    29  
    30  	datumAlloc        []Datum
    31  	dintAlloc         []DInt
    32  	dfloatAlloc       []DFloat
    33  	dbitArrayAlloc    []DBitArray
    34  	ddecimalAlloc     []DDecimal
    35  	ddateAlloc        []DDate
    36  	denumAlloc        []DEnum
    37  	dbox2dAlloc       []DBox2D
    38  	dgeometryAlloc    []DGeometry
    39  	dgeographyAlloc   []DGeography
    40  	dtimeAlloc        []DTime
    41  	dtimetzAlloc      []DTimeTZ
    42  	dtimestampAlloc   []DTimestamp
    43  	dtimestampTzAlloc []DTimestampTZ
    44  	dintervalAlloc    []DInterval
    45  	duuidAlloc        []DUuid
    46  	dipnetAlloc       []DIPAddr
    47  	djsonAlloc        []DJSON
    48  	dtupleAlloc       []DTuple
    49  	doidAlloc         []DOid
    50  	dvoidAlloc        []DVoid
    51  	dpglsnAlloc       []DPGLSN
    52  	// stringAlloc is used by all datum types that are strings (DBytes, DString, DEncodedKey).
    53  	stringAlloc []string
    54  	env         CollationEnvironment
    55  
    56  	// Allocations for geopb.SpatialObject.EWKB
    57  	ewkbAlloc               []byte
    58  	curEWKBAllocSize        int
    59  	lastEWKBBeyondAllocSize bool
    60  }
    61  
    62  const defaultDatumAllocSize = 16  // Arbitrary, could be tuned.
    63  const datumAllocMultiplier = 4    // Arbitrary, could be tuned.
    64  const defaultEWKBAllocSize = 4096 // Arbitrary, could be tuned.
    65  const maxEWKBAllocSize = 16384    // Arbitrary, could be tuned.
    66  
    67  // NewDatums allocates Datums of the specified size.
    68  func (a *DatumAlloc) NewDatums(num int) Datums {
    69  	if a.AllocSize == 0 {
    70  		a.AllocSize = defaultDatumAllocSize
    71  	}
    72  	buf := &a.datumAlloc
    73  	if len(*buf) < num {
    74  		extensionSize := a.AllocSize
    75  		if extTupleLen := num * datumAllocMultiplier; extensionSize < extTupleLen {
    76  			extensionSize = extTupleLen
    77  		}
    78  		*buf = make(Datums, extensionSize)
    79  	}
    80  	r := (*buf)[:num]
    81  	*buf = (*buf)[num:]
    82  	return r
    83  }
    84  
    85  // NewDInt allocates a DInt.
    86  func (a *DatumAlloc) NewDInt(v DInt) *DInt {
    87  	if a.AllocSize == 0 {
    88  		a.AllocSize = defaultDatumAllocSize
    89  	}
    90  	buf := &a.dintAlloc
    91  	if len(*buf) == 0 {
    92  		*buf = make([]DInt, a.AllocSize)
    93  	}
    94  	r := &(*buf)[0]
    95  	*r = v
    96  	*buf = (*buf)[1:]
    97  	return r
    98  }
    99  
   100  // NewDPGLSN allocates a DPGLSN.
   101  func (a *DatumAlloc) NewDPGLSN(v DPGLSN) *DPGLSN {
   102  	if a.AllocSize == 0 {
   103  		a.AllocSize = defaultDatumAllocSize
   104  	}
   105  	buf := &a.dpglsnAlloc
   106  	if len(*buf) == 0 {
   107  		*buf = make([]DPGLSN, a.AllocSize)
   108  	}
   109  	r := &(*buf)[0]
   110  	*r = v
   111  	*buf = (*buf)[1:]
   112  	return r
   113  }
   114  
   115  // NewDFloat allocates a DFloat.
   116  func (a *DatumAlloc) NewDFloat(v DFloat) *DFloat {
   117  	if a.AllocSize == 0 {
   118  		a.AllocSize = defaultDatumAllocSize
   119  	}
   120  	buf := &a.dfloatAlloc
   121  	if len(*buf) == 0 {
   122  		*buf = make([]DFloat, a.AllocSize)
   123  	}
   124  	r := &(*buf)[0]
   125  	*r = v
   126  	*buf = (*buf)[1:]
   127  	return r
   128  }
   129  
   130  func (a *DatumAlloc) newString() *string {
   131  	if a.AllocSize == 0 {
   132  		a.AllocSize = defaultDatumAllocSize
   133  	}
   134  	buf := &a.stringAlloc
   135  	if len(*buf) == 0 {
   136  		*buf = make([]string, a.AllocSize)
   137  	}
   138  	r := &(*buf)[0]
   139  	*buf = (*buf)[1:]
   140  	return r
   141  }
   142  
   143  // NewDString allocates a DString.
   144  func (a *DatumAlloc) NewDString(v DString) *DString {
   145  	r := (*DString)(a.newString())
   146  	*r = v
   147  	return r
   148  }
   149  
   150  // NewDCollatedString allocates a DCollatedString.
   151  func (a *DatumAlloc) NewDCollatedString(contents string, locale string) (*DCollatedString, error) {
   152  	return NewDCollatedString(contents, locale, &a.env)
   153  }
   154  
   155  // NewDName allocates a DName.
   156  func (a *DatumAlloc) NewDName(v DString) Datum {
   157  	return NewDNameFromDString(a.NewDString(v))
   158  }
   159  
   160  // NewDRefCursor allocates a DRefCursor.
   161  func (a *DatumAlloc) NewDRefCursor(v DString) Datum {
   162  	return NewDRefCursorFromDString(a.NewDString(v))
   163  }
   164  
   165  // NewDBytes allocates a DBytes.
   166  func (a *DatumAlloc) NewDBytes(v DBytes) *DBytes {
   167  	r := (*DBytes)(a.newString())
   168  	*r = v
   169  	return r
   170  }
   171  
   172  // NewDEncodedKey allocates a DEncodedKey.
   173  func (a *DatumAlloc) NewDEncodedKey(v DEncodedKey) *DEncodedKey {
   174  	r := (*DEncodedKey)(a.newString())
   175  	*r = v
   176  	return r
   177  }
   178  
   179  // NewDBitArray allocates a DBitArray.
   180  func (a *DatumAlloc) NewDBitArray(v DBitArray) *DBitArray {
   181  	if a.AllocSize == 0 {
   182  		a.AllocSize = defaultDatumAllocSize
   183  	}
   184  	buf := &a.dbitArrayAlloc
   185  	if len(*buf) == 0 {
   186  		*buf = make([]DBitArray, a.AllocSize)
   187  	}
   188  	r := &(*buf)[0]
   189  	*r = v
   190  	*buf = (*buf)[1:]
   191  	return r
   192  }
   193  
   194  // NewDDecimal allocates a DDecimal.
   195  func (a *DatumAlloc) NewDDecimal(v DDecimal) *DDecimal {
   196  	if a.AllocSize == 0 {
   197  		a.AllocSize = defaultDatumAllocSize
   198  	}
   199  	buf := &a.ddecimalAlloc
   200  	if len(*buf) == 0 {
   201  		*buf = make([]DDecimal, a.AllocSize)
   202  	}
   203  	r := &(*buf)[0]
   204  	r.Set(&v.Decimal)
   205  	*buf = (*buf)[1:]
   206  	return r
   207  }
   208  
   209  // NewDDate allocates a DDate.
   210  func (a *DatumAlloc) NewDDate(v DDate) *DDate {
   211  	if a.AllocSize == 0 {
   212  		a.AllocSize = defaultDatumAllocSize
   213  	}
   214  	buf := &a.ddateAlloc
   215  	if len(*buf) == 0 {
   216  		*buf = make([]DDate, a.AllocSize)
   217  	}
   218  	r := &(*buf)[0]
   219  	*r = v
   220  	*buf = (*buf)[1:]
   221  	return r
   222  }
   223  
   224  // NewDEnum allocates a DEnum.
   225  func (a *DatumAlloc) NewDEnum(v DEnum) *DEnum {
   226  	if a.AllocSize == 0 {
   227  		a.AllocSize = defaultDatumAllocSize
   228  	}
   229  	buf := &a.denumAlloc
   230  	if len(*buf) == 0 {
   231  		*buf = make([]DEnum, a.AllocSize)
   232  	}
   233  	r := &(*buf)[0]
   234  	*r = v
   235  	*buf = (*buf)[1:]
   236  	return r
   237  }
   238  
   239  // NewDBox2D allocates a DBox2D.
   240  func (a *DatumAlloc) NewDBox2D(v DBox2D) *DBox2D {
   241  	if a.AllocSize == 0 {
   242  		a.AllocSize = defaultDatumAllocSize
   243  	}
   244  	buf := &a.dbox2dAlloc
   245  	if len(*buf) == 0 {
   246  		*buf = make([]DBox2D, a.AllocSize)
   247  	}
   248  	r := &(*buf)[0]
   249  	*r = v
   250  	*buf = (*buf)[1:]
   251  	return r
   252  }
   253  
   254  // NewDGeography allocates a DGeography.
   255  func (a *DatumAlloc) NewDGeography(v DGeography) *DGeography {
   256  	if a.AllocSize == 0 {
   257  		a.AllocSize = defaultDatumAllocSize
   258  	}
   259  	buf := &a.dgeographyAlloc
   260  	if len(*buf) == 0 {
   261  		*buf = make([]DGeography, a.AllocSize)
   262  	}
   263  	r := &(*buf)[0]
   264  	*r = v
   265  	*buf = (*buf)[1:]
   266  	return r
   267  }
   268  
   269  // NewDVoid allocates a new DVoid.
   270  func (a *DatumAlloc) NewDVoid() *DVoid {
   271  	if a.AllocSize == 0 {
   272  		a.AllocSize = defaultDatumAllocSize
   273  	}
   274  	buf := &a.dvoidAlloc
   275  	if len(*buf) == 0 {
   276  		*buf = make([]DVoid, a.AllocSize)
   277  	}
   278  	r := &(*buf)[0]
   279  	*buf = (*buf)[1:]
   280  	return r
   281  }
   282  
   283  // NewDGeographyEmpty allocates a new empty DGeography for unmarshalling.
   284  // After unmarshalling, DoneInitNewDGeo must be called to return unused
   285  // pre-allocated space to the DatumAlloc.
   286  func (a *DatumAlloc) NewDGeographyEmpty() *DGeography {
   287  	r := a.NewDGeography(DGeography{})
   288  	a.giveBytesToEWKB(r.SpatialObjectRef())
   289  	return r
   290  }
   291  
   292  // DoneInitNewDGeo is called after unmarshalling a SpatialObject allocated via
   293  // NewDGeographyEmpty/NewDGeometryEmpty, to return space to the DatumAlloc.
   294  func (a *DatumAlloc) DoneInitNewDGeo(so *geopb.SpatialObject) {
   295  	// Don't allocate next time if the allocation was wasted and there is no way
   296  	// to pre-allocate enough. This is just a crude heuristic to avoid wasting
   297  	// allocations if the EWKBs are very large.
   298  	a.lastEWKBBeyondAllocSize = len(so.EWKB) > maxEWKBAllocSize
   299  	c := cap(so.EWKB)
   300  	l := len(so.EWKB)
   301  	if (c - l) > l {
   302  		a.ewkbAlloc = so.EWKB[l:l:c]
   303  		so.EWKB = so.EWKB[:l:l]
   304  	}
   305  }
   306  
   307  // NewDGeometry allocates a DGeometry.
   308  func (a *DatumAlloc) NewDGeometry(v DGeometry) *DGeometry {
   309  	if a.AllocSize == 0 {
   310  		a.AllocSize = defaultDatumAllocSize
   311  	}
   312  	buf := &a.dgeometryAlloc
   313  	if len(*buf) == 0 {
   314  		*buf = make([]DGeometry, a.AllocSize)
   315  	}
   316  	r := &(*buf)[0]
   317  	*r = v
   318  	*buf = (*buf)[1:]
   319  	return r
   320  }
   321  
   322  // NewDGeometryEmpty allocates a new empty DGeometry for unmarshalling. After
   323  // unmarshalling, DoneInitNewDGeo must be called to return unused
   324  // pre-allocated space to the DatumAlloc.
   325  func (a *DatumAlloc) NewDGeometryEmpty() *DGeometry {
   326  	r := a.NewDGeometry(DGeometry{})
   327  	a.giveBytesToEWKB(r.SpatialObjectRef())
   328  	return r
   329  }
   330  
   331  func (a *DatumAlloc) giveBytesToEWKB(so *geopb.SpatialObject) {
   332  	if a.ewkbAlloc == nil && !a.lastEWKBBeyondAllocSize {
   333  		if a.curEWKBAllocSize == 0 {
   334  			a.curEWKBAllocSize = defaultEWKBAllocSize
   335  		} else if a.curEWKBAllocSize < maxEWKBAllocSize {
   336  			a.curEWKBAllocSize *= 2
   337  		}
   338  		so.EWKB = make([]byte, 0, a.curEWKBAllocSize)
   339  	} else {
   340  		so.EWKB = a.ewkbAlloc
   341  		a.ewkbAlloc = nil
   342  	}
   343  }
   344  
   345  // NewDTime allocates a DTime.
   346  func (a *DatumAlloc) NewDTime(v DTime) *DTime {
   347  	if a.AllocSize == 0 {
   348  		a.AllocSize = defaultDatumAllocSize
   349  	}
   350  	buf := &a.dtimeAlloc
   351  	if len(*buf) == 0 {
   352  		*buf = make([]DTime, a.AllocSize)
   353  	}
   354  	r := &(*buf)[0]
   355  	*r = v
   356  	*buf = (*buf)[1:]
   357  	return r
   358  }
   359  
   360  // NewDTimeTZ allocates a DTimeTZ.
   361  func (a *DatumAlloc) NewDTimeTZ(v DTimeTZ) *DTimeTZ {
   362  	if a.AllocSize == 0 {
   363  		a.AllocSize = defaultDatumAllocSize
   364  	}
   365  	buf := &a.dtimetzAlloc
   366  	if len(*buf) == 0 {
   367  		*buf = make([]DTimeTZ, a.AllocSize)
   368  	}
   369  	r := &(*buf)[0]
   370  	*r = v
   371  	*buf = (*buf)[1:]
   372  	return r
   373  }
   374  
   375  // NewDTimestamp allocates a DTimestamp.
   376  func (a *DatumAlloc) NewDTimestamp(v DTimestamp) *DTimestamp {
   377  	if a.AllocSize == 0 {
   378  		a.AllocSize = defaultDatumAllocSize
   379  	}
   380  	buf := &a.dtimestampAlloc
   381  	if len(*buf) == 0 {
   382  		*buf = make([]DTimestamp, a.AllocSize)
   383  	}
   384  	r := &(*buf)[0]
   385  	*r = v
   386  	*buf = (*buf)[1:]
   387  	return r
   388  }
   389  
   390  // NewDTimestampTZ allocates a DTimestampTZ.
   391  func (a *DatumAlloc) NewDTimestampTZ(v DTimestampTZ) *DTimestampTZ {
   392  	if a.AllocSize == 0 {
   393  		a.AllocSize = defaultDatumAllocSize
   394  	}
   395  	buf := &a.dtimestampTzAlloc
   396  	if len(*buf) == 0 {
   397  		*buf = make([]DTimestampTZ, a.AllocSize)
   398  	}
   399  	r := &(*buf)[0]
   400  	*r = v
   401  	*buf = (*buf)[1:]
   402  	return r
   403  }
   404  
   405  // NewDInterval allocates a DInterval.
   406  func (a *DatumAlloc) NewDInterval(v DInterval) *DInterval {
   407  	if a.AllocSize == 0 {
   408  		a.AllocSize = defaultDatumAllocSize
   409  	}
   410  	buf := &a.dintervalAlloc
   411  	if len(*buf) == 0 {
   412  		*buf = make([]DInterval, a.AllocSize)
   413  	}
   414  	r := &(*buf)[0]
   415  	*r = v
   416  	*buf = (*buf)[1:]
   417  	return r
   418  }
   419  
   420  // NewDUuid allocates a DUuid.
   421  func (a *DatumAlloc) NewDUuid(v DUuid) *DUuid {
   422  	if a.AllocSize == 0 {
   423  		a.AllocSize = defaultDatumAllocSize
   424  	}
   425  	buf := &a.duuidAlloc
   426  	if len(*buf) == 0 {
   427  		*buf = make([]DUuid, a.AllocSize)
   428  	}
   429  	r := &(*buf)[0]
   430  	*r = v
   431  	*buf = (*buf)[1:]
   432  	return r
   433  }
   434  
   435  // NewDIPAddr allocates a DIPAddr.
   436  func (a *DatumAlloc) NewDIPAddr(v DIPAddr) *DIPAddr {
   437  	if a.AllocSize == 0 {
   438  		a.AllocSize = defaultDatumAllocSize
   439  	}
   440  	buf := &a.dipnetAlloc
   441  	if len(*buf) == 0 {
   442  		*buf = make([]DIPAddr, a.AllocSize)
   443  	}
   444  	r := &(*buf)[0]
   445  	*r = v
   446  	*buf = (*buf)[1:]
   447  	return r
   448  }
   449  
   450  // NewDJSON allocates a DJSON.
   451  func (a *DatumAlloc) NewDJSON(v DJSON) *DJSON {
   452  	if a.AllocSize == 0 {
   453  		a.AllocSize = defaultDatumAllocSize
   454  	}
   455  	buf := &a.djsonAlloc
   456  	if len(*buf) == 0 {
   457  		*buf = make([]DJSON, a.AllocSize)
   458  	}
   459  	r := &(*buf)[0]
   460  	*r = v
   461  	*buf = (*buf)[1:]
   462  	return r
   463  }
   464  
   465  // NewDTuple allocates a DTuple.
   466  func (a *DatumAlloc) NewDTuple(v DTuple) *DTuple {
   467  	if a.AllocSize == 0 {
   468  		a.AllocSize = defaultDatumAllocSize
   469  	}
   470  	buf := &a.dtupleAlloc
   471  	if len(*buf) == 0 {
   472  		*buf = make([]DTuple, a.AllocSize)
   473  	}
   474  	r := &(*buf)[0]
   475  	*r = v
   476  	*buf = (*buf)[1:]
   477  	return r
   478  }
   479  
   480  // NewDOid allocates a DOid.
   481  func (a *DatumAlloc) NewDOid(v DOid) Datum {
   482  	if a.AllocSize == 0 {
   483  		a.AllocSize = defaultDatumAllocSize
   484  	}
   485  	buf := &a.doidAlloc
   486  	if len(*buf) == 0 {
   487  		*buf = make([]DOid, a.AllocSize)
   488  	}
   489  	r := &(*buf)[0]
   490  	*r = v
   491  	*buf = (*buf)[1:]
   492  	return r
   493  }