| 1 | /* |
| 2 | * $Id: build.c,v 1.5 2009/06/28 14:01:08 jms Exp $ |
| 3 | * |
| 4 | * Revision History =================== $Log: build.c,v $ |
| 5 | * Revision History =================== Revision 1.5 2009/06/28 14:01:08 jms |
| 6 | * Revision History =================== bug fix for DOP |
| 7 | * Revision History =================== Revision 1.4 |
| 8 | * 2005/10/28 02:56:22 jms add platform-specific printf formats to allow for |
| 9 | * DSS_HUGE data type |
| 10 | * |
| 11 | * Revision 1.3 2005/10/14 23:16:54 jms fix for answer set compliance |
| 12 | * |
| 13 | * Revision 1.2 2005/01/03 20:08:58 jms change line terminations |
| 14 | * |
| 15 | * Revision 1.1.1.1 2004/11/24 23:31:46 jms re-establish external server |
| 16 | * |
| 17 | * Revision 1.3 2004/04/07 20:17:29 jms bug #58 (join fails between |
| 18 | * order/lineitem) |
| 19 | * |
| 20 | * Revision 1.2 2004/01/22 05:49:29 jms AIX porting (AIX 5.1) |
| 21 | * |
| 22 | * Revision 1.1.1.1 2003/08/08 21:35:26 jms recreation after CVS crash |
| 23 | * |
| 24 | * Revision 1.3 2003/08/08 21:35:26 jms first integration of rng64 for |
| 25 | * o_custkey and l_partkey |
| 26 | * |
| 27 | * Revision 1.2 2003/08/07 17:58:34 jms Convery RNG to 64bit space as |
| 28 | * preparation for new large scale RNG |
| 29 | * |
| 30 | * Revision 1.1.1.1 2003/04/03 18:54:21 jms initial checkin |
| 31 | * |
| 32 | * |
| 33 | */ |
| 34 | /* stuff related to the customer table */ |
| 35 | #include <stdio.h> |
| 36 | #include <string.h> |
| 37 | #ifndef VMS |
| 38 | #include <sys/types.h> |
| 39 | #endif |
| 40 | #if defined(SUN) |
| 41 | #include <unistd.h> |
| 42 | #endif |
| 43 | #include <math.h> |
| 44 | |
| 45 | #include "dss.h" |
| 46 | #include "dsstypes.h" |
| 47 | #ifdef ADHOC |
| 48 | #include "adhoc.h" |
| 49 | extern adhoc_t adhocs[]; |
| 50 | #endif /* ADHOC */ |
| 51 | #include "rng64.h" |
| 52 | |
| 53 | #define LEAP_ADJ(yr, mnth) \ |
| 54 | ((LEAP(yr) && (mnth) >= 2) ? 1 : 0) |
| 55 | #define JDAY_BASE 8035 /* start from 1/1/70 a la unix */ |
| 56 | #define JMNTH_BASE (-70 * 12) /* start from 1/1/70 a la unix */ |
| 57 | #define JDAY(date) ((date) - STARTDATE + JDAY_BASE + 1) |
| 58 | #define PART_SUPP_BRIDGE(tgt, p, s) \ |
| 59 | { \ |
| 60 | DSS_HUGE tot_scnt = tdefs[SUPP].base * scale; \ |
| 61 | tgt = (p + s * (tot_scnt / SUPP_PER_PART + \ |
| 62 | (long) ((p - 1) / tot_scnt))) % tot_scnt + 1; \ |
| 63 | } |
| 64 | #define V_STR(avg, sd, tgt) a_rnd((int)(avg * V_STR_LOW),(int)(avg * V_STR_HGH), sd, tgt) |
| 65 | #define TEXT(avg, sd, tgt) dbg_text(tgt, (int)(avg * V_STR_LOW),(int)(avg * V_STR_HGH), sd) |
| 66 | static void gen_phone PROTO((DSS_HUGE ind, char *target, long seed)); |
| 67 | |
| 68 | DSS_HUGE |
| 69 | rpb_routine(DSS_HUGE p) |
| 70 | { |
| 71 | DSS_HUGE price; |
| 72 | |
| 73 | price = 90000; |
| 74 | price += (p / 10) % 20001; /* limit contribution to $200 */ |
| 75 | price += (p % 1000) * 100; |
| 76 | |
| 77 | return (price); |
| 78 | } |
| 79 | |
| 80 | static void |
| 81 | gen_phone(DSS_HUGE ind, char *target, long seed) |
| 82 | { |
| 83 | DSS_HUGE acode, exchg, number; |
| 84 | |
| 85 | RANDOM(acode, 100, 999, seed); |
| 86 | RANDOM(exchg, 100, 999, seed); |
| 87 | RANDOM(number, 1000, 9999, seed); |
| 88 | |
| 89 | sprintf(target, "%02d" , (int) (10 + (ind % NATIONS_MAX))); |
| 90 | sprintf(target + 3, "%03d" , (int) acode); |
| 91 | sprintf(target + 7, "%03d" , (int) exchg); |
| 92 | sprintf(target + 11, "%04d" , (int) number); |
| 93 | target[2] = target[6] = target[10] = '-'; |
| 94 | |
| 95 | return; |
| 96 | } |
| 97 | |
| 98 | |
| 99 | |
| 100 | long |
| 101 | mk_cust(DSS_HUGE n_cust, customer_t * c) |
| 102 | { |
| 103 | DSS_HUGE i; |
| 104 | static int bInit = 0; |
| 105 | static char szFormat[100]; |
| 106 | |
| 107 | if (!bInit) |
| 108 | { |
| 109 | sprintf(szFormat, C_NAME_FMT, 9, HUGE_FORMAT + 1); |
| 110 | bInit = 1; |
| 111 | } |
| 112 | c->custkey = n_cust; |
| 113 | sprintf(c->name, szFormat, C_NAME_TAG, n_cust); |
| 114 | V_STR(C_ADDR_LEN, C_ADDR_SD, c->address); |
| 115 | c->alen = (int)strlen(c->address); |
| 116 | RANDOM(i, 0, (nations.count - 1), C_NTRG_SD); |
| 117 | c->nation_code = i; |
| 118 | gen_phone(i, c->phone, (long) C_PHNE_SD); |
| 119 | RANDOM(c->acctbal, C_ABAL_MIN, C_ABAL_MAX, C_ABAL_SD); |
| 120 | pick_str(&c_mseg_set, C_MSEG_SD, c->mktsegment); |
| 121 | TEXT(C_CMNT_LEN, C_CMNT_SD, c->comment); |
| 122 | c->clen = (int)strlen(c->comment); |
| 123 | |
| 124 | return (0); |
| 125 | } |
| 126 | |
| 127 | |
| 128 | /* |
| 129 | * generate the numbered order and its associated lineitems |
| 130 | */ |
| 131 | void |
| 132 | mk_sparse(DSS_HUGE i, DSS_HUGE * ok, long seq) |
| 133 | { |
| 134 | long low_bits; |
| 135 | |
| 136 | *ok = i; |
| 137 | low_bits = (long) (i & ((1 << SPARSE_KEEP) - 1)); |
| 138 | *ok = *ok >> SPARSE_KEEP; |
| 139 | *ok = *ok << SPARSE_BITS; |
| 140 | *ok += seq; |
| 141 | *ok = *ok << SPARSE_KEEP; |
| 142 | *ok += low_bits; |
| 143 | |
| 144 | |
| 145 | return; |
| 146 | } |
| 147 | |
| 148 | long |
| 149 | mk_order(DSS_HUGE index, order_t * o, long upd_num) |
| 150 | { |
| 151 | DSS_HUGE lcnt; |
| 152 | DSS_HUGE rprice; |
| 153 | long ocnt; |
| 154 | DSS_HUGE tmp_date; |
| 155 | DSS_HUGE s_date; |
| 156 | DSS_HUGE r_date; |
| 157 | DSS_HUGE c_date; |
| 158 | DSS_HUGE clk_num; |
| 159 | DSS_HUGE supp_num; |
| 160 | static char **asc_date = NULL; |
| 161 | char tmp_str[2]; |
| 162 | char **mk_ascdate PROTO((void)); |
| 163 | int delta = 1; |
| 164 | static int bInit = 0; |
| 165 | static char szFormat[100]; |
| 166 | |
| 167 | if (!bInit) |
| 168 | { |
| 169 | sprintf(szFormat, O_CLRK_FMT, 9, HUGE_FORMAT + 1); |
| 170 | bInit = 1; |
| 171 | } |
| 172 | if (asc_date == NULL) |
| 173 | asc_date = mk_ascdate(); |
| 174 | mk_sparse(index, &o->okey, |
| 175 | (upd_num == 0) ? 0 : 1 + upd_num / (10000 / UPD_PCT)); |
| 176 | if (scale >= 30000) |
| 177 | RANDOM64(o->custkey, O_CKEY_MIN, O_CKEY_MAX, O_CKEY_SD); |
| 178 | else |
| 179 | RANDOM(o->custkey, O_CKEY_MIN, O_CKEY_MAX, O_CKEY_SD); |
| 180 | while (o->custkey % CUST_MORTALITY == 0) |
| 181 | { |
| 182 | o->custkey += delta; |
| 183 | o->custkey = MIN(o->custkey, O_CKEY_MAX); |
| 184 | delta *= -1; |
| 185 | } |
| 186 | |
| 187 | |
| 188 | RANDOM(tmp_date, O_ODATE_MIN, O_ODATE_MAX, O_ODATE_SD); |
| 189 | strcpy(o->odate, asc_date[tmp_date - STARTDATE]); |
| 190 | |
| 191 | pick_str(&o_priority_set, O_PRIO_SD, o->opriority); |
| 192 | RANDOM(clk_num, 1, MAX((scale * O_CLRK_SCL), O_CLRK_SCL), O_CLRK_SD); |
| 193 | sprintf(o->clerk, szFormat, O_CLRK_TAG, clk_num); |
| 194 | TEXT(O_CMNT_LEN, O_CMNT_SD, o->comment); |
| 195 | o->clen = (int)strlen(o->comment); |
| 196 | #ifdef DEBUG |
| 197 | if (o->clen > O_CMNT_MAX) |
| 198 | fprintf(stderr, "comment error: O%d\n" , index); |
| 199 | #endif /* DEBUG */ |
| 200 | o->spriority = 0; |
| 201 | |
| 202 | o->totalprice = 0; |
| 203 | o->orderstatus = 'O'; |
| 204 | ocnt = 0; |
| 205 | |
| 206 | RANDOM(o->lines, O_LCNT_MIN, O_LCNT_MAX, O_LCNT_SD); |
| 207 | for (lcnt = 0; lcnt < o->lines; lcnt++) |
| 208 | { |
| 209 | o->l[lcnt].okey = o->okey;; |
| 210 | o->l[lcnt].lcnt = lcnt + 1; |
| 211 | RANDOM(o->l[lcnt].quantity, L_QTY_MIN, L_QTY_MAX, L_QTY_SD); |
| 212 | RANDOM(o->l[lcnt].discount, L_DCNT_MIN, L_DCNT_MAX, L_DCNT_SD); |
| 213 | RANDOM(o->l[lcnt].tax, L_TAX_MIN, L_TAX_MAX, L_TAX_SD); |
| 214 | pick_str(&l_instruct_set, L_SHIP_SD, o->l[lcnt].shipinstruct); |
| 215 | pick_str(&l_smode_set, L_SMODE_SD, o->l[lcnt].shipmode); |
| 216 | TEXT(L_CMNT_LEN, L_CMNT_SD, o->l[lcnt].comment); |
| 217 | o->l[lcnt].clen = (int)strlen(o->l[lcnt].comment); |
| 218 | if (scale >= 30000) |
| 219 | RANDOM64(o->l[lcnt].partkey, L_PKEY_MIN, L_PKEY_MAX, L_PKEY_SD); |
| 220 | else |
| 221 | RANDOM(o->l[lcnt].partkey, L_PKEY_MIN, L_PKEY_MAX, L_PKEY_SD); |
| 222 | rprice = rpb_routine(o->l[lcnt].partkey); |
| 223 | RANDOM(supp_num, 0, 3, L_SKEY_SD); |
| 224 | PART_SUPP_BRIDGE(o->l[lcnt].suppkey, o->l[lcnt].partkey, supp_num); |
| 225 | o->l[lcnt].eprice = rprice * o->l[lcnt].quantity; |
| 226 | |
| 227 | o->totalprice += |
| 228 | ((o->l[lcnt].eprice * |
| 229 | ((long) 100 - o->l[lcnt].discount)) / (long) PENNIES) * |
| 230 | ((long) 100 + o->l[lcnt].tax) |
| 231 | / (long) PENNIES; |
| 232 | |
| 233 | RANDOM(s_date, L_SDTE_MIN, L_SDTE_MAX, L_SDTE_SD); |
| 234 | s_date += tmp_date; |
| 235 | RANDOM(c_date, L_CDTE_MIN, L_CDTE_MAX, L_CDTE_SD); |
| 236 | c_date += tmp_date; |
| 237 | RANDOM(r_date, L_RDTE_MIN, L_RDTE_MAX, L_RDTE_SD); |
| 238 | r_date += s_date; |
| 239 | |
| 240 | |
| 241 | strcpy(o->l[lcnt].sdate, asc_date[s_date - STARTDATE]); |
| 242 | strcpy(o->l[lcnt].cdate, asc_date[c_date - STARTDATE]); |
| 243 | strcpy(o->l[lcnt].rdate, asc_date[r_date - STARTDATE]); |
| 244 | |
| 245 | |
| 246 | if (julian(r_date) <= CURRENTDATE) |
| 247 | { |
| 248 | pick_str(&l_rflag_set, L_RFLG_SD, tmp_str); |
| 249 | o->l[lcnt].rflag[0] = *tmp_str; |
| 250 | } |
| 251 | else |
| 252 | o->l[lcnt].rflag[0] = 'N'; |
| 253 | |
| 254 | if (julian(s_date) <= CURRENTDATE) |
| 255 | { |
| 256 | ocnt++; |
| 257 | o->l[lcnt].lstatus[0] = 'F'; |
| 258 | } |
| 259 | else |
| 260 | o->l[lcnt].lstatus[0] = 'O'; |
| 261 | } |
| 262 | |
| 263 | if (ocnt > 0) |
| 264 | o->orderstatus = 'P'; |
| 265 | if (ocnt == o->lines) |
| 266 | o->orderstatus = 'F'; |
| 267 | |
| 268 | return (0); |
| 269 | } |
| 270 | |
| 271 | long |
| 272 | mk_part(DSS_HUGE index, part_t * p) |
| 273 | { |
| 274 | DSS_HUGE temp; |
| 275 | long snum; |
| 276 | DSS_HUGE brnd; |
| 277 | static int bInit = 0; |
| 278 | static char szFormat[100]; |
| 279 | static char szBrandFormat[100]; |
| 280 | |
| 281 | if (!bInit) |
| 282 | { |
| 283 | sprintf(szFormat, P_MFG_FMT, 1, HUGE_FORMAT + 1); |
| 284 | sprintf(szBrandFormat, P_BRND_FMT, 2, HUGE_FORMAT + 1); |
| 285 | bInit = 1; |
| 286 | } |
| 287 | p->partkey = index; |
| 288 | agg_str(&colors, (long) P_NAME_SCL, (long) P_NAME_SD, p->name); |
| 289 | RANDOM(temp, P_MFG_MIN, P_MFG_MAX, P_MFG_SD); |
| 290 | sprintf(p->mfgr, szFormat, P_MFG_TAG, temp); |
| 291 | RANDOM(brnd, P_BRND_MIN, P_BRND_MAX, P_BRND_SD); |
| 292 | sprintf(p->brand, szBrandFormat, P_BRND_TAG, (temp * 10 + brnd)); |
| 293 | p->tlen = pick_str(&p_types_set, P_TYPE_SD, p->type); |
| 294 | p->tlen = (int)strlen(p_types_set.list[p->tlen].text); |
| 295 | RANDOM(p->size, P_SIZE_MIN, P_SIZE_MAX, P_SIZE_SD); |
| 296 | pick_str(&p_cntr_set, P_CNTR_SD, p->container); |
| 297 | p->retailprice = rpb_routine(index); |
| 298 | TEXT(P_CMNT_LEN, P_CMNT_SD, p->comment); |
| 299 | p->clen = (int)strlen(p->comment); |
| 300 | |
| 301 | for (snum = 0; snum < SUPP_PER_PART; snum++) |
| 302 | { |
| 303 | p->s[snum].partkey = p->partkey; |
| 304 | PART_SUPP_BRIDGE(p->s[snum].suppkey, index, snum); |
| 305 | RANDOM(p->s[snum].qty, PS_QTY_MIN, PS_QTY_MAX, PS_QTY_SD); |
| 306 | RANDOM(p->s[snum].scost, PS_SCST_MIN, PS_SCST_MAX, PS_SCST_SD); |
| 307 | TEXT(PS_CMNT_LEN, PS_CMNT_SD, p->s[snum].comment); |
| 308 | p->s[snum].clen = (int)strlen(p->s[snum].comment); |
| 309 | } |
| 310 | return (0); |
| 311 | } |
| 312 | |
| 313 | long |
| 314 | mk_supp(DSS_HUGE index, supplier_t * s) |
| 315 | { |
| 316 | DSS_HUGE i, bad_press, noise, offset, type; |
| 317 | static int bInit = 0; |
| 318 | static char szFormat[100]; |
| 319 | |
| 320 | if (!bInit) |
| 321 | { |
| 322 | sprintf(szFormat, S_NAME_FMT, 9, HUGE_FORMAT + 1); |
| 323 | bInit = 1; |
| 324 | } |
| 325 | s->suppkey = index; |
| 326 | sprintf(s->name, szFormat, S_NAME_TAG, index); |
| 327 | V_STR(S_ADDR_LEN, S_ADDR_SD, s->address); |
| 328 | s->alen = (int)strlen(s->address); |
| 329 | RANDOM(i, 0, nations.count - 1, S_NTRG_SD); |
| 330 | s->nation_code = i; |
| 331 | gen_phone(i, s->phone, S_PHNE_SD); |
| 332 | RANDOM(s->acctbal, S_ABAL_MIN, S_ABAL_MAX, S_ABAL_SD); |
| 333 | |
| 334 | TEXT(S_CMNT_LEN, S_CMNT_SD, s->comment); |
| 335 | s->clen = (int)strlen(s->comment); |
| 336 | /* |
| 337 | * these calls should really move inside the if stmt below, but this |
| 338 | * will simplify seedless parallel load |
| 339 | */ |
| 340 | RANDOM(bad_press, 1, 10000, BBB_CMNT_SD); |
| 341 | RANDOM(type, 0, 100, BBB_TYPE_SD); |
| 342 | RANDOM(noise, 0, (s->clen - BBB_CMNT_LEN), BBB_JNK_SD); |
| 343 | RANDOM(offset, 0, (s->clen - (BBB_CMNT_LEN + noise)), |
| 344 | BBB_OFFSET_SD); |
| 345 | if (bad_press <= S_CMNT_BBB) |
| 346 | { |
| 347 | type = (type < BBB_DEADBEATS) ? 0 : 1; |
| 348 | memcpy(s->comment + offset, BBB_BASE, BBB_BASE_LEN); |
| 349 | if (type == 0) |
| 350 | memcpy(s->comment + BBB_BASE_LEN + offset + noise, |
| 351 | BBB_COMPLAIN, BBB_TYPE_LEN); |
| 352 | else |
| 353 | memcpy(s->comment + BBB_BASE_LEN + offset + noise, |
| 354 | BBB_COMMEND, BBB_TYPE_LEN); |
| 355 | } |
| 356 | return (0); |
| 357 | } |
| 358 | |
| 359 | struct |
| 360 | { |
| 361 | char *mdes; |
| 362 | long days; |
| 363 | long dcnt; |
| 364 | } months[] = |
| 365 | |
| 366 | { |
| 367 | { |
| 368 | NULL, 0, 0 |
| 369 | }, |
| 370 | { |
| 371 | "JAN" , 31, 31 |
| 372 | }, |
| 373 | { |
| 374 | "FEB" , 28, 59 |
| 375 | }, |
| 376 | { |
| 377 | "MAR" , 31, 90 |
| 378 | }, |
| 379 | { |
| 380 | "APR" , 30, 120 |
| 381 | }, |
| 382 | { |
| 383 | "MAY" , 31, 151 |
| 384 | }, |
| 385 | { |
| 386 | "JUN" , 30, 181 |
| 387 | }, |
| 388 | { |
| 389 | "JUL" , 31, 212 |
| 390 | }, |
| 391 | { |
| 392 | "AUG" , 31, 243 |
| 393 | }, |
| 394 | { |
| 395 | "SEP" , 30, 273 |
| 396 | }, |
| 397 | { |
| 398 | "OCT" , 31, 304 |
| 399 | }, |
| 400 | { |
| 401 | "NOV" , 30, 334 |
| 402 | }, |
| 403 | { |
| 404 | "DEC" , 31, 365 |
| 405 | } |
| 406 | }; |
| 407 | |
| 408 | long |
| 409 | mk_time(DSS_HUGE index, dss_time_t * t) |
| 410 | { |
| 411 | long m = 0; |
| 412 | long y; |
| 413 | long d; |
| 414 | |
| 415 | t->timekey = index + JDAY_BASE; |
| 416 | y = julian(index + STARTDATE - 1) / 1000; |
| 417 | d = julian(index + STARTDATE - 1) % 1000; |
| 418 | while (d > months[m].dcnt + LEAP_ADJ(y, m)) |
| 419 | m++; |
| 420 | PR_DATE(t->alpha, y, m, |
| 421 | d - months[m - 1].dcnt - ((LEAP(y) && m > 2) ? 1 : 0)); |
| 422 | t->year = 1900 + y; |
| 423 | t->month = m + 12 * y + JMNTH_BASE; |
| 424 | t->week = (d + T_START_DAY - 1) / 7 + 1; |
| 425 | t->day = d - months[m - 1].dcnt - LEAP_ADJ(y, m - 1); |
| 426 | |
| 427 | return (0); |
| 428 | } |
| 429 | |
| 430 | int |
| 431 | mk_nation(DSS_HUGE index, code_t * c) |
| 432 | { |
| 433 | c->code = index - 1; |
| 434 | c->text = nations.list[index - 1].text; |
| 435 | c->join = nations.list[index - 1].weight; |
| 436 | TEXT(N_CMNT_LEN, N_CMNT_SD, c->comment); |
| 437 | c->clen = (int)strlen(c->comment); |
| 438 | return (0); |
| 439 | } |
| 440 | |
| 441 | int |
| 442 | mk_region(DSS_HUGE index, code_t * c) |
| 443 | { |
| 444 | |
| 445 | c->code = index - 1; |
| 446 | c->text = regions.list[index - 1].text; |
| 447 | c->join = 0; /* for completeness */ |
| 448 | TEXT(R_CMNT_LEN, R_CMNT_SD, c->comment); |
| 449 | c->clen = (int)strlen(c->comment); |
| 450 | return (0); |
| 451 | } |
| 452 | |