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  }