1: # include "../ingres.h" 2: # include "../aux.h" 3: # include "../symbol.h" 4: # include "../tree.h" 5: # include "../access.h" 6: # include "../pipes.h" 7: # include "ovqp.h" 8: 9: 10: 11: /* 12: ** 13: ** INTERPRET 14: ** 15: ** Processes the retrieved tuple from the Source relation 16: ** according to the symbols in the list. Recognition 17: ** of characteristic delimiters and separators initiates 18: ** action appropriate to a target list or qualification list 19: ** as the case may be. 20: ** 21: ** Between delimiters, the symbol list is expected to be in 22: ** Polish postfix form. A qualification list is further 23: ** expected to be in conjunctive normal form, with Boolean 24: ** operators infixed. 25: ** 26: */ 27: 28: 29: double pow(); 30: double sqrt(); 31: double log(); 32: double exp(); 33: double sin(); 34: double cos(); 35: double atan(); 36: double gamma(); 37: 38: struct symbol *interpret(list) 39: 40: struct symbol **list; /* ptr to list of sym pointers */ 41: 42: { 43: register struct stacksym *tos; 44: struct symbol *op1,*op2; /*operands popped off stack*/ 45: register int *val1,*val2; /*ptrs to values of operands*/ 46: int opval, optype, l1; 47: char *s1; 48: int byflag; 49: long hitid; 50: extern char *Usercode; 51: extern ov_err(); 52: int cb_mark; 53: extern char *Ovqpbuf; 54: 55: 56: # ifdef xOTR1 57: if (tTf(23, 0)) 58: printf("INTERP: list=%l\n",list); 59: # endif 60: 61: # ifdef xOTM 62: if (tTf(76, 2)) 63: timtrace(11, 0); 64: # endif 65: 66: byflag = (list == Bylist); /* set byflag if aggregate function */ 67: tos = Stack-1; 68: /* reset the concat and ascii operator buffer */ 69: seterr(Ovqpbuf, CBUFULL, ov_err); 70: cb_mark = markbuf(Ovqpbuf); 71: 72: loop: 73: # ifdef xOTR1 74: if (tTf(23, 1) && tos >= Stack) 75: { 76: printf("\ttops of stack="); 77: prstack(tos); /* print top of stack element */ 78: } 79: # endif 80: /* check for stack overflow */ 81: l1 = getsymbol(++tos, &list); 82: 83: if (l1) 84: { 85: # ifdef xOTM 86: if (tTf(76, 2)) 87: timtrace(12, 0); 88: # endif 89: 90: freebuf(Ovqpbuf, cb_mark); 91: return ((struct symbol *) tos); 92: } 93: optype = tos->type; 94: opval = *tos->value; 95: tos--; /* assume that stack will be poped */ 96: 97: switch(optype) 98: { 99: case INT: 100: case FLOAT: 101: case CHAR: 102: ++tos; /* just leave symbol on stack */ 103: goto loop; 104: 105: case COP: 106: ++tos; /* new symbol goes on stack */ 107: tos->type = CHAR; 108: switch (opval) 109: { 110: 111: case opDBA: 112: cpderef(tos->value) = Admin.adhdr.adowner; 113: tos->len = 2; 114: goto loop; 115: 116: case opUSERCODE: 117: cpderef(tos->value) = Usercode; 118: tos->len = 2; 119: goto loop; 120: } 121: 122: case AND: /* if top value false return immediately */ 123: if (!*tos->value) 124: { 125: # ifdef xOTM 126: if (tTf(76, 2)) 127: timtrace(12, 0); 128: # endif 129: freebuf(Ovqpbuf, cb_mark); 130: return((struct symbol *) tos); 131: } 132: else 133: --tos; 134: freebuf(Ovqpbuf, cb_mark); 135: goto loop; 136: 137: case OR: /* if top value is true then skip to 138: ** end of disjunction. */ 139: if (*tos->value) 140: { 141: tos++; 142: do 143: { 144: getsymbol(tos, &list); 145: } while (tos->type != AND); 146: optype = AND; 147: --tos; 148: } 149: --tos; 150: goto loop; 151: 152: case RESDOM: 153: freebuf(Ovqpbuf, cb_mark); /* init the concat and ascii buffer */ 154: if (Result) 155: { 156: if (opval) /* if gt zero then opval represents a real domain */ 157: { 158: if (byflag) 159: opval++; /* skip over count field for ag functs */ 160: rcvt(tos, Result->relfrmt[opval], Result->relfrml[opval]); 161: tout(tos, Outtup+Result->reloff[opval], Result->relfrml[opval]); 162: } 163: else /* opval refers to the tid and this is an update */ 164: { 165: Uptid = i4deref(tos->value); /* copy tid */ 166: if (Ov_qmode == mdREPL || (Diffrel && Ov_qmode == mdDEL && Result->relindxd > 0 )) 167: { 168: /* Origtup must be left with the orig 169: ** unaltered tuple, and Outtup must 170: ** be initialized with the orig tuple. 171: ** 172: ** Outtup only matters with REPL. 173: ** Scan() sets up Origtup so when 174: ** Source == Result, origtup is already 175: ** correct. 176: */ 177: 178: if (Diffrel) 179: { 180: if (l1 = get(Result, &Uptid, &hitid, Origtup, CURTUP)) 181: syserr("interp:get on resdom %s, %d", locv(Uptid), l1); 182: bmove(Origtup, Outtup, Result->relwid); 183: } 184: else 185: { 186: bmove(Intup, Outtup, Result->relwid); 187: } 188: } 189: } 190: } 191: else 192: { 193: if (Equel) 194: equelatt(tos); /* send attribute to equel */ 195: else 196: { 197: if (tos->type == CHAR) 198: s1 = cpderef(tos->value); 199: else 200: s1 = (char *) tos->value; 201: printatt(tos->type, tos->len & 0377, s1); /* print attribute */ 202: } 203: } 204: --tos; 205: goto loop; 206: 207: 208: case BOP: 209: op2 = (struct symbol *) tos--; 210: op1 = (struct symbol *) tos; 211: typecheck(op1, op2, opval); 212: val1 = op1->value; 213: val2 = op2->value; 214: 215: switch (tos->type) 216: { 217: case INT: 218: switch (tos->len) 219: { 220: case 1: 221: case 2: 222: switch (opval) 223: { 224: case opADD: 225: *val1 += *val2; 226: goto loop; 227: case opSUB: 228: *val1 -= *val2; 229: goto loop; 230: case opMUL: 231: *val1 *= *val2; 232: goto loop; 233: case opDIV: 234: *val1 /= *val2; 235: goto loop; 236: case opMOD: 237: *val1 %= *val2; 238: goto loop; 239: 240: 241: case opPOW: 242: itof(op1); 243: itof(op2); 244: f8deref(val1) = pow(f8deref(val1), f8deref(val2)); 245: goto loop; 246: 247: 248: /* relational operator */ 249: default: 250: l1 = *val1 - *val2; 251: *val1 = relop_interp(opval, l1); 252: goto loop; 253: } 254: 255: case 4: 256: switch(opval) 257: { 258: case opADD: 259: i4deref(val1) += i4deref(val2); 260: goto loop; 261: 262: case opSUB: 263: i4deref(val1) -= i4deref(val2); 264: goto loop; 265: 266: case opMUL: 267: i4deref(val1) *= i4deref(val2); 268: goto loop; 269: 270: case opDIV: 271: i4deref(val1) /= i4deref(val2); 272: goto loop; 273: 274: case opMOD: 275: i4deref(val1) %= i4deref(val2); 276: goto loop; 277: 278: case opPOW: 279: itof(op1); 280: itof(op2); 281: f8deref(val1) = pow(f8deref(val1), f8deref(val2)); 282: goto loop; 283: 284: /* relational operator */ 285: default: 286: tos->len =2; 287: if (i4deref(val1) > i4deref(val2)) 288: l1 = 1; 289: else 290: if (i4deref(val1) == i4deref(val2)) 291: l1 = 0; 292: else 293: l1 = -1; 294: 295: *val1 = relop_interp(opval, l1); 296: goto loop; 297: 298: } 299: } 300: 301: case FLOAT: 302: switch (opval) 303: { 304: case opADD: 305: f8deref(val1) += f8deref(val2); 306: goto loop; 307: 308: case opSUB: 309: f8deref(val1) -= f8deref(val2); 310: goto loop; 311: 312: case opMUL: 313: f8deref(val1) *= f8deref(val2); 314: goto loop; 315: 316: case opDIV: 317: f8deref(val1) /= f8deref(val2); 318: goto loop; 319: 320: case opPOW: 321: f8deref(val1) = pow(f8deref(val1), f8deref(val2)); 322: goto loop; 323: 324: default: 325: tos->type = INT; 326: tos->len = 2; 327: if (f8deref(val1) > f8deref(val2)) 328: l1 = 1; 329: else 330: if (f8deref(val1) == f8deref(val2)) 331: l1 = 0; 332: else 333: l1 = -1; 334: *val1 = relop_interp(opval, l1); 335: goto loop; 336: } 337: 338: case CHAR: 339: if (opval == opCONCAT) 340: { 341: concatsym(op1, op2); /* concatenate the two symbols */ 342: goto loop; 343: } 344: l1 = lexcomp(cpderef(val1), op1->len & 0377, cpderef(val2), op2->len & 0377); 345: tos->type = INT; 346: tos->len = 2; 347: *val1 = relop_interp(opval, l1); 348: goto loop; 349: } /* end of BOP */ 350: 351: case UOP: 352: val1 = tos->value; 353: switch (opval) 354: { 355: case opMINUS: 356: case opABS: 357: if (tos->type == CHAR) 358: ov_err(BADUOPC); 359: l1 = opval == opMINUS; 360: switch (tos->type) 361: { 362: case INT: 363: switch (tos->len) 364: { 365: case 1: 366: case 2: 367: if (l1 || (*val1 < 0)) 368: *val1 = -*val1; 369: goto loop; 370: 371: case 4: 372: if (l1 || (i4deref(val1) < 0)) 373: i4deref(val1) = -i4deref(val1); 374: goto loop; 375: } 376: 377: case FLOAT: 378: if (l1 || (f8deref(val1) < 0.0)) 379: f8deref(val1) = -f8deref(val1); 380: goto loop; 381: } 382: 383: case opNOT: 384: *val1 = !*val1; 385: case opPLUS: 386: if (tos->type == CHAR) 387: ov_err(BADUOPC); 388: goto loop; 389: 390: case opASCII: 391: ascii(tos); 392: goto loop; 393: 394: case opINT1: 395: typecoerce(tos, INT, 1); 396: goto loop; 397: 398: case opINT2: 399: typecoerce(tos, INT, 2); 400: goto loop; 401: 402: case opINT4: 403: typecoerce(tos, INT, 4); 404: goto loop; 405: 406: case opFLOAT4: 407: typecoerce(tos, FLOAT, 4); 408: goto loop; 409: 410: case opFLOAT8: 411: typecoerce(tos, FLOAT, 8); 412: goto loop; 413: 414: default: 415: if (tos->type == CHAR) 416: ov_err(BADUOPC); 417: if (tos->type == INT) 418: itof(tos); 419: switch (opval) 420: { 421: case opATAN: 422: f8deref(val1) = atan(f8deref(val1)); 423: goto loop; 424: 425: case opGAMMA: 426: f8deref(val1) = gamma(f8deref(val1)); 427: goto loop; 428: 429: case opLOG: 430: f8deref(val1) = log(f8deref(val1)); 431: goto loop; 432: 433: case opSIN: 434: f8deref(val1) = sin(f8deref(val1)); 435: goto loop; 436: 437: case opCOS: 438: f8deref(val1) = cos(f8deref(val1)); 439: goto loop; 440: 441: case opSQRT: 442: f8deref(val1) = sqrt(f8deref(val1)); 443: goto loop; 444: 445: case opEXP: 446: f8deref(val1) = exp(f8deref(val1)); 447: goto loop; 448: 449: default: 450: syserr("interp:bad uop %d",opval); 451: } 452: } 453: 454: 455: case AOP: 456: aop_interp(opval, tos); 457: goto loop; 458: 459: } 460: } 461: 462: 463: 464: relop_interp(opval, l1) 465: int opval; 466: int l1; 467: 468: /* 469: ** relop_interp interprets the relational operators 470: ** (ie. EQ, NE etc.) and returns true or false 471: ** by evaluating l1. 472: ** 473: ** l1 should be greater than, equal or less than zero. 474: */ 475: 476: { 477: register int i; 478: 479: i = l1; 480: 481: switch (opval) 482: { 483: 484: case opEQ: 485: return (i == 0); 486: 487: case opNE: 488: return (i != 0); 489: 490: case opLT: 491: return (i < 0); 492: 493: case opLE: 494: return (i <= 0); 495: 496: case opGT: 497: return (i > 0); 498: 499: case opGE: 500: return (i >= 0); 501: 502: default: 503: syserr("relop:bad relop or bop %d", opval); 504: } 505: } 506: 507: aop_interp(opval, tosp) 508: struct stacksym *tosp; 509: 510: /* 511: ** Aggregate values are stored in Outtup. Tend points 512: ** to the spot for the next aggregate. Aop_interp() 513: ** computes the value for the aggregate and leaves 514: ** the result in the position pointed to by Tend. 515: */ 516: 517: { 518: register struct stacksym *tos; 519: register char *number; 520: register int i; 521: int l1; 522: char numb[8]; /* used for type conversion */ 523: 524: tos = tosp; 525: number = numb; 526: bmove(Tend, number, 8); /* note: this assumes that there are always 8 bytes which can be moved. 527: ** if it moves beyond Tend, it's ok */ 528: switch (opval) 529: { 530: 531: case opSUMU: 532: case opSUM: 533: if (*Counter <= 1) 534: goto puta; 535: switch (tos->type) 536: { 537: case INT: 538: switch(tos->len) 539: { 540: case 1: 541: i1deref(tos->value) += i1deref(number); 542: goto puta; 543: 544: case 2: 545: i2deref(tos->value) += i2deref(number); 546: goto puta; 547: 548: case 4: 549: i4deref(tos->value) += i4deref(number); 550: goto puta; 551: } 552: 553: case FLOAT: 554: if (tos->len == 4) 555: f8deref(number) = f4deref(number); 556: f8deref(tos->value) += f8deref(number); 557: goto puta; 558: 559: default: 560: ov_err(BADSUMC); /* cant sum char fields */ 561: } 562: 563: case opCOUNTU: 564: case opCOUNT: 565: tos->type = CNTTYPE; 566: tos->len = CNTLEN; 567: i4deref(tos->value) = *Counter; 568: goto puta; 569: 570: case opANY: 571: tos->type = ANYTYPE; 572: tos->len = ANYLEN; 573: if (*Counter) 574: { 575: *tos->value = 1; 576: if (!Bylist && (Agcount == 1)) 577: Targvc = 0; /* if simple agg. stop scan */ 578: } 579: else 580: *tos->value = 0; 581: goto puta; 582: 583: case opMIN: 584: case opMAX: 585: if (*Counter<=1) 586: goto puta; 587: switch (tos->type) 588: { 589: case INT: 590: switch (tos->len) 591: { 592: case 1: 593: i = (i1deref(tos->value) < i1deref(number)); 594: break; 595: 596: case 2: 597: i = (i2deref(tos->value) < i2deref(number)); 598: break; 599: 600: case 4: 601: i = (i4deref(tos->value) < i4deref(number)); 602: break; 603: } 604: break; 605: 606: case FLOAT: 607: if (tos->len == 4) 608: f8deref(number) = f4deref(number); 609: i = (f8deref(tos->value) < f8deref(number)); 610: break; 611: 612: case CHAR: 613: l1 = tos->len & 0377; 614: i = (lexcomp(cpderef(tos->value), l1, Tend, l1) < 0); 615: break; 616: 617: default: 618: syserr("interp:bad op type for opMIN/MAX %d", tos->type); 619: } 620: 621: /* check result of comparison */ 622: if (opval == opMAX) 623: i = !i; /* complement test for opMAX */ 624: if (i) 625: goto puta; /* condition true. new value */ 626: 627: /* condition false. Keep old value */ 628: goto done; 629: 630: 631: case opAVGU: 632: case opAVG: 633: if (tos->type == INT) 634: itof(tos); 635: else 636: if (tos->type == CHAR) 637: ov_err(BADAVG); 638: if (*Counter > 1) 639: { 640: f8deref(tos->value) = f8deref(number) + (f8deref(tos->value) - f8deref(number))/ *Counter; 641: } 642: tos->len = 8; 643: goto puta; 644: 645: default: 646: syserr("interp:bad agg op %d", tos->type); 647: } 648: 649: puta: 650: tout(tos, Tend, tos->len); 651: done: 652: Tend += tos->len & 0377; 653: }