📄 interp.c
字号:
#include <stdio.h>#include "catalog.h"#include "query.h"#include "utility.h"#include "parse.h"#include "y.tab.h"#define E_OK 0#define E_INCOMPATIBLE -1#define E_TOOMANYATTRS -2#define E_NOLENGTH -3#define E_INVINTSIZE -4#define E_INVFLOATSIZE -5#define E_INVFORMATSTRING -6#define E_INVSTRLEN -7#define E_DUPLICATEATTR -8#define E_TOOLONG -9#define E_STRINGTOOLONG -10#define ERRFP stderr // error message go here#define MAXATTRS 40 // max. number of attrs in a relation//// prefab arrays of useful types//static REL_ATTR qual_attrs[MAXATTRS + 1];static ATTR_DESCR attr_descrs[MAXATTRS + 1];static ATTR_VAL ins_attrs[MAXATTRS + 1];static char *names[MAXATTRS + 1];static int mk_attrnames(NODE *list, char *attrnames[], char *relname);static int mk_qual_attrs(NODE *list, REL_ATTR qual_attrs[], char *relname1, char *relname2);static int mk_attr_descrs(NODE *list, ATTR_DESCR attr_descrs[]);static int mk_ins_attrs(NODE *list, ATTR_VAL ins_attrs[]);//static int parse_format_string(char *format_string, int *type, int *len);static int parse_format_string(int format, int *type, int *len);static void *value_of(NODE *n);static int type_of(NODE *n);static int length_of(NODE *n);static void print_error(char *errmsg, int errval);static void echo_query(NODE *n);static void print_qual(NODE *n);static void print_attrnames(NODE *n);static void print_attrdescrs(NODE *n);static void print_attrvals(NODE *n);static void print_primattr(NODE *n);static void print_qualattr(NODE *n);static void print_op(int op);static void print_val(NODE *n);static attrInfo attrList[MAXATTRS];static attrInfo attr1;static attrInfo attr2;extern "C" int isatty(int fd); // returns 1 if fd is a tty device//// interp: interprets parse trees//// No return value.//void interp(NODE *n){ int nattrs; // number of attributes int type; // attribute type int len; // attribute length int op; // comparison operator NODE *temp, *temp1, *temp2; // temporary node pointers char *attrname; // temp attribute names void *value; // temp value int nbuckets; // temp number of buckets int errval; // returned error value RelDesc relDesc; Status status; int attrCnt, i, j; AttrDesc *attrs; string resultName; static int counter = 0; // if input not coming from a terminal, then echo the query if (!isatty(0)) echo_query(n); switch(n->kind) { case N_QUERY: // First check if the result relation is specified if (n->u.QUERY.relname) { resultName = n->u.QUERY.relname; // Check if the result relation exists. status = attrCat->getRelInfo(resultName, attrCnt, attrs); if (status != OK && status != RELNOTFOUND) { error.print(status); return; } } else { resultName = "Tmp_Ubase_Result"; status = relCat->getInfo(resultName, relDesc); if (status != OK && status != RELNOTFOUND) { error.print(status); return; } if (status == OK) { error.print(TMP_RES_EXISTS); return; } } // if no qualification then this is a simple select temp = n->u.QUERY.qual; if (temp == NULL) { // make a list of attribute names suitable for passing to select nattrs = mk_attrnames(temp1 = n->u.QUERY.attrlist, names, NULL); if (nattrs < 0) { print_error("select", nattrs); break; } for(int acnt = 0; acnt < nattrs; acnt++) { strcpy(attrList[acnt].relName, names[nattrs]); strcpy(attrList[acnt].attrName, names[acnt]); attrList[acnt].attrType = -1; attrList[acnt].attrLen = -1; attrList[acnt].attrValue = NULL; } if (status == RELNOTFOUND) { // Create the result relation attrInfo *createAttrInfo = new attrInfo[nattrs]; for (i = 0; i < nattrs; i++) { AttrDesc attrDesc; strcpy(createAttrInfo[i].relName, resultName.c_str()); strcpy(createAttrInfo[i].attrName, attrList[i].attrName); status = attrCat->getInfo(attrList[i].relName, attrList[i].attrName, attrDesc); if (status != OK) { error.print(status); return; } createAttrInfo[i].attrType = attrDesc.attrType; createAttrInfo[i].attrLen = attrDesc.attrLen; } status = relCat->createRel(resultName, nattrs, createAttrInfo); delete []createAttrInfo; if (status != OK) { error.print(status); return; } } else { // Check to see that the attribute types match if (nattrs != attrCnt) { error.print(ATTRTYPEMISMATCH); return; } for (i = 0; i < nattrs; i++) { AttrDesc attrDesc; status = attrCat->getInfo(attrList[i].relName, attrList[i].attrName, attrDesc); if (status != OK) { error.print(status); return; } if (attrDesc.attrType != attrs[i].attrType || attrDesc.attrLen != attrs[i].attrLen) { error.print(ATTRTYPEMISMATCH); return; } } free(attrs); } // make the call to QU_Select errval = QU_Select(resultName, nattrs, attrList, NULL, (Operator)0, NULL); if (errval != OK) error.print((Status)errval); } // if qual is `attr op value' then this is a regular select else if (temp->kind == N_SELECT) { temp1 = temp->u.SELECT.selattr; // make a list of attribute names suitable for passing to select nattrs = mk_attrnames(n->u.QUERY.attrlist, names, temp1->u.QUALATTR.relname); if (nattrs < 0) { print_error("select", nattrs); break; } for(int acnt = 0; acnt < nattrs; acnt++) { strcpy(attrList[acnt].relName, names[nattrs]); strcpy(attrList[acnt].attrName, names[acnt]); attrList[acnt].attrType = -1; attrList[acnt].attrLen = -1; attrList[acnt].attrValue = NULL; } strcpy(attr1.relName, names[nattrs]); strcpy(attr1.attrName, temp1->u.QUALATTR.attrname); attr1.attrType = type_of(temp->u.SELECT.value); attr1.attrLen = -1; attr1.attrValue = (char *)value_of(temp->u.SELECT.value); if (status == RELNOTFOUND) { // Create the result relation attrInfo *createAttrInfo = new attrInfo[nattrs]; for (i = 0; i < nattrs; i++) { AttrDesc attrDesc; strcpy(createAttrInfo[i].relName, resultName.c_str()); strcpy(createAttrInfo[i].attrName, attrList[i].attrName); status = attrCat->getInfo(attrList[i].relName, attrList[i].attrName, attrDesc); if (status != OK) { error.print(status); return; } createAttrInfo[i].attrType = attrDesc.attrType; createAttrInfo[i].attrLen = attrDesc.attrLen; } status = relCat->createRel(resultName, nattrs, createAttrInfo); delete []createAttrInfo; if (status != OK) { error.print(status); return; } } else { // Check to see that the attribute types match if (nattrs != attrCnt) { error.print(ATTRTYPEMISMATCH); return; } for (i = 0; i < nattrs; i++) { AttrDesc attrDesc; status = attrCat->getInfo(attrList[i].relName, attrList[i].attrName, attrDesc); if (status != OK) { error.print(status); return; } if (attrDesc.attrType != attrs[i].attrType || attrDesc.attrLen != attrs[i].attrLen) { error.print(ATTRTYPEMISMATCH); return; } } free(attrs); } // make the call to QU_Select char * tmpValue = (char *)value_of(temp->u.SELECT.value); errval = QU_Select(resultName, nattrs, attrList, &attr1, (Operator)temp->u.SELECT.op, tmpValue); delete [] tmpValue; delete [] attr1.attrValue; if (errval != OK) error.print((Status)errval); } // if qual is `attr1 op attr2' then this is a join else { temp1 = temp->u.JOIN.joinattr1; temp2 = temp->u.JOIN.joinattr2; // make an attribute list suitable for passing to join nattrs = mk_qual_attrs(n->u.QUERY.attrlist, qual_attrs, temp1->u.QUALATTR.relname, temp2->u.QUALATTR.relname); if (nattrs < 0) { print_error("select", nattrs); break; } // set up the joined attributes to be passed to Join qual_attrs[nattrs].relName = temp1->u.QUALATTR.relname; qual_attrs[nattrs].attrName = temp1->u.QUALATTR.attrname; qual_attrs[nattrs + 1].relName = temp2->u.QUALATTR.relname; qual_attrs[nattrs + 1].attrName = temp2->u.QUALATTR.attrname; for(int acnt = 0; acnt < nattrs; acnt++) { strcpy(attrList[acnt].relName, qual_attrs[acnt].relName); strcpy(attrList[acnt].attrName, qual_attrs[acnt].attrName); attrList[acnt].attrType = -1; attrList[acnt].attrLen = -1; attrList[acnt].attrValue = NULL; } strcpy(attr1.relName, qual_attrs[nattrs].relName); strcpy(attr1.attrName, qual_attrs[nattrs].attrName); attr1.attrType = -1; attr1.attrLen = -1; attr1.attrValue = NULL; strcpy(attr2.relName, qual_attrs[nattrs+1].relName); strcpy(attr2.attrName, qual_attrs[nattrs+1].attrName); attr2.attrType = -1; attr2.attrLen = -1; attr2.attrValue = NULL; if (status == RELNOTFOUND) { // Create the result relation attrInfo *createAttrInfo = new attrInfo[nattrs]; for (i = 0; i < nattrs; i++) { AttrDesc attrDesc; strcpy(createAttrInfo[i].relName, resultName.c_str()); // Check if there is another attribute with same name for (j = 0; j < i; j++) if (!strcmp(createAttrInfo[j].attrName, attrList[i].attrName)) break; strcpy(createAttrInfo[i].attrName, attrList[i].attrName); if (j != i) sprintf(createAttrInfo[i].attrName, "%s_%d", createAttrInfo[i].attrName, counter++); status = attrCat->getInfo(attrList[i].relName, attrList[i].attrName, attrDesc); if (status != OK) { error.print(status); return; } createAttrInfo[i].attrType = attrDesc.attrType; createAttrInfo[i].attrLen = attrDesc.attrLen; } status = relCat->createRel(resultName, nattrs, createAttrInfo); delete []createAttrInfo; if (status != OK) { error.print(status); return; } } else { // Check to see that the attribute types match if (nattrs != attrCnt) { error.print(ATTRTYPEMISMATCH); return; } for (i = 0; i < nattrs; i++) { AttrDesc attrDesc; status = attrCat->getInfo(attrList[i].relName, attrList[i].attrName, attrDesc); if (status != OK) { error.print(status); return; } if (attrDesc.attrType != attrs[i].attrType || attrDesc.attrLen != attrs[i].attrLen) { error.print(ATTRTYPEMISMATCH); return; } } free(attrs); } // make the call to QU_Join errval = QU_Join(resultName, nattrs, attrList, &attr1, (Operator)temp->u.JOIN.op, &attr2); if (errval != OK) error.print((Status)errval); } if (resultName == string( "Tmp_Ubase_Result")) { // Print the contents of the result relation and destroy it status = UT_Print(resultName); if (status != OK) error.print(status); status = relCat->destroyRel(resultName); if (status != OK) error.print(status); } break; case N_INSERT: // make attribute and value list to be passed to QU_Insert nattrs = mk_ins_attrs(n->u.INSERT.attrlist, ins_attrs); if (nattrs < 0) { print_error("insert", nattrs); break; } // make the call to QU_Insert int acnt; for(acnt = 0; acnt < nattrs; acnt++) { strcpy(attrList[acnt].relName, n->u.INSERT.relname); strcpy(attrList[acnt].attrName, ins_attrs[acnt].attrName); attrList[acnt].attrType = (Datatype)ins_attrs[acnt].valType; attrList[acnt].attrLen = -1; attrList[acnt].attrValue = ins_attrs[acnt].value; } errval = QU_Insert(n->u.INSERT.relname, nattrs, attrList); for (acnt = 0; acnt < nattrs; acnt++) delete [] attrList[acnt].attrValue; if (errval != OK) error.print((Status)errval); break; case N_DELETE: // set up the name of deletion relation qual_attrs[0].relName = n->u.DELETE.relname; // if qualification given... if ((temp1 = n->u.DELETE.qual) != NULL) { // qualification must be a select, not a join if (temp1->kind != N_SELECT) { cerr << "Syntax Error" << endl; break; } temp2 = temp1->u.SELECT.selattr;/* // make sure attribute in qualification is from deletion rel if (strcmp(n->u.DELETE.relname, temp2->u.QUALATTR.relname)) { print_error("delete", E_INCOMPATIBLE); break; }*/ // set up qualification attrname = temp2->u.QUALATTR.attrname; op = temp1->u.SELECT.op; type = type_of(temp1->u.SELECT.value); len = length_of(temp1->u.SELECT.value); value = value_of(temp1->u.SELECT.value); } // otherwise, set up for no qualification else { attrname = NULL; op = (Operator)0; type = 0; len = 0; value = NULL; } // make the call to QU_Delete if (attrname) errval = QU_Delete(n -> u.DELETE.relname, attrname, (Operator)op, (Datatype)type, (char *)value); else errval = QU_Delete(n -> u.DELETE.relname, "", (Operator)op, (Datatype)type, (char *)value); delete [] value; if (errval != OK) error.print((Status)errval); break; case N_UPDATE: // set up the name of update relation qual_attrs[0].relName = n->u.UPDATE.relname; // if qualification given... if ((temp1 = n->u.UPDATE.qual) != NULL) { // qualification must be a select, not a join if (temp1->kind != N_SELECT) { cerr << "Syntax Error" << endl; break; } temp2 = temp1->u.SELECT.selattr; /* // make sure attribute in qualification is from update rel if (strcmp(n->u.UPDATE.relname, temp2->u.QUALATTR.relname)) { print_error("delete", E_INCOMPATIBLE); break; } */ // set up qualification attrname = temp2->u.QUALATTR.attrname; op = temp1->u.SELECT.op; type = type_of(temp1->u.SELECT.value); len = length_of(temp1->u.SELECT.value); value = value_of(temp1->u.SELECT.value); } // otherwise, set up for no qualification else { attrname = NULL; op = (Operator)0; type = 0; len = 0; value = NULL; } // make attribute and value list to be passed to QU_Update nattrs = mk_ins_attrs(n->u.UPDATE.attrlist, ins_attrs); if (nattrs < 0) { print_error("update", nattrs); break; } for(int acnt = 0; acnt < nattrs; acnt++) { strcpy(attrList[acnt].relName, n->u.UPDATE.relname); strcpy(attrList[acnt].attrName, ins_attrs[acnt].attrName); attrList[acnt].attrType = (Datatype)ins_attrs[acnt].valType; attrList[acnt].attrLen = -1; attrList[acnt].attrValue = ins_attrs[acnt].value; } // make the call to QU_Update if (attrname) errval = QU_Update(n -> u.UPDATE.relname, nattrs, attrList, attrname, (Operator)op, (Datatype)type, (char *)value); else errval = QU_Update(n -> u.UPDATE.relname, nattrs, attrList, "", (Operator)op, (Datatype)type, (char *)value); delete [] value; if (errval != OK) error.print((Status)errval); break; case N_CREATE: // make a list of ATTR_DESCRS suitable for sending to UT_Create nattrs = mk_attr_descrs(n->u.CREATE.attrlist, attr_descrs);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -