1: # include <symbol.h> 2: # include <ingres.h> 3: # include <tree.h> 4: # include <aux.h> 5: # include <sccs.h> 6: 7: SCCSID(@(#)pr_tree.c 8.2 1/15/85) 8: 9: /* 10: ** PR_TREE.C -- Query tree printing routines 11: ** 12: ** Trace Flags: 13: ** 52 14: */ 15: 16: 17: 18: 19: char *pr_trim(); 20: char *resultres(); 21: 22: struct tab 23: { 24: char t_opcode; 25: char *t_string; 26: }; 27: 28: 29: struct tab Uop_tab[] = 30: { 31: opPLUS, "+ ", 32: opMINUS, "- ", 33: opNOT, "not[ERROR]", 34: opATAN, "atan", 35: opCOS, "cos", 36: opGAMMA, "gamma", 37: opLOG, "log", 38: opASCII, "ascii", 39: opSIN, "sin", 40: opSQRT, "sqrt", 41: opABS, "abs", 42: opEXP, "exp", 43: opINT1, "int1", 44: opINT2, "int2", 45: opINT4, "int4", 46: opFLOAT4, "float4", 47: opFLOAT8, "float8", 48: }; 49: struct tab Bop_tab[] = 50: { 51: opADD, "+", 52: opSUB, "-", 53: opMUL, "*", 54: opDIV, "/", 55: opPOW, "**", 56: opEQ, "=", 57: opNE, "!=", 58: opLT, "<", 59: opLE, "<=", 60: opGT, ">", 61: opGE, ">=", 62: opMOD, "%", 63: }; 64: 65: struct tab Cop_tab[] = 66: { 67: opDBA, "dba", 68: opUSERCODE, "usercode", 69: opDATE, "date", 70: opTIME, "time", 71: }; 72: 73: struct tab Aop_tab[] = 74: { 75: opCOUNT, "count", 76: opCOUNTU, "countu", 77: opSUM, "sum", 78: opSUMU, "sumu", 79: opAVG, "avg", 80: opAVGU, "avgu", 81: opMIN, "min", 82: opMAX, "max", 83: opANY, "any", 84: }; 85: 86: 87: DESC Attdes; 88: int Tl_elm; 89: int Dom_num; 90: char *Resrel; 91: /* 92: ** PR_TREE 93: ** 94: ** tree: tl_clause ROOT tl_clause 95: ** 96: ** prints out a tree assuming a mdVIEW-like mode 97: ** 98: */ 99: 100: pr_tree(root) 101: QTREE *root; 102: { 103: 104: # ifdef xZTR1 105: if (tTf(52, -1)) 106: printf("pr_tree: root %u Resultvar %d Resrel %s\n", 107: root, Qt.qt_resvar, Resrel); 108: # endif 109: 110: printf("%s ", pr_trim(resultres(), MAXNAME)); 111: 112: pr_dom_init(); 113: Tl_elm = 0; 114: 115: /* print target list */ 116: printf("(\n"); 117: pr_tl_clause(root->left, TRUE); 118: putchar(')'); 119: 120: /* print qualification */ 121: if (root->right->sym.type != QLEND) 122: { 123: printf("\nwhere "); 124: pr_qual(root->right); 125: } 126: putchar('\n'); 127: } 128: /* 129: ** PR_TL_CLAUSE 130: ** 131: ** tl_clause: TREE 132: ** | tl_clause RESDOM expr 133: ** 134: ** target_flag = "in a target list (as opposed to in a by list)" 135: */ 136: 137: pr_tl_clause(t_l, target_flag) 138: QTREE *t_l; 139: register bool target_flag; 140: { 141: 142: # ifdef xZTR1 143: if (tTf(52, 1)) 144: printf("tl_clause target %d Tl_elm %d\n", target_flag, Tl_elm); 145: # endif 146: 147: if (t_l->sym.type != TREE) 148: { 149: pr_tl_clause(t_l->left, target_flag); 150: if (Tl_elm) 151: { 152: printf(", "); 153: if (target_flag) 154: putchar('\n'); 155: } 156: /* print out info on result variable */ 157: pr_resdom(t_l, target_flag); 158: pr_expr(t_l->right); 159: Tl_elm++; 160: } 161: } 162: /* 163: ** PR_RESDOM 164: ** 165: ** print out info on a result attribute. 166: ** this will be done only if the RESDOM node 167: ** is inside a target_list and if the Qt.qt_resvar >= 0. 168: ** Qt.qt_resvar == -1 inside a target list indicates that this is 169: ** a retrieve to terminal. 170: */ 171: 172: pr_resdom(resdom, target_flag) 173: QTREE *resdom; 174: int target_flag; 175: { 176: 177: # ifdef xZTR1 178: if (tTf(52, 2)) 179: printf("pr_resdom: target_flag %d\n", target_flag); 180: # endif 181: 182: if (target_flag) 183: { 184: printf("\t"); 185: pr_attname(resultres(), resdom->sym.value.sym_resdom.resno); 186: printf(" = "); 187: } 188: } 189: /* 190: ** PR_ATTNAME 191: ** 192: ** give a relation name, and the attribute number of that 193: ** relation, looks in the attribute relation for the name of the 194: ** attribute. 195: */ 196: 197: pr_attname(rel, attno) 198: char *rel; 199: int attno; 200: { 201: TID tid; 202: struct attribute key, tuple; 203: short attnum; 204: register i; 205: 206: # ifdef xZTR1 207: if (tTf(52, 3)) 208: printf("pr_attname: rel %s attno %d\n", 209: rel, attno); 210: # endif 211: 212: if (attno == 0) 213: { 214: printf("tid"); 215: return; 216: } 217: opencatalog("attribute", OR_READ); 218: clearkeys(&Attdes); 219: attnum = (short) attno; 220: setkey(&Attdes, &key, rel, ATTRELID); 221: setkey(&Attdes, &key, &attnum, ATTID); 222: i = getequal(&Attdes, &key, &tuple, &tid); 223: if (i) 224: syserr("pr_attname: bad getequal %d rel %s attno %d", 225: i, rel, attno); 226: printf("%s", pr_trim(tuple.attname, MAXNAME)); 227: } 228: /* 229: ** PR_EXPR 230: ** 231: ** expr: VAR 232: ** | expr BOP expr 233: ** | expr UOP 234: ** | AOP AGHEAD qual 235: ** \ 236: ** expr 237: ** | BYHEAD AGHEAD qual 238: ** / \ 239: ** tl_clause AOP 240: ** \ 241: ** expr 242: ** | INT 243: ** | FLOAT 244: ** | CHAR 245: */ 246: 247: pr_expr(e) 248: register QTREE *e; 249: { 250: register int op; 251: register int tl_elm; 252: 253: switch (e->sym.type) 254: { 255: case VAR: 256: pr_var(e); 257: break; 258: 259: case BOP: 260: if (e->sym.value.sym_op.opno == opCONCAT) 261: { 262: printf("concat("); 263: pr_expr(e->left); 264: printf(", "); 265: pr_expr(e->right); 266: putchar(')'); 267: } 268: else 269: { 270: putchar('('); 271: pr_expr(e->left); 272: pr_op(BOP, e->sym.value.sym_op.opno); 273: pr_expr(e->right); 274: putchar(')'); 275: } 276: break; 277: 278: case UOP: 279: if ((op = e->sym.value.sym_op.opno) == opMINUS || op == opPLUS || op == opNOT) 280: { 281: pr_op(UOP, e->sym.value.sym_op.opno); 282: pr_expr(e->left); 283: putchar(')'); 284: } 285: else 286: { 287: /* functional operators */ 288: pr_op(UOP, e->sym.value.sym_op.opno); 289: pr_expr(e->left); 290: putchar(')'); 291: } 292: break; 293: 294: case AGHEAD: 295: if (e->left->sym.type == AOP) 296: { 297: /* simple aggregate */ 298: pr_op(AOP, e->left->sym.value.sym_op.opno); 299: pr_expr(e->left->right); 300: if (e->right->sym.type != QLEND) 301: { 302: printf("\where "); 303: pr_qual(e->right); 304: } 305: putchar(')'); 306: } 307: else 308: { 309: /* aggregate function */ 310: pr_op(AOP, e->left->right->sym.value.sym_op.opno); 311: pr_expr(e->left->right->right); 312: printf(" by "); 313: /* avoid counting target list elements 314: * in determining wether to put out 315: * commas after list's elements 316: */ 317: tl_elm = Tl_elm; 318: Tl_elm = 0; 319: pr_tl_clause(e->left->left, FALSE); 320: Tl_elm = tl_elm; 321: if (e->right->sym.type != QLEND) 322: { 323: printf("\n\t\twhere "); 324: pr_qual(e->right); 325: } 326: putchar(')'); 327: } 328: break; 329: 330: case INT: 331: case FLOAT: 332: case CHAR: 333: pr_const(e); 334: break; 335: 336: default: 337: syserr("expr %d", e->sym.type); 338: } 339: } 340: /* 341: ** PR_CONST -- print constant 342: */ 343: 344: pr_const(c) 345: register QTREE *c; 346: { 347: register char *cp; 348: register int i; 349: char ch; 350: double d; 351: 352: switch (c->sym.type) 353: { 354: case INT: 355: if (c->sym.len == 1) 356: printf("%d", c->sym.value.sym_data.i1type); 357: else if (c->sym.len == 2) 358: printf("%d", c->sym.value.sym_data.i2type); 359: else /* i4 */ 360: printf("%D", c->sym.value.sym_data.i4type); 361: break; 362: 363: case FLOAT: 364: if (c->sym.len == 4) 365: d = c->sym.value.sym_data.f4type; 366: else 367: d = c->sym.value.sym_data.f8type; 368: printf("%-10.3f", c->sym.value.sym_data.f8type); 369: break; 370: 371: case CHAR: 372: printf("\""); 373: cp = c->sym.value.sym_data.c0type; 374: for (i = c->sym.len; i--; cp++) 375: { 376: if (any(*cp, "\"\\[]*?") == TRUE) 377: putchar('\\'); 378: 379: if (*cp >= ' ') 380: { 381: putchar(*cp); 382: continue; 383: } 384: /* perform pattern matching character replacement */ 385: switch (*cp) 386: { 387: case PAT_ANY: 388: ch = '*'; 389: break; 390: 391: case PAT_ONE: 392: ch = '?'; 393: break; 394: 395: case PAT_LBRAC: 396: ch = '['; 397: break; 398: 399: case PAT_RBRAC: 400: ch = ']'; 401: break; 402: 403: default: 404: ch = *cp; 405: } 406: putchar(ch); 407: } 408: putchar('"'); 409: break; 410: 411: default: 412: syserr("bad constant %d", c->sym.type); 413: } 414: } 415: /* 416: ** PR_OP -- print out operator of a certain type 417: */ 418: 419: pr_op(op_type, op_code) 420: int op_type; 421: register int op_code; 422: { 423: register struct tab *s; 424: 425: switch (op_type) 426: { 427: case UOP: 428: s = &Uop_tab[op_code]; 429: printf("%s(", s->t_string); 430: break; 431: 432: case BOP: 433: s = &Bop_tab[op_code]; 434: printf(" %s ", s->t_string); 435: break; 436: 437: case AOP: 438: s = &Aop_tab[op_code]; 439: printf("%s(", s->t_string); 440: break; 441: 442: case COP: 443: s = &Cop_tab[op_code]; 444: printf("%s", s->t_string); 445: break; 446: } 447: if (op_code != s->t_opcode) 448: syserr("pr_op: op in wrong place type %d, code %d", op_type, 449: s->t_opcode); 450: } 451: /* 452: ** PR_VAR 453: ** 454: ** print a VAR node: that is, a var.attno pair 455: ** at present the var part is the relation name over which var 456: ** ranges. 457: */ 458: 459: pr_var(var) 460: QTREE *var; 461: { 462: 463: # ifdef xZTR1 464: if (tTf(52, 4)) 465: printf("pr_var(var=%d)\n", var); 466: # endif 467: pr_rv(var->sym.value.sym_var.varno); 468: putchar('.'); 469: pr_attname(Qt.qt_rangev[var->sym.value.sym_var.varno].rngvdesc->reldum.relid, var->sym.value.sym_var.attno); 470: } 471: /* 472: ** PR_QUAL 473: ** 474: ** qual: QLEND 475: ** | q_clause AND qual 476: ** 477: */ 478: 479: pr_qual(q) 480: register QTREE *q; 481: { 482: 483: pr_q_clause(q->left); 484: if (q->right->sym.type != QLEND) 485: { 486: printf(" and "); 487: pr_qual(q->right); 488: } 489: } 490: /* 491: ** PR_Q_CLAUSE 492: ** 493: ** q_clause: q_clause OR q_clause 494: ** | expr 495: */ 496: 497: pr_q_clause(q) 498: QTREE *q; 499: { 500: 501: if (q->sym.type == OR) 502: { 503: pr_q_clause(q->left); 504: printf(" or "); 505: pr_q_clause(q->right); 506: } 507: else 508: pr_expr(q); 509: } 510: /* 511: ** PR_TRIM 512: */ 513: 514: char * 515: pr_trim(s, l) 516: register char *s; 517: register int l; 518: { 519: static char buf[30]; 520: 521: bmove(s, buf, l); 522: for (s = buf; l && *s != ' ' && *s; --l) 523: s++; 524: *s = '\0'; 525: return (buf); 526: } 527: /* 528: ** PR_DOM_INIT 529: */ 530: 531: pr_dom_init() 532: { 533: Dom_num = 0; 534: } 535: 536: pr_ddom() 537: { 538: printf("d%d = ", Dom_num++); 539: } 540: /* 541: ** PR_RANGE -- print the range table 542: */ 543: 544: pr_range() 545: { 546: register int i; 547: 548: for (i = 0; i <= MAXVAR; i++) 549: { 550: if (Qt.qt_rangev[i].rngvdesc != NULL) 551: { 552: printf("range of "); 553: pr_rv(i); 554: printf(" is %s\n", 555: pr_trim(Qt.qt_rangev[i].rngvdesc->reldum.relid, MAXNAME)); 556: } 557: } 558: } 559: /* 560: ** PR_RV -- print range variable 561: */ 562: 563: pr_rv(re) 564: register int re; 565: { 566: register int j; 567: register char ch; 568: 569: ch = Qt.qt_rangev[re].rngvdesc->reldum.relid[0]; 570: 571: # ifdef xZTR1 572: if (tTf(52, 6)) 573: printf("pr_rv(%d) ch '%c'\n", re, ch); 574: # endif 575: 576: for (j = 0; j <= MAXVAR; j++) 577: { 578: if (Qt.qt_rangev[j].rngvdesc == NULL) 579: continue; 580: if (ch == Qt.qt_rangev[j].rngvdesc->reldum.relid[0]) 581: break; 582: } 583: if (j < re) 584: printf("rv%d", re); 585: else 586: printf("%c", ch); 587: } 588: /* 589: ** RESULTRES 590: */ 591: 592: char * 593: resultres() 594: { 595: extern char *Resrel; 596: 597: # ifdef xZTR1 598: if (tTf(52, 5)) 599: printf("resultres: Resultvar %d, Resrel %s\n", Qt.qt_resvar, Resrel); 600: # endif 601: if (Qt.qt_resvar > 0) 602: return (Qt.qt_rangev[Qt.qt_resvar].rngvdesc->reldum.relid); 603: if (Resrel == 0) 604: syserr("resultres: Resrel == 0"); 605: 606: return (Resrel); 607: } 608: 609: any(c, s) 610: register char c; 611: register char *s; 612: { 613: 614: while (*s != '\0') 615: if (*s++ == c) 616: return (TRUE); 617: return (FALSE); 618: }