334 lines
6.8 KiB
C
334 lines
6.8 KiB
C
# include <stdio.h>
|
|
# include "gen.h"
|
|
# include "../h/dbs.h"
|
|
# include "../h/aux.h"
|
|
# include "../h/tree.h"
|
|
# include "../h/pipes.h"
|
|
# include "../h/symbol.h"
|
|
# include "parser.h"
|
|
|
|
char Trfrmt; /* format for type checking */
|
|
char Trfrml; /* format length for type checking */
|
|
|
|
/*
|
|
** 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)
|
|
*/
|
|
format(result1)
|
|
QTREE *result1;
|
|
{
|
|
register char rfrmt;
|
|
register char rfrml;
|
|
register QTREE *result;
|
|
struct constop *cpt;
|
|
extern struct out_arg AAout_arg;
|
|
extern struct constop Coptab[];
|
|
|
|
result = result1;
|
|
switch (result->sym.type)
|
|
{
|
|
case VAR:
|
|
rfrmt = ((VAR_NODE *) result)->frmt;
|
|
rfrml = ((VAR_NODE *) result)->frml;
|
|
break;
|
|
|
|
case AOP:
|
|
switch (((OP_NODE *) result)->opno)
|
|
{
|
|
case opAVG:
|
|
case opAVGU:
|
|
rfrmt = FLOAT;
|
|
rfrml = sizeof (double);
|
|
if (((AOP_NODE *) result)->agfrmt == CHAR)
|
|
/* character domain not allowed in these aggs */
|
|
yyerror(AVGTYPE, (char *) 0);
|
|
break;
|
|
|
|
case opCNT:
|
|
case opCNTU:
|
|
rfrmt = INT;
|
|
rfrml = sizeof (long);
|
|
break;
|
|
|
|
case opANY:
|
|
rfrmt = INT;
|
|
rfrml = sizeof (short);
|
|
break;
|
|
|
|
case opSUM:
|
|
case opSUMU:
|
|
rfrmt = ((AOP_NODE *) result)->agfrmt;
|
|
rfrml = ((AOP_NODE *) result)->agfrml;
|
|
if (rfrmt == CHAR)
|
|
/* no char domains for these aggs */
|
|
yyerror(SUMTYPE, (char *) 0);
|
|
break;
|
|
|
|
default:
|
|
rfrmt = ((AOP_NODE *) result)->agfrmt;
|
|
rfrml = ((AOP_NODE *) result)->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 = ((VAR_NODE *) result->left)->frmt;
|
|
rfrml = ((VAR_NODE *) result->left)->frml;
|
|
}
|
|
else
|
|
{
|
|
/* skip over by-list */
|
|
rfrmt = ((VAR_NODE *) result->left->right)->frmt;
|
|
rfrml = ((VAR_NODE *) result->left->right)->frml;
|
|
}
|
|
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 (((OP_NODE *) result)->opno == cpt->copnum)
|
|
{
|
|
rfrmt = cpt->coptype;
|
|
rfrml = cpt->coplen;
|
|
break;
|
|
}
|
|
}
|
|
if (!cpt->copname)
|
|
AAsyserr(18002, ((OP_NODE *) result)->opno);
|
|
break;
|
|
|
|
case UOP:
|
|
switch (((OP_NODE *) result)->opno)
|
|
{
|
|
case opATAN:
|
|
case opCOS:
|
|
case opGAMMA:
|
|
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 */
|
|
yyerror(FOPTYPE, (char *) 0);
|
|
|
|
case opFLT8:
|
|
/* float8 is type conversion and can have char values */
|
|
rfrmt = FLOAT;
|
|
rfrml = sizeof (double);
|
|
break;
|
|
|
|
# ifndef NO_F4
|
|
case opFLT4:
|
|
rfrmt = FLOAT;
|
|
rfrml = sizeof (float);
|
|
break;
|
|
# endif
|
|
|
|
case opINT1:
|
|
rfrmt = INT;
|
|
rfrml = sizeof (char);
|
|
break;
|
|
|
|
case opINT2:
|
|
rfrmt = INT;
|
|
rfrml = sizeof (short);
|
|
break;
|
|
|
|
case opINT4:
|
|
rfrmt = INT;
|
|
rfrml = sizeof (long);
|
|
break;
|
|
|
|
case opASCII:
|
|
format(result->left);
|
|
rfrmt = CHAR;
|
|
rfrml = Trfrml;
|
|
if (Trfrmt == INT)
|
|
{
|
|
if (Trfrml == sizeof (short))
|
|
rfrml = AAout_arg.i2width;
|
|
else if (Trfrml == sizeof (long))
|
|
rfrml = AAout_arg.i4width;
|
|
else if (Trfrml == sizeof (char))
|
|
rfrml = AAout_arg.i1width;
|
|
else
|
|
AAsyserr(18003, Trfrml);
|
|
break;
|
|
}
|
|
if (Trfrmt == FLOAT)
|
|
{
|
|
if (Trfrml == sizeof (double))
|
|
rfrml = AAout_arg.f8width;
|
|
# ifndef NO_F4
|
|
else if (Trfrml == sizeof (float))
|
|
rfrml = AAout_arg.f4width;
|
|
# endif
|
|
else
|
|
AAsyserr(18004, Trfrml);
|
|
break;
|
|
}
|
|
if (Trfrmt == CHAR)
|
|
break;
|
|
AAsyserr(18005, Trfrmt);
|
|
|
|
case opNOT:
|
|
if (!Qlflag)
|
|
AAsyserr(18006);
|
|
return;
|
|
|
|
case opMINUS:
|
|
case opPLUS:
|
|
format(result->right);
|
|
if (Trfrmt == CHAR)
|
|
/* no chars for these unary ops */
|
|
yyerror(UOPTYPE, (char *) 0);
|
|
return;
|
|
|
|
case opABS:
|
|
format(result->left);
|
|
if (Trfrmt == CHAR)
|
|
/* no char values in fcn */
|
|
yyerror(FOPTYPE, (char *) 0);
|
|
return;
|
|
|
|
default:
|
|
AAsyserr(18007, ((OP_NODE *) result)->opno);
|
|
}
|
|
break;
|
|
|
|
case BOP:
|
|
switch (((OP_NODE *) result)->opno)
|
|
{
|
|
|
|
case opEQ:
|
|
case opNE:
|
|
case opLT:
|
|
case opLE:
|
|
case opGT:
|
|
case opGE:
|
|
if (!Qlflag)
|
|
AAsyserr(18008);
|
|
format(result->right);
|
|
rfrmt = Trfrmt;
|
|
format(result->left);
|
|
if ((rfrmt == CHAR) != (Trfrmt == CHAR))
|
|
/* type conflict on relational operator */
|
|
yyerror(RELTYPE, (char *) 0);
|
|
return;
|
|
|
|
case opADD:
|
|
case opSUB:
|
|
case opMUL:
|
|
case opDIV:
|
|
format(result->left);
|
|
rfrmt = Trfrmt;
|
|
rfrml = Trfrml;
|
|
format(result->right);
|
|
if (rfrmt == CHAR || Trfrmt == CHAR)
|
|
/* no opns on characters allowed */
|
|
yyerror(NUMTYPE, (char *) 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 */
|
|
yyerror(MODTYPE, (char *) 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 */
|
|
yyerror(NUMTYPE, (char *) 0);
|
|
}
|
|
# ifndef NO_F4
|
|
if ((rfrmt == FLOAT && rfrml == sizeof (float))
|
|
|| (Trfrmt == FLOAT && Trfrml == sizeof (float)))
|
|
{
|
|
rfrmt = FLOAT;
|
|
rfrml = sizeof (float);
|
|
}
|
|
else
|
|
# endif
|
|
{
|
|
rfrmt = FLOAT;
|
|
rfrml = sizeof (double);
|
|
}
|
|
break;
|
|
|
|
case opCONCAT:
|
|
format(result->left);
|
|
rfrmt = Trfrmt;
|
|
rfrml = Trfrml;
|
|
format(result->right);
|
|
if (rfrmt != CHAR || Trfrmt != CHAR)
|
|
/* only character domains allowed */
|
|
yyerror(CONCATTYPE, (char *) 0);
|
|
rfrml += Trfrml;
|
|
break;
|
|
|
|
default:
|
|
AAsyserr(18009, ((OP_NODE *) result)->opno);
|
|
}
|
|
}
|
|
Trfrmt = rfrmt;
|
|
Trfrml = rfrml;
|
|
}
|