|
|
BSD 4.3
# 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
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.