| 1 | /* |
| 2 | * $Id: print.c,v 1.3 2005/10/28 02:56:22 jms Exp $ |
| 3 | * |
| 4 | * Revision History |
| 5 | * =================== |
| 6 | * $Log: print.c,v $ |
| 7 | * Revision 1.3 2005/10/28 02:56:22 jms |
| 8 | * add platform-specific printf formats to allow for DSS_HUGE data type |
| 9 | * |
| 10 | * Revision 1.2 2005/01/03 20:08:59 jms |
| 11 | * change line terminations |
| 12 | * |
| 13 | * Revision 1.1.1.1 2004/11/24 23:31:47 jms |
| 14 | * re-establish external server |
| 15 | * |
| 16 | * Revision 1.4 2004/02/18 16:26:49 jms |
| 17 | * 32/64 bit changes for overflow handling needed additional changes when ported back to windows |
| 18 | * |
| 19 | * Revision 1.3 2004/02/18 14:05:53 jms |
| 20 | * porting changes for LINUX and 64 bit RNG |
| 21 | * |
| 22 | * Revision 1.2 2004/01/22 05:49:29 jms |
| 23 | * AIX porting (AIX 5.1) |
| 24 | * |
| 25 | * Revision 1.1.1.1 2003/08/07 17:58:34 jms |
| 26 | * recreation after CVS crash |
| 27 | * |
| 28 | * Revision 1.2 2003/08/07 17:58:34 jms |
| 29 | * Convery RNG to 64bit space as preparation for new large scale RNG |
| 30 | * |
| 31 | * Revision 1.1.1.1 2003/04/03 18:54:21 jms |
| 32 | * initial checkin |
| 33 | * |
| 34 | * |
| 35 | */ |
| 36 | /* generate flat files for data load */ |
| 37 | #include <stdio.h> |
| 38 | #ifndef VMS |
| 39 | #include <sys/types.h> |
| 40 | #endif |
| 41 | #if defined(SUN) |
| 42 | #include <unistd.h> |
| 43 | #endif |
| 44 | #include <math.h> |
| 45 | |
| 46 | #include "dss.h" |
| 47 | #include "dsstypes.h" |
| 48 | #include <string.h> |
| 49 | |
| 50 | /* |
| 51 | * Function Prototypes |
| 52 | */ |
| 53 | FILE *print_prep PROTO((int table, int update)); |
| 54 | int pr_drange PROTO((int tbl, DSS_HUGE min, DSS_HUGE cnt, long num)); |
| 55 | |
| 56 | FILE * |
| 57 | print_prep(int table, int update) |
| 58 | { |
| 59 | char upath[128]; |
| 60 | FILE *res; |
| 61 | |
| 62 | if (updates) |
| 63 | { |
| 64 | if (update > 0) /* updates */ |
| 65 | if ( insert_segments ) |
| 66 | { |
| 67 | int this_segment; |
| 68 | if(strcmp(tdefs[table].name,"orders.tbl" )) |
| 69 | this_segment=++insert_orders_segment; |
| 70 | else |
| 71 | this_segment=++insert_lineitem_segment; |
| 72 | sprintf(upath, "%s%c%s.u%d.%d" , |
| 73 | env_config(PATH_TAG, PATH_DFLT), |
| 74 | PATH_SEP, tdefs[table].name, update%10000,this_segment); |
| 75 | } |
| 76 | else |
| 77 | { |
| 78 | sprintf(upath, "%s%c%s.u%d" , |
| 79 | env_config(PATH_TAG, PATH_DFLT), |
| 80 | PATH_SEP, tdefs[table].name, update); |
| 81 | } |
| 82 | else /* deletes */ |
| 83 | if ( delete_segments ) |
| 84 | { |
| 85 | ++delete_segment; |
| 86 | sprintf(upath, "%s%cdelete.u%d.%d" , |
| 87 | env_config(PATH_TAG, PATH_DFLT), PATH_SEP, -update%10000, |
| 88 | delete_segment); |
| 89 | } |
| 90 | else |
| 91 | { |
| 92 | sprintf(upath, "%s%cdelete.%d" , |
| 93 | env_config(PATH_TAG, PATH_DFLT), PATH_SEP, -update); |
| 94 | } |
| 95 | return(fopen(upath, "w" )); |
| 96 | } |
| 97 | res = tbl_open(table, "w" ); |
| 98 | OPEN_CHECK(res, tdefs[table].name); |
| 99 | return(res); |
| 100 | } |
| 101 | |
| 102 | int |
| 103 | dbg_print(int format, FILE *target, void *data, int len, int sep) |
| 104 | { |
| 105 | int dollars, |
| 106 | cents; |
| 107 | |
| 108 | switch(format) |
| 109 | { |
| 110 | case DT_STR: |
| 111 | fprintf(target, "%s" , (char *)data); |
| 112 | break; |
| 113 | #ifdef MVS |
| 114 | case DT_VSTR: |
| 115 | /* note: only used in MVS, assumes columnar output */ |
| 116 | fprintf(target, "%c%c%-*s" , |
| 117 | (len >> 8) & 0xFF, len & 0xFF, len, (char *)data); |
| 118 | break; |
| 119 | #endif /* MVS */ |
| 120 | case DT_INT: |
| 121 | fprintf(target, "%ld" , (long)data); |
| 122 | break; |
| 123 | case DT_HUGE: |
| 124 | fprintf(target, HUGE_FORMAT, *(DSS_HUGE *)data); |
| 125 | break; |
| 126 | case DT_KEY: |
| 127 | fprintf(target, "%ld" , (long)data); |
| 128 | break; |
| 129 | case DT_MONEY: |
| 130 | cents = (int)*(DSS_HUGE *)data; |
| 131 | if (cents < 0) |
| 132 | { |
| 133 | fprintf(target, "-" ); |
| 134 | cents = -cents; |
| 135 | } |
| 136 | dollars = cents / 100; |
| 137 | cents %= 100; |
| 138 | fprintf(target, "%d.%02d" , dollars, cents); |
| 139 | break; |
| 140 | case DT_CHR: |
| 141 | fprintf(target, "%c" , *(char *)data); |
| 142 | break; |
| 143 | } |
| 144 | |
| 145 | #ifdef EOL_HANDLING |
| 146 | if (sep) |
| 147 | #endif /* EOL_HANDLING */ |
| 148 | fprintf(target, "%c" , SEPARATOR); |
| 149 | |
| 150 | return(0); |
| 151 | } |
| 152 | |
| 153 | int |
| 154 | pr_cust(customer_t *c, int mode) |
| 155 | { |
| 156 | static FILE *fp = NULL; |
| 157 | |
| 158 | if (fp == NULL) |
| 159 | fp = print_prep(CUST, 0); |
| 160 | |
| 161 | PR_STRT(fp); |
| 162 | PR_HUGE(fp, &c->custkey); |
| 163 | if (scale <= 3000) |
| 164 | PR_VSTR(fp, c->name, C_NAME_LEN); |
| 165 | else |
| 166 | PR_VSTR(fp, c->name, C_NAME_LEN + 3); |
| 167 | PR_VSTR(fp, c->address, c->alen); |
| 168 | PR_HUGE(fp, &c->nation_code); |
| 169 | PR_STR(fp, c->phone, PHONE_LEN); |
| 170 | PR_MONEY(fp, &c->acctbal); |
| 171 | PR_STR(fp, c->mktsegment, C_MSEG_LEN); |
| 172 | PR_VSTR_LAST(fp, c->comment, c->clen); |
| 173 | PR_END(fp); |
| 174 | |
| 175 | return(0); |
| 176 | } |
| 177 | |
| 178 | /* |
| 179 | * print the numbered order |
| 180 | */ |
| 181 | int |
| 182 | pr_order(order_t *o, int mode) |
| 183 | { |
| 184 | static FILE *fp_o = NULL; |
| 185 | static int last_mode = 0; |
| 186 | |
| 187 | if (fp_o == NULL || mode != last_mode) |
| 188 | { |
| 189 | if (fp_o) |
| 190 | fclose(fp_o); |
| 191 | fp_o = print_prep(ORDER, mode); |
| 192 | last_mode = mode; |
| 193 | } |
| 194 | PR_STRT(fp_o); |
| 195 | PR_HUGE(fp_o, &o->okey); |
| 196 | PR_HUGE(fp_o, &o->custkey); |
| 197 | PR_CHR(fp_o, &o->orderstatus); |
| 198 | PR_MONEY(fp_o, &o->totalprice); |
| 199 | PR_STR(fp_o, o->odate, DATE_LEN); |
| 200 | PR_STR(fp_o, o->opriority, O_OPRIO_LEN); |
| 201 | PR_STR(fp_o, o->clerk, O_CLRK_LEN); |
| 202 | PR_INT(fp_o, o->spriority); |
| 203 | PR_VSTR_LAST(fp_o, o->comment, o->clen); |
| 204 | PR_END(fp_o); |
| 205 | |
| 206 | return(0); |
| 207 | } |
| 208 | |
| 209 | /* |
| 210 | * print an order's lineitems |
| 211 | */ |
| 212 | int |
| 213 | pr_line(order_t *o, int mode) |
| 214 | { |
| 215 | static FILE *fp_l = NULL; |
| 216 | static int last_mode = 0; |
| 217 | long i; |
| 218 | |
| 219 | if (fp_l == NULL || mode != last_mode) |
| 220 | { |
| 221 | if (fp_l) |
| 222 | fclose(fp_l); |
| 223 | fp_l = print_prep(LINE, mode); |
| 224 | last_mode = mode; |
| 225 | } |
| 226 | |
| 227 | for (i = 0; i < o->lines; i++) |
| 228 | { |
| 229 | PR_STRT(fp_l); |
| 230 | PR_HUGE(fp_l, &o->l[i].okey); |
| 231 | PR_HUGE(fp_l, &o->l[i].partkey); |
| 232 | PR_HUGE(fp_l, &o->l[i].suppkey); |
| 233 | PR_HUGE(fp_l, &o->l[i].lcnt); |
| 234 | PR_HUGE(fp_l, &o->l[i].quantity); |
| 235 | PR_MONEY(fp_l, &o->l[i].eprice); |
| 236 | PR_MONEY(fp_l, &o->l[i].discount); |
| 237 | PR_MONEY(fp_l, &o->l[i].tax); |
| 238 | PR_CHR(fp_l, &o->l[i].rflag[0]); |
| 239 | PR_CHR(fp_l, &o->l[i].lstatus[0]); |
| 240 | PR_STR(fp_l, o->l[i].sdate, DATE_LEN); |
| 241 | PR_STR(fp_l, o->l[i].cdate, DATE_LEN); |
| 242 | PR_STR(fp_l, o->l[i].rdate, DATE_LEN); |
| 243 | PR_STR(fp_l, o->l[i].shipinstruct, L_INST_LEN); |
| 244 | PR_STR(fp_l, o->l[i].shipmode, L_SMODE_LEN); |
| 245 | PR_VSTR_LAST(fp_l, o->l[i].comment,o->l[i].clen); |
| 246 | PR_END(fp_l); |
| 247 | } |
| 248 | |
| 249 | return(0); |
| 250 | } |
| 251 | |
| 252 | /* |
| 253 | * print the numbered order *and* its associated lineitems |
| 254 | */ |
| 255 | int |
| 256 | pr_order_line(order_t *o, int mode) |
| 257 | { |
| 258 | tdefs[ORDER].name = tdefs[ORDER_LINE].name; |
| 259 | pr_order(o, mode); |
| 260 | pr_line(o, mode); |
| 261 | |
| 262 | return(0); |
| 263 | } |
| 264 | |
| 265 | /* |
| 266 | * print the given part |
| 267 | */ |
| 268 | int |
| 269 | pr_part(part_t *part, int mode) |
| 270 | { |
| 271 | static FILE *p_fp = NULL; |
| 272 | |
| 273 | if (p_fp == NULL) |
| 274 | p_fp = print_prep(PART, 0); |
| 275 | |
| 276 | PR_STRT(p_fp); |
| 277 | PR_HUGE(p_fp, &part->partkey); |
| 278 | PR_VSTR(p_fp, part->name,part->nlen); |
| 279 | PR_STR(p_fp, part->mfgr, P_MFG_LEN); |
| 280 | PR_STR(p_fp, part->brand, P_BRND_LEN); |
| 281 | PR_VSTR(p_fp, part->type,part->tlen); |
| 282 | PR_HUGE(p_fp, &part->size); |
| 283 | PR_STR(p_fp, part->container, P_CNTR_LEN); |
| 284 | PR_MONEY(p_fp, &part->retailprice); |
| 285 | PR_VSTR_LAST(p_fp, part->comment,part->clen); |
| 286 | PR_END(p_fp); |
| 287 | |
| 288 | return(0); |
| 289 | } |
| 290 | |
| 291 | /* |
| 292 | * print the given part's suppliers |
| 293 | */ |
| 294 | int |
| 295 | pr_psupp(part_t *part, int mode) |
| 296 | { |
| 297 | static FILE *ps_fp = NULL; |
| 298 | long i; |
| 299 | |
| 300 | if (ps_fp == NULL) |
| 301 | ps_fp = print_prep(PSUPP, mode); |
| 302 | |
| 303 | for (i = 0; i < SUPP_PER_PART; i++) |
| 304 | { |
| 305 | PR_STRT(ps_fp); |
| 306 | PR_HUGE(ps_fp, &part->s[i].partkey); |
| 307 | PR_HUGE(ps_fp, &part->s[i].suppkey); |
| 308 | PR_HUGE(ps_fp, &part->s[i].qty); |
| 309 | PR_MONEY(ps_fp, &part->s[i].scost); |
| 310 | PR_VSTR_LAST(ps_fp, part->s[i].comment,part->s[i].clen); |
| 311 | PR_END(ps_fp); |
| 312 | } |
| 313 | |
| 314 | return(0); |
| 315 | } |
| 316 | |
| 317 | /* |
| 318 | * print the given part *and* its suppliers |
| 319 | */ |
| 320 | int |
| 321 | pr_part_psupp(part_t *part, int mode) |
| 322 | { |
| 323 | tdefs[PART].name = tdefs[PART_PSUPP].name; |
| 324 | pr_part(part, mode); |
| 325 | pr_psupp(part, mode); |
| 326 | |
| 327 | return(0); |
| 328 | } |
| 329 | |
| 330 | int |
| 331 | pr_supp(supplier_t *supp, int mode) |
| 332 | { |
| 333 | static FILE *fp = NULL; |
| 334 | |
| 335 | if (fp == NULL) |
| 336 | fp = print_prep(SUPP, mode); |
| 337 | |
| 338 | PR_STRT(fp); |
| 339 | PR_HUGE(fp, &supp->suppkey); |
| 340 | PR_STR(fp, supp->name, S_NAME_LEN); |
| 341 | PR_VSTR(fp, supp->address, supp->alen); |
| 342 | PR_HUGE(fp, &supp->nation_code); |
| 343 | PR_STR(fp, supp->phone, PHONE_LEN); |
| 344 | PR_MONEY(fp, &supp->acctbal); |
| 345 | PR_VSTR_LAST(fp, supp->comment, supp->clen); |
| 346 | PR_END(fp); |
| 347 | |
| 348 | return(0); |
| 349 | } |
| 350 | |
| 351 | int |
| 352 | pr_nation(code_t *c, int mode) |
| 353 | { |
| 354 | static FILE *fp = NULL; |
| 355 | |
| 356 | if (fp == NULL) |
| 357 | fp = print_prep(NATION, mode); |
| 358 | |
| 359 | PR_STRT(fp); |
| 360 | PR_HUGE(fp, &c->code); |
| 361 | PR_STR(fp, c->text, NATION_LEN); |
| 362 | PR_INT(fp, c->join); |
| 363 | PR_VSTR_LAST(fp, c->comment, c->clen); |
| 364 | PR_END(fp); |
| 365 | |
| 366 | return(0); |
| 367 | } |
| 368 | |
| 369 | int |
| 370 | pr_region(code_t *c, int mode) |
| 371 | { |
| 372 | static FILE *fp = NULL; |
| 373 | |
| 374 | if (fp == NULL) |
| 375 | fp = print_prep(REGION, mode); |
| 376 | |
| 377 | PR_STRT(fp); |
| 378 | PR_HUGE(fp, &c->code); |
| 379 | PR_STR(fp, c->text, REGION_LEN); |
| 380 | PR_VSTR_LAST(fp, c->comment, c->clen); |
| 381 | PR_END(fp); |
| 382 | |
| 383 | return(0); |
| 384 | } |
| 385 | |
| 386 | /* |
| 387 | * NOTE: this routine does NOT use the BCD2_* routines. As a result, |
| 388 | * it WILL fail if the keys being deleted exceed 32 bits. Since this |
| 389 | * would require ~660 update iterations, this seems an acceptable |
| 390 | * oversight |
| 391 | */ |
| 392 | int |
| 393 | pr_drange(int tbl, DSS_HUGE min, DSS_HUGE cnt, long num) |
| 394 | { |
| 395 | static int last_num = 0; |
| 396 | static FILE *dfp = NULL; |
| 397 | DSS_HUGE child = -1; |
| 398 | DSS_HUGE start, last, new; |
| 399 | |
| 400 | static DSS_HUGE rows_per_segment=0; |
| 401 | static DSS_HUGE rows_this_segment=0; |
| 402 | |
| 403 | if (last_num != num) |
| 404 | { |
| 405 | if (dfp) |
| 406 | fclose(dfp); |
| 407 | dfp = print_prep(tbl, -num); |
| 408 | if (dfp == NULL) |
| 409 | return(-1); |
| 410 | last_num = num; |
| 411 | rows_this_segment=0; |
| 412 | } |
| 413 | |
| 414 | start = MK_SPARSE(min, num/ (10000 / UPD_PCT)); |
| 415 | last = start - 1; |
| 416 | for (child=min; cnt > 0; child++, cnt--) |
| 417 | { |
| 418 | new = MK_SPARSE(child, num/ (10000 / UPD_PCT)); |
| 419 | if (delete_segments) |
| 420 | { |
| 421 | |
| 422 | if(rows_per_segment==0) |
| 423 | rows_per_segment = (cnt / delete_segments) + 1; |
| 424 | if((++rows_this_segment) > rows_per_segment) |
| 425 | { |
| 426 | fclose(dfp); |
| 427 | dfp = print_prep(tbl, -num); |
| 428 | if (dfp == NULL) return(-1); |
| 429 | last_num = num; |
| 430 | rows_this_segment=1; |
| 431 | } |
| 432 | } |
| 433 | PR_STRT(dfp); |
| 434 | PR_HUGE(dfp, &new); |
| 435 | PR_END(dfp); |
| 436 | start = new; |
| 437 | last = new; |
| 438 | } |
| 439 | |
| 440 | return(0); |
| 441 | } |
| 442 | |
| 443 | |
| 444 | |
| 445 | |