github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/workload/tpch/generate.go (about) 1 // Copyright 2020 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 tpch 12 13 import ( 14 "time" 15 16 "github.com/cockroachdb/cockroach/pkg/col/coldata" 17 "github.com/cockroachdb/cockroach/pkg/sql/types" 18 "github.com/cockroachdb/cockroach/pkg/util/bufalloc" 19 "github.com/cockroachdb/cockroach/pkg/util/timeutil/pgdate" 20 "golang.org/x/exp/rand" 21 ) 22 23 var regionNames = [...]string{`AFRICA`, `AMERICA`, `ASIA`, `EUROPE`, `MIDDLE EAST`} 24 var nations = [...]struct { 25 name string 26 regionKey int 27 }{ 28 {name: `ALGERIA`, regionKey: 0}, 29 {name: `ARGENTINA`, regionKey: 1}, 30 {name: `BRAZIL`, regionKey: 1}, 31 {name: `CANADA`, regionKey: 1}, 32 {name: `EGYPT`, regionKey: 4}, 33 {name: `ETHIOPIA`, regionKey: 0}, 34 {name: `FRANCE`, regionKey: 3}, 35 {name: `GERMANY`, regionKey: 3}, 36 {name: `INDIA`, regionKey: 2}, 37 {name: `INDONESIA`, regionKey: 2}, 38 {name: `IRAN`, regionKey: 4}, 39 {name: `IRAQ`, regionKey: 4}, 40 {name: `JAPAN`, regionKey: 2}, 41 {name: `JORDAN`, regionKey: 4}, 42 {name: `KENYA`, regionKey: 0}, 43 {name: `MOROCCO`, regionKey: 0}, 44 {name: `MOZAMBIQUE`, regionKey: 0}, 45 {name: `PERU`, regionKey: 1}, 46 {name: `CHINA`, regionKey: 2}, 47 {name: `ROMANIA`, regionKey: 3}, 48 {name: `SAUDI ARABIA`, regionKey: 4}, 49 {name: `VIETNAM`, regionKey: 2}, 50 {name: `RUSSIA`, regionKey: 3}, 51 {name: `UNITED KINGDOM`, regionKey: 3}, 52 {name: `UNITED STATES`, regionKey: 1}, 53 } 54 55 var regionTypes = []*types.T{ 56 types.Int2, 57 types.Bytes, 58 types.Bytes, 59 } 60 61 func (w *tpch) tpchRegionInitialRowBatch( 62 batchIdx int, cb coldata.Batch, a *bufalloc.ByteAllocator, 63 ) { 64 l := w.localsPool.Get().(*generateLocals) 65 defer w.localsPool.Put(l) 66 rng := l.rng 67 rng.Seed(w.seed + uint64(batchIdx)) 68 69 regionKey := batchIdx 70 cb.Reset(regionTypes, 1, coldata.StandardColumnFactory) 71 cb.ColVec(0).Int16()[0] = int16(regionKey) // r_regionkey 72 cb.ColVec(1).Bytes().Set(0, []byte(regionNames[regionKey])) // r_name 73 cb.ColVec(2).Bytes().Set(0, w.textPool.randString(rng, 31, 115)) // r_comment 74 } 75 76 var nationTypes = []*types.T{ 77 types.Int2, 78 types.Bytes, 79 types.Int2, 80 types.Bytes, 81 } 82 83 func (w *tpch) tpchNationInitialRowBatch( 84 batchIdx int, cb coldata.Batch, a *bufalloc.ByteAllocator, 85 ) { 86 l := w.localsPool.Get().(*generateLocals) 87 defer w.localsPool.Put(l) 88 rng := l.rng 89 rng.Seed(w.seed + uint64(batchIdx)) 90 91 nationKey := batchIdx 92 nation := nations[nationKey] 93 cb.Reset(nationTypes, 1, coldata.StandardColumnFactory) 94 cb.ColVec(0).Int16()[0] = int16(nationKey) // n_nationkey 95 cb.ColVec(1).Bytes().Set(0, []byte(nation.name)) // n_name 96 cb.ColVec(2).Int16()[0] = int16(nation.regionKey) // n_regionkey 97 cb.ColVec(3).Bytes().Set(0, w.textPool.randString(rng, 31, 115)) // r_comment 98 } 99 100 var supplierTypes = []*types.T{ 101 types.Int, 102 types.Bytes, 103 types.Bytes, 104 types.Int2, 105 types.Bytes, 106 types.Float, 107 types.Bytes, 108 } 109 110 func (w *tpch) tpchSupplierInitialRowBatch( 111 batchIdx int, cb coldata.Batch, a *bufalloc.ByteAllocator, 112 ) { 113 l := w.localsPool.Get().(*generateLocals) 114 defer w.localsPool.Put(l) 115 rng := l.rng 116 rng.Seed(w.seed + uint64(batchIdx)) 117 118 suppKey := int64(batchIdx) + 1 119 nationKey := int16(randInt(rng, 0, 24)) 120 cb.Reset(supplierTypes, 1, coldata.StandardColumnFactory) 121 cb.ColVec(0).Int64()[0] = suppKey // s_suppkey 122 cb.ColVec(1).Bytes().Set(0, supplierName(a, suppKey)) // s_name 123 cb.ColVec(2).Bytes().Set(0, randVString(rng, a, 10, 40)) // s_address 124 cb.ColVec(3).Int16()[0] = nationKey // s_nationkey 125 cb.ColVec(4).Bytes().Set(0, randPhone(rng, a, nationKey)) // s_phone 126 cb.ColVec(5).Float64()[0] = float64(randFloat(rng, -99999, 999999, 100)) // s_acctbal 127 // TODO(jordan): this needs to sometimes have Customer Complaints or Customer Recommends. see 4.2.3. 128 cb.ColVec(6).Bytes().Set(0, w.textPool.randString(rng, 25, 100)) // s_comment 129 } 130 131 var partTypes = []*types.T{ 132 types.Int, 133 types.Bytes, 134 types.Bytes, 135 types.Bytes, 136 types.Bytes, 137 types.Int2, 138 types.Bytes, 139 types.Float, 140 types.Bytes, 141 } 142 143 func makeRetailPriceFromPartKey(partKey int) float32 { 144 return float32(90000+((partKey/10)%20001)+100*(partKey%1000)) / 100 145 } 146 147 func (w *tpch) tpchPartInitialRowBatch(batchIdx int, cb coldata.Batch, a *bufalloc.ByteAllocator) { 148 l := w.localsPool.Get().(*generateLocals) 149 defer w.localsPool.Put(l) 150 rng := l.rng 151 rng.Seed(w.seed + uint64(batchIdx)) 152 153 partKey := batchIdx + 1 154 cb.Reset(partTypes, 1, coldata.StandardColumnFactory) 155 156 // P_PARTKEY unique within [SF * 200,000]. 157 cb.ColVec(0).Int64()[0] = int64(partKey) 158 // P_NAME generated by concatenating five unique randomly selected part name strings. 159 cb.ColVec(1).Bytes().Set(0, randPartName(rng, l.namePerm, a)) 160 m, mfgr := randMfgr(rng, a) 161 // P_MFGR text appended with digit ["Manufacturer#",M], where M = random value [1,5]. 162 cb.ColVec(2).Bytes().Set(0, mfgr) // 163 // P_BRAND text appended with digits ["Brand#",MN], where N = random value [1,5] and M is defined 164 // while generating P_MFGR. 165 cb.ColVec(3).Bytes().Set(0, randBrand(rng, a, m)) 166 // P_TYPE random string [Types]. 167 cb.ColVec(4).Bytes().Set(0, randType(rng, a)) 168 // P_SIZE random value [1 .. 50]. 169 cb.ColVec(5).Int16()[0] = int16(randInt(rng, 1, 50)) 170 // P_CONTAINER random string [Containers]. 171 cb.ColVec(6).Bytes().Set(0, randContainer(rng, a)) 172 // P_RETAILPRICE = (90000 + ((P_PARTKEY/10) modulo 20001 ) + 100 * (P_PARTKEY modulo 1000))/100. 173 cb.ColVec(7).Float64()[0] = float64(makeRetailPriceFromPartKey(partKey)) 174 // P_COMMENT text string [5,22]. 175 cb.ColVec(8).Bytes().Set(0, w.textPool.randString(rng, 5, 22)) 176 } 177 178 var partSuppTypes = []*types.T{ 179 types.Int, 180 types.Int, 181 types.Int2, 182 types.Float, 183 types.Bytes, 184 } 185 186 func (w *tpch) tpchPartSuppInitialRowBatch( 187 batchIdx int, cb coldata.Batch, a *bufalloc.ByteAllocator, 188 ) { 189 l := w.localsPool.Get().(*generateLocals) 190 defer w.localsPool.Put(l) 191 rng := l.rng 192 rng.Seed(w.seed + uint64(batchIdx)) 193 194 partKey := batchIdx + 1 195 cb.Reset(partSuppTypes, numPartSuppPerPart, coldata.StandardColumnFactory) 196 197 // P_PARTKEY unique within [SF * 200,000]. 198 partKeyCol := cb.ColVec(0).Int64() 199 suppKeyCol := cb.ColVec(1).Int64() 200 availQtyCol := cb.ColVec(2).Int16() 201 supplyCostCol := cb.ColVec(3).Float64() 202 commentCol := cb.ColVec(4).Bytes() 203 204 // For each row in the PART table, four rows in PartSupp table. 205 for i := 0; i < numPartSuppPerPart; i++ { 206 // PS_PARTKEY = P_PARTKEY. 207 partKeyCol[i] = int64(partKey) 208 // PS_SUPPKEY = (ps_partkey + (i * (( S/4 ) + (int)(ps_partkey-1 )/S)))) 209 // modulo S + 1 where i is the ith supplier within [0 .. 3] and S = SF * 210 // 10,000. 211 s := w.scaleFactor * 10000 212 suppKeyCol[i] = int64((partKey+(i*((s/numPartSuppPerPart)+(partKey-1)/s)))%s + 1) 213 // PS_AVAILQTY random value [1 .. 9,999]. 214 availQtyCol[i] = int16(randInt(rng, 1, 9999)) 215 // PS_SUPPLYCOST random value [1.00 .. 1,000.00]. 216 supplyCostCol[i] = float64(randFloat(rng, 1, 1000, 100)) 217 // PS_COMMENT text string [49,198]. 218 commentCol.Set(i, w.textPool.randString(rng, 49, 198)) 219 } 220 } 221 222 var customerTypes = []*types.T{ 223 types.Int, 224 types.Bytes, 225 types.Bytes, 226 types.Int2, 227 types.Bytes, 228 types.Float, 229 types.Bytes, 230 types.Bytes, 231 } 232 233 func (w *tpch) tpchCustomerInitialRowBatch( 234 batchIdx int, cb coldata.Batch, a *bufalloc.ByteAllocator, 235 ) { 236 l := w.localsPool.Get().(*generateLocals) 237 defer w.localsPool.Put(l) 238 rng := l.rng 239 rng.Seed(w.seed + uint64(batchIdx)) 240 241 custKey := int64(batchIdx) + 1 242 cb.Reset(customerTypes, 1, coldata.StandardColumnFactory) 243 244 // C_CUSTKEY unique within [SF * 150,000]. 245 cb.ColVec(0).Int64()[0] = custKey 246 // C_NAME text appended with minimum 9 digits with leading zeros ["Customer#", C_CUSTKEY]. 247 cb.ColVec(1).Bytes().Set(0, customerName(a, custKey)) 248 // C_ADDRESS random v-string [10,40]. 249 cb.ColVec(2).Bytes().Set(0, randVString(rng, a, 10, 40)) 250 nationKey := int16(randInt(rng, 0, 24)) 251 // C_NATIONKEY random value [0 .. 24]. 252 cb.ColVec(3).Int16()[0] = nationKey 253 // C_PHONE generated according to Clause 4.2.2.9. 254 cb.ColVec(4).Bytes().Set(0, randPhone(rng, a, nationKey)) 255 // C_ACCTBAL random value [-999.99 .. 9,999.99]. 256 cb.ColVec(5).Float64()[0] = float64(randFloat(rng, -99999, 999999, 100)) 257 // C_MKTSEGMENT random string [Segments]. 258 cb.ColVec(6).Bytes().Set(0, randSegment(rng)) 259 // C_COMMENT text string [29,116]. 260 cb.ColVec(7).Bytes().Set(0, w.textPool.randString(rng, 29, 116)) 261 } 262 263 const sparseBits = 2 264 const sparseKeep = 3 265 266 var ( 267 startDate = time.Date(1992, 1, 1, 0, 0, 0, 0, time.UTC) 268 currentDate = time.Date(1995, 6, 17, 0, 0, 0, 0, time.UTC) 269 endDate = time.Date(1998, 12, 31, 0, 0, 0, 0, time.UTC) 270 271 startDateDays int64 272 currentDateDays int64 273 endDateDays int64 274 ) 275 276 func init() { 277 var d pgdate.Date 278 var err error 279 d, err = pgdate.MakeDateFromTime(startDate) 280 if err != nil { 281 panic(err) 282 } 283 startDateDays = d.UnixEpochDaysWithOrig() 284 d, err = pgdate.MakeDateFromTime(currentDate) 285 if err != nil { 286 panic(err) 287 } 288 currentDateDays = d.UnixEpochDaysWithOrig() 289 d, err = pgdate.MakeDateFromTime(endDate) 290 if err != nil { 291 panic(err) 292 } 293 endDateDays = d.UnixEpochDaysWithOrig() 294 } 295 296 func getOrderKey(orderIdx int) int { 297 // This method is taken from dbgen's build.c: mk_sparse. Given an input i, it 298 // returns the ith order id in the tpch database, by using only the first 8 299 // integers from every 32 integers. 300 301 // Our input is 0-indexed; convert to 1-index. 302 i := orderIdx + 1 303 304 lowBits := i & ((1 << sparseKeep) - 1) 305 i = i >> sparseKeep 306 i = i << sparseBits 307 i = i << sparseKeep 308 i += lowBits 309 return i 310 } 311 312 type orderSharedRandomData struct { 313 nOrders int 314 orderDate int 315 partKeys []int 316 shipDates []int64 317 quantities []float32 318 discount []float32 319 tax []float32 320 321 allO bool 322 allF bool 323 } 324 325 var ordersTypes = []*types.T{ 326 types.Int, 327 types.Int, 328 types.Bytes, 329 types.Float, 330 types.Int, 331 types.Bytes, 332 types.Bytes, 333 types.Int2, 334 types.Bytes, 335 } 336 337 func populateSharedData(rng *rand.Rand, seed uint64, sf int, data *orderSharedRandomData) { 338 // Seed the rng here to force orders and lineitems to get the same results. 339 rng.Seed(seed) 340 341 data.nOrders = randInt(rng, 1, 7) 342 data.orderDate = randInt(rng, int(startDateDays), int(endDateDays-151)) 343 data.partKeys = data.partKeys[:data.nOrders] 344 data.shipDates = data.shipDates[:data.nOrders] 345 data.quantities = data.quantities[:data.nOrders] 346 data.discount = data.discount[:data.nOrders] 347 data.tax = data.tax[:data.nOrders] 348 // These will be invalidated in the loop. 349 data.allF = true 350 data.allO = true 351 352 for i := 0; i < data.nOrders; i++ { 353 shipDate := int64(data.orderDate + randInt(rng, 1, 121)) 354 data.shipDates[i] = shipDate 355 if shipDate > currentDateDays { 356 data.allF = false 357 } else { 358 data.allO = false 359 } 360 data.partKeys[i] = randInt(rng, 1, sf*numPartPerSF) 361 data.quantities[i] = float32(randInt(rng, 1, 50)) 362 data.discount[i] = randFloat(rng, 0, 10, 100) 363 data.tax[i] = randFloat(rng, 0, 8, 100) 364 } 365 } 366 367 func (w *tpch) tpchOrdersInitialRowBatch( 368 batchIdx int, cb coldata.Batch, a *bufalloc.ByteAllocator, 369 ) { 370 l := w.localsPool.Get().(*generateLocals) 371 defer w.localsPool.Put(l) 372 rng := l.rng 373 374 cb.Reset(ordersTypes, numOrderPerCustomer, coldata.StandardColumnFactory) 375 376 orderKeyCol := cb.ColVec(0).Int64() 377 custKeyCol := cb.ColVec(1).Int64() 378 orderStatusCol := cb.ColVec(2).Bytes() 379 totalPriceCol := cb.ColVec(3).Float64() 380 orderDateCol := cb.ColVec(4).Int64() 381 orderPriorityCol := cb.ColVec(5).Bytes() 382 clerkCol := cb.ColVec(6).Bytes() 383 shipPriorityCol := cb.ColVec(7).Int16() 384 commentCol := cb.ColVec(8).Bytes() 385 386 orderStartIdx := numOrderPerCustomer * batchIdx 387 for i := 0; i < numOrderPerCustomer; i++ { 388 populateSharedData(rng, w.seed+uint64(orderStartIdx+i), w.scaleFactor, l.orderData) 389 390 orderKeyCol[i] = int64(getOrderKey(orderStartIdx + i)) 391 // O_CUSTKEY = random value c [1 .. (SF * 150,000)], s.t. c % 3 != 0. 392 numCust := w.scaleFactor * numCustomerPerSF 393 custKeyCol[i] = int64((randInt(rng, 1, w.scaleFactor*(numCustomerPerSF/3))*3 + rng.Intn(2) + 1) % numCust) 394 // O_ORDERSTATUS = F if all lineitems.LINESTATUS = F; O if all O; P 395 // otherwise. 396 if l.orderData.allF { 397 orderStatusCol.Set(i, []byte("F")) 398 } else if l.orderData.allO { 399 orderStatusCol.Set(i, []byte("O")) 400 } else { 401 orderStatusCol.Set(i, []byte("P")) 402 } 403 totalPrice := float32(0) 404 for j := 0; j < l.orderData.nOrders; j++ { 405 ep := l.orderData.quantities[j] * makeRetailPriceFromPartKey(l.orderData.partKeys[j]) 406 totalPrice += ep * (1 + l.orderData.tax[j]) * (1 - l.orderData.discount[j]) 407 } 408 // O_TOTALPRICE computed as: 409 // sum (L_EXTENDEDPRICE * (1+L_TAX) * (1-L_DISCOUNT)) for all LINEITEM of 410 // this order. 411 totalPriceCol[i] = float64(totalPrice) 412 // O_ORDERDATE uniformly distributed between STARTDATE and 413 // (ENDDATE - 151 days). 414 orderDateCol[i] = int64(l.orderData.orderDate) 415 // O_ORDERPRIORITY random string [Priorities]. 416 orderPriorityCol.Set(i, randPriority(rng)) 417 // O_CLERK text appended with minimum 9 digits with leading zeros 418 // ["Clerk#", C] where C = random value [000000001 .. (SF * 1000)]. 419 clerkCol.Set(i, randClerk(rng, a, w.scaleFactor)) 420 // O_SHIPPRIORITY set to 0. 421 shipPriorityCol[i] = 0 422 // O_COMMENT text string [19,78]. 423 commentCol.Set(i, w.textPool.randString(rng, 19, 78)) 424 } 425 } 426 427 var lineItemTypes = []*types.T{ 428 types.Int, 429 types.Int, 430 types.Int, 431 types.Int2, 432 types.Float, 433 types.Float, 434 types.Float, 435 types.Float, 436 types.Bytes, 437 types.Bytes, 438 types.Int, 439 types.Int, 440 types.Int, 441 types.Bytes, 442 types.Bytes, 443 types.Bytes, 444 } 445 446 func (w *tpch) tpchLineItemInitialRowBatch( 447 batchIdx int, cb coldata.Batch, a *bufalloc.ByteAllocator, 448 ) { 449 l := w.localsPool.Get().(*generateLocals) 450 defer w.localsPool.Put(l) 451 rng := l.rng 452 453 cb.Reset(lineItemTypes, numOrderPerCustomer*7, coldata.StandardColumnFactory) 454 455 orderKeyCol := cb.ColVec(0).Int64() 456 partKeyCol := cb.ColVec(1).Int64() 457 suppKeyCol := cb.ColVec(2).Int64() 458 lineNumberCol := cb.ColVec(3).Int16() 459 quantityCol := cb.ColVec(4).Float64() 460 extendedPriceCol := cb.ColVec(5).Float64() 461 discountCol := cb.ColVec(6).Float64() 462 taxCol := cb.ColVec(7).Float64() 463 returnFlagCol := cb.ColVec(8).Bytes() 464 lineStatusCol := cb.ColVec(9).Bytes() 465 shipDateCol := cb.ColVec(10).Int64() 466 commitDateCol := cb.ColVec(11).Int64() 467 receiptDateCol := cb.ColVec(12).Int64() 468 shipInstructCol := cb.ColVec(13).Bytes() 469 shipModeCol := cb.ColVec(14).Bytes() 470 commentCol := cb.ColVec(15).Bytes() 471 472 orderStartIdx := numOrderPerCustomer * batchIdx 473 s := w.scaleFactor * 10000 474 offset := 0 475 for i := 0; i < numOrderPerCustomer; i++ { 476 populateSharedData(rng, w.seed+uint64(orderStartIdx+i), w.scaleFactor, l.orderData) 477 478 orderKey := int64(getOrderKey(orderStartIdx + i)) 479 for j := 0; j < l.orderData.nOrders; j++ { 480 idx := offset + j 481 // L_ORDERKEY = O_ORDERKEY. 482 orderKeyCol[idx] = orderKey 483 partKey := l.orderData.partKeys[j] 484 // L_PARTKEY random value [1 .. (SF * 200,000)]. 485 partKeyCol[idx] = int64(partKey) 486 // L_SUPPKEY = (L_PARTKEY + (i * (( S/4 ) + (int)(L_partkey-1 )/S)))) 487 // modulo S + 1 where i is the corresponding supplier within [0 .. 3] and 488 // S = SF * 10,000. 489 suppKey := (partKey+(randInt(rng, 0, 3)*((s/4)+(partKey-1)/s)))%s + 1 490 suppKeyCol[idx] = int64(suppKey) 491 // L_LINENUMBER unique within [7]. 492 lineNumberCol[idx] = int16(j) 493 // L_QUANTITY random value [1 .. 50]. 494 quantityCol[idx] = float64(l.orderData.quantities[j]) 495 // L_EXTENDEDPRICE = L_QUANTITY * P_RETAILPRICE where P_RETAILPRICE is 496 // from the part with P_PARTKEY = L_PARTKEY. 497 extendedPriceCol[idx] = float64(l.orderData.quantities[j] * makeRetailPriceFromPartKey(partKey)) 498 // L_DISCOUNT random value [0.00 .. 0.10]. 499 discountCol[idx] = float64(l.orderData.discount[j]) 500 // L_TAX random value [0.00 .. 0.08]. 501 taxCol[idx] = float64(l.orderData.tax[j]) 502 // L_SHIPDATE = O_ORDERDATE + random value [1 .. 121]. 503 shipDate := l.orderData.shipDates[j] 504 shipDateCol[idx] = shipDate 505 // L_RECEIPTDATE = L_SHIPDATE + random value [1 .. 30]. 506 receiptDate := shipDate + int64(randInt(rng, 1, 30)) 507 receiptDateCol[idx] = receiptDate 508 // L_COMMITDATE = O_ORDERDATE + random value [30 .. 90]. 509 commitDateCol[idx] = int64(l.orderData.orderDate + randInt(rng, 30, 90)) 510 // L_RETURNFLAG set to a value selected as follows: 511 // If L_RECEIPTDATE <= CURRENTDATE 512 // then either "R" or "A" is selected at random 513 // else "N" is selected. 514 if receiptDate < currentDateDays { 515 if rng.Intn(2) == 0 { 516 returnFlagCol.Set(idx, []byte("R")) 517 } else { 518 returnFlagCol.Set(idx, []byte("A")) 519 } 520 } else { 521 returnFlagCol.Set(idx, []byte("N")) 522 } 523 // L_LINESTATUS set the following value: 524 // "O" if L_SHIPDATE > CURRENTDATE 525 // "F" otherwise. 526 if shipDate > currentDateDays { 527 lineStatusCol.Set(idx, []byte("O")) 528 } else { 529 lineStatusCol.Set(idx, []byte("F")) 530 } 531 // L_SHIPINSTRUCT random string [Instructions]. 532 shipInstructCol.Set(idx, randInstruction(rng)) 533 // L_SHIPMODE random string [Modes]. 534 shipModeCol.Set(idx, randMode(rng)) 535 // L_COMMENT text string [10,43]. 536 commentCol.Set(idx, w.textPool.randString(rng, 10, 43)) 537 } 538 offset += l.orderData.nOrders 539 } 540 cb.SetLength(offset) 541 }