4.3BSD/usr/ingres/source/dbu/pr_tree.c
# include <symbol.h>
# include <ingres.h>
# include <tree.h>
# include <aux.h>
# include <sccs.h>
SCCSID(@(#)pr_tree.c 8.2 1/15/85)
/*
** PR_TREE.C -- Query tree printing routines
**
** Trace Flags:
** 52
*/
char *pr_trim();
char *resultres();
struct tab
{
char t_opcode;
char *t_string;
};
struct tab Uop_tab[] =
{
opPLUS, "+ ",
opMINUS, "- ",
opNOT, "not[ERROR]",
opATAN, "atan",
opCOS, "cos",
opGAMMA, "gamma",
opLOG, "log",
opASCII, "ascii",
opSIN, "sin",
opSQRT, "sqrt",
opABS, "abs",
opEXP, "exp",
opINT1, "int1",
opINT2, "int2",
opINT4, "int4",
opFLOAT4, "float4",
opFLOAT8, "float8",
};
struct tab Bop_tab[] =
{
opADD, "+",
opSUB, "-",
opMUL, "*",
opDIV, "/",
opPOW, "**",
opEQ, "=",
opNE, "!=",
opLT, "<",
opLE, "<=",
opGT, ">",
opGE, ">=",
opMOD, "%",
};
struct tab Cop_tab[] =
{
opDBA, "dba",
opUSERCODE, "usercode",
opDATE, "date",
opTIME, "time",
};
struct tab Aop_tab[] =
{
opCOUNT, "count",
opCOUNTU, "countu",
opSUM, "sum",
opSUMU, "sumu",
opAVG, "avg",
opAVGU, "avgu",
opMIN, "min",
opMAX, "max",
opANY, "any",
};
DESC Attdes;
int Tl_elm;
int Dom_num;
char *Resrel;
/*
** PR_TREE
**
** tree: tl_clause ROOT tl_clause
**
** prints out a tree assuming a mdVIEW-like mode
**
*/
pr_tree(root)
QTREE *root;
{
# ifdef xZTR1
if (tTf(52, -1))
printf("pr_tree: root %u Resultvar %d Resrel %s\n",
root, Qt.qt_resvar, Resrel);
# endif
printf("%s ", pr_trim(resultres(), MAXNAME));
pr_dom_init();
Tl_elm = 0;
/* print target list */
printf("(\n");
pr_tl_clause(root->left, TRUE);
putchar(')');
/* print qualification */
if (root->right->sym.type != QLEND)
{
printf("\nwhere ");
pr_qual(root->right);
}
putchar('\n');
}
/*
** PR_TL_CLAUSE
**
** tl_clause: TREE
** | tl_clause RESDOM expr
**
** target_flag = "in a target list (as opposed to in a by list)"
*/
pr_tl_clause(t_l, target_flag)
QTREE *t_l;
register bool target_flag;
{
# ifdef xZTR1
if (tTf(52, 1))
printf("tl_clause target %d Tl_elm %d\n", target_flag, Tl_elm);
# endif
if (t_l->sym.type != TREE)
{
pr_tl_clause(t_l->left, target_flag);
if (Tl_elm)
{
printf(", ");
if (target_flag)
putchar('\n');
}
/* print out info on result variable */
pr_resdom(t_l, target_flag);
pr_expr(t_l->right);
Tl_elm++;
}
}
/*
** PR_RESDOM
**
** print out info on a result attribute.
** this will be done only if the RESDOM node
** is inside a target_list and if the Qt.qt_resvar >= 0.
** Qt.qt_resvar == -1 inside a target list indicates that this is
** a retrieve to terminal.
*/
pr_resdom(resdom, target_flag)
QTREE *resdom;
int target_flag;
{
# ifdef xZTR1
if (tTf(52, 2))
printf("pr_resdom: target_flag %d\n", target_flag);
# endif
if (target_flag)
{
printf("\t");
pr_attname(resultres(), resdom->sym.value.sym_resdom.resno);
printf(" = ");
}
}
/*
** PR_ATTNAME
**
** give a relation name, and the attribute number of that
** relation, looks in the attribute relation for the name of the
** attribute.
*/
pr_attname(rel, attno)
char *rel;
int attno;
{
TID tid;
struct attribute key, tuple;
short attnum;
register i;
# ifdef xZTR1
if (tTf(52, 3))
printf("pr_attname: rel %s attno %d\n",
rel, attno);
# endif
if (attno == 0)
{
printf("tid");
return;
}
opencatalog("attribute", OR_READ);
clearkeys(&Attdes);
attnum = (short) attno;
setkey(&Attdes, &key, rel, ATTRELID);
setkey(&Attdes, &key, &attnum, ATTID);
i = getequal(&Attdes, &key, &tuple, &tid);
if (i)
syserr("pr_attname: bad getequal %d rel %s attno %d",
i, rel, attno);
printf("%s", pr_trim(tuple.attname, MAXNAME));
}
/*
** PR_EXPR
**
** expr: VAR
** | expr BOP expr
** | expr UOP
** | AOP AGHEAD qual
** \
** expr
** | BYHEAD AGHEAD qual
** / \
** tl_clause AOP
** \
** expr
** | INT
** | FLOAT
** | CHAR
*/
pr_expr(e)
register QTREE *e;
{
register int op;
register int tl_elm;
switch (e->sym.type)
{
case VAR:
pr_var(e);
break;
case BOP:
if (e->sym.value.sym_op.opno == opCONCAT)
{
printf("concat(");
pr_expr(e->left);
printf(", ");
pr_expr(e->right);
putchar(')');
}
else
{
putchar('(');
pr_expr(e->left);
pr_op(BOP, e->sym.value.sym_op.opno);
pr_expr(e->right);
putchar(')');
}
break;
case UOP:
if ((op = e->sym.value.sym_op.opno) == opMINUS || op == opPLUS || op == opNOT)
{
pr_op(UOP, e->sym.value.sym_op.opno);
pr_expr(e->left);
putchar(')');
}
else
{
/* functional operators */
pr_op(UOP, e->sym.value.sym_op.opno);
pr_expr(e->left);
putchar(')');
}
break;
case AGHEAD:
if (e->left->sym.type == AOP)
{
/* simple aggregate */
pr_op(AOP, e->left->sym.value.sym_op.opno);
pr_expr(e->left->right);
if (e->right->sym.type != QLEND)
{
printf("\where ");
pr_qual(e->right);
}
putchar(')');
}
else
{
/* aggregate function */
pr_op(AOP, e->left->right->sym.value.sym_op.opno);
pr_expr(e->left->right->right);
printf(" by ");
/* avoid counting target list elements
* in determining wether to put out
* commas after list's elements
*/
tl_elm = Tl_elm;
Tl_elm = 0;
pr_tl_clause(e->left->left, FALSE);
Tl_elm = tl_elm;
if (e->right->sym.type != QLEND)
{
printf("\n\t\twhere ");
pr_qual(e->right);
}
putchar(')');
}
break;
case INT:
case FLOAT:
case CHAR:
pr_const(e);
break;
default:
syserr("expr %d", e->sym.type);
}
}
/*
** PR_CONST -- print constant
*/
pr_const(c)
register QTREE *c;
{
register char *cp;
register int i;
char ch;
double d;
switch (c->sym.type)
{
case INT:
if (c->sym.len == 1)
printf("%d", c->sym.value.sym_data.i1type);
else if (c->sym.len == 2)
printf("%d", c->sym.value.sym_data.i2type);
else /* i4 */
printf("%D", c->sym.value.sym_data.i4type);
break;
case FLOAT:
if (c->sym.len == 4)
d = c->sym.value.sym_data.f4type;
else
d = c->sym.value.sym_data.f8type;
printf("%-10.3f", c->sym.value.sym_data.f8type);
break;
case CHAR:
printf("\"");
cp = c->sym.value.sym_data.c0type;
for (i = c->sym.len; i--; cp++)
{
if (any(*cp, "\"\\[]*?") == TRUE)
putchar('\\');
if (*cp >= ' ')
{
putchar(*cp);
continue;
}
/* perform pattern matching character replacement */
switch (*cp)
{
case PAT_ANY:
ch = '*';
break;
case PAT_ONE:
ch = '?';
break;
case PAT_LBRAC:
ch = '[';
break;
case PAT_RBRAC:
ch = ']';
break;
default:
ch = *cp;
}
putchar(ch);
}
putchar('"');
break;
default:
syserr("bad constant %d", c->sym.type);
}
}
/*
** PR_OP -- print out operator of a certain type
*/
pr_op(op_type, op_code)
int op_type;
register int op_code;
{
register struct tab *s;
switch (op_type)
{
case UOP:
s = &Uop_tab[op_code];
printf("%s(", s->t_string);
break;
case BOP:
s = &Bop_tab[op_code];
printf(" %s ", s->t_string);
break;
case AOP:
s = &Aop_tab[op_code];
printf("%s(", s->t_string);
break;
case COP:
s = &Cop_tab[op_code];
printf("%s", s->t_string);
break;
}
if (op_code != s->t_opcode)
syserr("pr_op: op in wrong place type %d, code %d", op_type,
s->t_opcode);
}
/*
** PR_VAR
**
** print a VAR node: that is, a var.attno pair
** at present the var part is the relation name over which var
** ranges.
*/
pr_var(var)
QTREE *var;
{
# ifdef xZTR1
if (tTf(52, 4))
printf("pr_var(var=%d)\n", var);
# endif
pr_rv(var->sym.value.sym_var.varno);
putchar('.');
pr_attname(Qt.qt_rangev[var->sym.value.sym_var.varno].rngvdesc->reldum.relid, var->sym.value.sym_var.attno);
}
/*
** PR_QUAL
**
** qual: QLEND
** | q_clause AND qual
**
*/
pr_qual(q)
register QTREE *q;
{
pr_q_clause(q->left);
if (q->right->sym.type != QLEND)
{
printf(" and ");
pr_qual(q->right);
}
}
/*
** PR_Q_CLAUSE
**
** q_clause: q_clause OR q_clause
** | expr
*/
pr_q_clause(q)
QTREE *q;
{
if (q->sym.type == OR)
{
pr_q_clause(q->left);
printf(" or ");
pr_q_clause(q->right);
}
else
pr_expr(q);
}
/*
** PR_TRIM
*/
char *
pr_trim(s, l)
register char *s;
register int l;
{
static char buf[30];
bmove(s, buf, l);
for (s = buf; l && *s != ' ' && *s; --l)
s++;
*s = '\0';
return (buf);
}
/*
** PR_DOM_INIT
*/
pr_dom_init()
{
Dom_num = 0;
}
pr_ddom()
{
printf("d%d = ", Dom_num++);
}
/*
** PR_RANGE -- print the range table
*/
pr_range()
{
register int i;
for (i = 0; i <= MAXVAR; i++)
{
if (Qt.qt_rangev[i].rngvdesc != NULL)
{
printf("range of ");
pr_rv(i);
printf(" is %s\n",
pr_trim(Qt.qt_rangev[i].rngvdesc->reldum.relid, MAXNAME));
}
}
}
/*
** PR_RV -- print range variable
*/
pr_rv(re)
register int re;
{
register int j;
register char ch;
ch = Qt.qt_rangev[re].rngvdesc->reldum.relid[0];
# ifdef xZTR1
if (tTf(52, 6))
printf("pr_rv(%d) ch '%c'\n", re, ch);
# endif
for (j = 0; j <= MAXVAR; j++)
{
if (Qt.qt_rangev[j].rngvdesc == NULL)
continue;
if (ch == Qt.qt_rangev[j].rngvdesc->reldum.relid[0])
break;
}
if (j < re)
printf("rv%d", re);
else
printf("%c", ch);
}
/*
** RESULTRES
*/
char *
resultres()
{
extern char *Resrel;
# ifdef xZTR1
if (tTf(52, 5))
printf("resultres: Resultvar %d, Resrel %s\n", Qt.qt_resvar, Resrel);
# endif
if (Qt.qt_resvar > 0)
return (Qt.qt_rangev[Qt.qt_resvar].rngvdesc->reldum.relid);
if (Resrel == 0)
syserr("resultres: Resrel == 0");
return (Resrel);
}
any(c, s)
register char c;
register char *s;
{
while (*s != '\0')
if (*s++ == c)
return (TRUE);
return (FALSE);
}