# include <ingres.h> # include <aux.h> # include <tree.h> # include <symbol.h> # include "parser.h" # include <sccs.h> # include <errors.h> SCCSID(@(#)format.c 8.2 2/8/85) /* ** FORMAT ** routine to compute the format of the result relation attributes ** it is called after ATTLOOKUP so the tuple defining the current ** attribute is already available. ** if the element is a function of more than one attribute, the result ** domain format is computed by the following rules: ** - no fcns allowed on character attributes ** - fcn of integer attribs is an integer fcn with ** length = MAX(length of all attributes) ** - fcn of floating point attribs is a floating point ** fcn with length = MIN(length of all attribs) ** - fcn of integer and floating attributes is a ** floating fcn with length = MIN(length of all floating ** attributes) ** ** Trace Flags: ** Format ~~ 52.0, 52.1 */ format(result1) QTREE *result1; { register char rfrmt; register char rfrml; register QTREE *result; struct constop *cpt; extern struct out_arg Out_arg; extern struct constop Coptab[]; extern char Trfrml; extern char Trfrmt; extern int Qlflag; # ifdef xPTR2 tTfp(52, 0, "format:.\n"); # endif result = result1; switch (result->sym.type) { case VAR: rfrmt = result->sym.value.sym_var.varfrmt; rfrml = result->sym.value.sym_var.varfrml; break; case AOP: switch (result->sym.value.sym_op.opno) { case opAVG: case opAVGU: rfrmt = FLOAT; rfrml = 8; if (result->sym.value.sym_op.agfrmt == CHAR) /* character domain not allowed in these aggs */ par_error(AVGTYPE, WARN, 0); break; case opCOUNT: case opCOUNTU: rfrmt = INT; rfrml = 4; break; case opANY: rfrmt = INT; rfrml = 2; break; case opSUM: case opSUMU: rfrmt = result->sym.value.sym_op.agfrmt; rfrml = result->sym.value.sym_op.agfrml; if (rfrmt == CHAR) /* no char domains for these aggs */ par_error(SUMTYPE, WARN, 0); break; default: rfrmt = result->sym.value.sym_op.agfrmt; rfrml = result->sym.value.sym_op.agfrml; break; } break; case AGHEAD: /* ** can get format info from the AOP node because ** it already has format info computed */ if (result->left->sym.type == AOP) { /* no by-list */ rfrmt = result->left->sym.value.sym_op.opfrmt; rfrml = result->left->sym.value.sym_op.opfrml; } else { /* skip over by-list */ rfrmt = result->left->right->sym.value.sym_resdom.resfrmt; rfrml = result->left->right->sym.value.sym_resdom.resfrml; } break; case RESDOM: format(result->right); return; case INT: case FLOAT: case CHAR: rfrmt = result->sym.type; rfrml = result->sym.len; break; case COP: for (cpt = Coptab; cpt->copname; cpt++) { if (result->sym.value.sym_op.opno == cpt->copnum) { rfrmt = cpt->coptype; rfrml = cpt->coplen; break; } } if (!cpt->copname) syserr("bad cop in format(%d)", result->sym.value.sym_op.opno); break; case UOP: switch (result->sym.value.sym_op.opno) { case opATAN: case opCOS: # ifdef xV6_UNIX case opGAMMA: # endif case opLOG: case opSIN: case opSQRT: case opEXP: format(result->left); if (Trfrmt == CHAR) /* ** no character expr in FOP ** if more ops are added, must change error message */ par_error(FOPTYPE, WARN, 0); case opFLOAT8: /* float8 is type conversion and can have char values */ rfrmt = FLOAT; rfrml = 8; break; case opFLOAT4: rfrmt = FLOAT; rfrml = 4; break; case opINT1: rfrmt = INT; rfrml = 1; break; case opINT2: rfrmt = INT; rfrml = 2; break; case opINT4: rfrmt = INT; rfrml = 4; break; case opASCII: format(result->left); rfrmt = CHAR; rfrml = Trfrml; if (Trfrmt == INT) { if (Trfrml == 2) rfrml = Out_arg.i2width; else if (Trfrml == 4) rfrml = Out_arg.i4width; else if (Trfrml == 1) rfrml = Out_arg.i1width; else syserr("bad length %d for INT", Trfrml); break; } if (Trfrmt == FLOAT) { if (Trfrml == 8) rfrml = Out_arg.f8width; else if (Trfrml == 4) rfrml = Out_arg.f4width; else syserr("bad length %d for FLOAT", Trfrml); break; } if (Trfrmt == CHAR) break; syserr("bad frmt in opASCII %d", Trfrmt); case opNOT: if (!Qlflag) syserr("opNOT in targ list"); return; case opMINUS: case opPLUS: format(result->right); if (Trfrmt == CHAR) /* no chars for these unary ops */ par_error(UOPTYPE, WARN, 0); return; case opABS: format(result->left); if (Trfrmt == CHAR) /* no char values in fcn */ par_error(FOPTYPE, WARN, 0); return; default: syserr("bad UOP in format %d", result->sym.value.sym_op.opno); } break; case BOP: switch (result->sym.value.sym_op.opno) { case opEQ: case opNE: case opLT: case opLE: case opGT: case opGE: if (!Qlflag) syserr("LBOP in targ list"); format(result->right); rfrmt = Trfrmt; format(result->left); if ((rfrmt == CHAR) != (Trfrmt == CHAR)) /* type conflict on relational operator */ par_error(RELTYPE, WARN, 0); return; case opADD: case opSUB: format(result->left); rfrmt = Trfrmt; rfrml = Trfrml; format(result->right); if (rfrmt == FLOAT || Trfrmt == FLOAT) { if (rfrmt == FLOAT && Trfrmt == FLOAT) { if (Trfrml < rfrml) rfrml = Trfrml; } else if (Trfrmt == FLOAT) rfrml = Trfrml; rfrmt = FLOAT; } else if (Trfrml > rfrml) rfrml = Trfrml; break; case opMUL: case opDIV: format(result->left); rfrmt = Trfrmt; rfrml = Trfrml; format(result->right); if ((rfrmt == CHAR || Trfrmt == CHAR)) par_error(NUMTYPE, WARN, 0); if (rfrmt == FLOAT || Trfrmt == FLOAT) { if (rfrmt == FLOAT && Trfrmt == FLOAT) { if (Trfrml < rfrml) rfrml = Trfrml; } else if (Trfrmt == FLOAT) rfrml = Trfrml; rfrmt = FLOAT; } else if (Trfrml > rfrml) rfrml = Trfrml; break; case opMOD: format(result->left); rfrmt = Trfrmt; rfrml = Trfrml; format(result->right); if (rfrmt != INT || Trfrmt != INT) /* mod operator not defined */ par_error(MODTYPE, WARN, 0); if (Trfrml > rfrml) rfrml = Trfrml; break; case opPOW: format(result->right); rfrmt = Trfrmt; rfrml = Trfrml; format(result->left); if (rfrmt == CHAR || Trfrmt == CHAR) /* no char values for pow */ par_error(NUMTYPE, WARN, 0); if ((rfrmt == FLOAT && rfrml == 4) || (Trfrmt == FLOAT && Trfrml == 4)) { rfrmt = FLOAT; rfrml = 4; } else { rfrmt = FLOAT; rfrml = 8; } break; case opCONCAT: format(result->left); rfrmt = Trfrmt; rfrml = Trfrml; format(result->right); if (rfrmt != CHAR || Trfrmt != CHAR) /* only character domains allowed */ par_error(CONCATTYPE, WARN, 0); rfrml += Trfrml; break; default: syserr("bad BOP in format %d", result->sym.value.sym_op.opno); } } Trfrmt = rfrmt; Trfrml = rfrml; # ifdef xPTR2 tTfp(52, 2, "format>>: Trfrmt = %d, Trfrml = %d.\n", Trfrmt, Trfrml); # endif }