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 }