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 */
53FILE *print_prep PROTO((int table, int update));
54int pr_drange PROTO((int tbl, DSS_HUGE min, DSS_HUGE cnt, long num));
55
56FILE *
57print_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
102int
103dbg_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
153int
154pr_cust(customer_t *c, int mode)
155{
156static 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 */
181int
182pr_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 */
212int
213pr_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 */
255int
256pr_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 */
268int
269pr_part(part_t *part, int mode)
270{
271static 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 */
294int
295pr_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 */
320int
321pr_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
330int
331pr_supp(supplier_t *supp, int mode)
332{
333static 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
351int
352pr_nation(code_t *c, int mode)
353{
354static 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
369int
370pr_region(code_t *c, int mode)
371{
372static 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 */
392int
393pr_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