📄 interp.c
字号:
if (nattrs < 0) { print_error("create", nattrs); break; } // get info about primary attribute, if there is one if ((temp = n->u.CREATE.primattr) == NULL) { attrname = NULL; nbuckets = 1; } else { attrname = temp->u.PRIMATTR.attrname; nbuckets = temp->u.PRIMATTR.nbuckets; } for(acnt = 0; acnt < nattrs; acnt++) { strcpy(attrList[acnt].relName, n -> u.CREATE.relname); strcpy(attrList[acnt].attrName, attr_descrs[acnt].attrName); attrList[acnt].attrType = attr_descrs[acnt].attrType; attrList[acnt].attrLen = attr_descrs[acnt].attrLen; attrList[acnt].attrValue = NULL; } // make the call to UT_Create errval = relCat->createRel(n -> u.CREATE.relname, nattrs, attrList); if (errval != OK) error.print((Status)errval); break; case N_DESTROY: errval = relCat->destroyRel(n -> u.DESTROY.relname); if (errval != OK) error.print((Status)errval); break; case N_LOAD: errval = UT_Load(n -> u.LOAD.relname, n -> u.LOAD.filename); if (errval != OK) error.print((Status)errval); break; case N_PRINT: errval = UT_Print(n -> u.PRINT.relname); if (errval != OK) error.print((Status)errval); break; case N_HELP: if (n -> u.HELP.relname) errval = relCat->help(n -> u.HELP.relname); else errval = relCat->help(""); if (errval != OK) error.print((Status)errval); break; default: // so that compiler won't complain assert(0); }}//// mk_attrnames: converts a list of qualified attributes (<relation,// attribute> pairs) into an array of char pointers so it can be// sent to the appropriate UT or QU function.//// All of the attributes should come from relation relname. If relname// is NULL, then it checks that all attributes come from the same// relation.//// The first element of the array after the last attribute name is// set to the name of the relation.// // Returns:// the length of the list on success ( >= 0 )// error code otherwise ( < 0 )//// (Thus, the return code is both the number of attributes in the array,// and the index of the relatin name in the array).//static int mk_attrnames(NODE *list, char *attrnames[], char *relname){ int i; NODE *temp; // for each qualified attribute in the list... for(i = 0; list != NULL && i < MAXATTRS; ++i, list = list->u.LIST.next) { temp = list->u.LIST.self; // if relname is NULL, then remember this relname if (relname == NULL) relname = temp->u.QUALATTR.relname; // otherwise, see if the relname matches the remembered relname else if (strcmp(relname, temp->u.QUALATTR.relname)) return E_INCOMPATIBLE; // add attribute name to the list attrnames[i] = list->u.LIST.self->u.QUALATTR.attrname; } // if the list is too long then error if (i == MAXATTRS) return E_TOOMANYATTRS; // put the relation name in the last position in the array attrnames[i] = relname; return i;}//// mk_qual_attrs: converts a list of qualified attributes (<relation,// attribute> pairs) into an array of REL_ATTRS so it can be sent to// QU_Join.//// All of the attributes must come from either relname1 or relname2.//// Returns:// the lengh of the list on success ( >= 0 )// error code otherwise//static int mk_qual_attrs(NODE *list, REL_ATTR qual_attrs[], char *relname1, char *relname2){ int i; NODE *attr; // for each element of the list... for(i = 0; list != NULL && i < MAXATTRS; ++i, list = list->u.LIST.next) { attr = list->u.LIST.self; // if relname != relname 1... if (strcmp(attr->u.QUALATTR.relname, relname1)) { // and relname != relname 2, then error if (strcmp(attr->u.QUALATTR.relname, relname2)) return E_INCOMPATIBLE; } // add it to the list qual_attrs[i].relName = attr->u.QUALATTR.relname; qual_attrs[i].attrName = attr->u.QUALATTR.attrname; } // If the list is too long then error if (i == MAXATTRS) return E_TOOMANYATTRS; return i;}//// mk_attr_descrs: converts a list of attribute descriptors (attribute names,// types, and lengths) to an array of ATTR_DESCR's so it can be sent to// UT_Create.//// Returns:// length of the list on success ( >= 0 )// error code otherwise//static int mk_attr_descrs(NODE *list, ATTR_DESCR attr_descrs[]){ int i; int type, len; NODE *attr; int errval; // for each element of the list... for(i = 0; list != NULL && i < MAXATTRS; ++i, list = list->u.LIST.next) { attr = list->u.LIST.self; // interpret the format string errval = parse_format_string(attr->u.ATTRTYPE.type, &type, &len); if (errval != E_OK) return errval; // add it to the list attr_descrs[i].attrName = attr->u.ATTRTYPE.attrname; attr_descrs[i].attrType = type; attr_descrs[i].attrLen = len; } // if the list is too long, then error if (i == MAXATTRS) return E_TOOMANYATTRS; return i;}//// mk_ins_attrs: converts a list of <attribute, value> pairs to an array// of ATTR_VAL's so it can be sent to QU_Insert.//// Returns:// length of the list on success ( >= 0 )// error code otherwise ( < 0 )//static int mk_ins_attrs(NODE *list, ATTR_VAL ins_attrs[]){ int i, type, len; NODE *attr; // add the attributes to the list for(i = 0; list != NULL && i < MAXATTRS; ++i, list = list->u.LIST.next) { attr = list->u.LIST.self; // make sure string attributes aren't too long type = type_of(attr->u.ATTRVAL.value); len = length_of(attr->u.ATTRVAL.value); if (type == STRING && len > MAXSTRINGLEN) return E_STRINGTOOLONG; ins_attrs[i].attrName = attr->u.ATTRVAL.attrname; ins_attrs[i].valType = type; ins_attrs[i].valLength = len; ins_attrs[i].value = value_of(attr->u.ATTRVAL.value); } // if list is too long then error if (i == MAXATTRS) return E_TOOMANYATTRS; return i;}/* Re write parse_format_string due to change of NODE.ATTRTYPE*/static int parse_format_string(int format, int *type, int *len){ if (format == ('i'-128)) { *type = INTEGER; *len = sizeof(int); return E_OK; } else if (format == ('f'-128)) { *type = FLOAT; *len = sizeof(float); return E_OK; } else if ((format<=255)&&(format>=1)) { *type = STRING; *len = format; return E_OK; } return E_INVFORMATSTRING;}/*//// parse_format_string: deciphers a format string of the form: x// where x is a type specification (one of `i' INTEGER, `f' FLOAT,// or `s' STRING, and stores the type in *type.//// Returns// E_OK on success// error code otherwise//static int parse_format_string(char *format_string, int *type, int *len){ int n; char c; // extract the components of the format string n = sscanf(format_string, "%c%d", &c, len); // if no length given... if (n == 1) { switch(c) { case INTCHAR: *type = INTEGER; *len = sizeof(int); break; case FLOATCHAR: *type = FLOAT; *len = sizeof(float); break; case STRCHAR: *type = STRING; *len = 1; break; default: return E_INVFORMATSTRING; } } // if both are given, make sure the length is valid else if (n == 2) { switch(c) { case INTCHAR: *type = INTEGER; if (*len != sizeof(int)) return E_INVINTSIZE; break; case FLOATCHAR: *type = FLOAT; if (*len != sizeof(float)) return E_INVFLOATSIZE; break; case STRCHAR: *type = STRING; break; default: return E_INVFORMATSTRING; } } // otherwise it's not a valid format string else return E_INVFORMATSTRING; return E_OK;}*///// type_of: returns the type of a value node//static int type_of(NODE *n){ return n->u.VALUE.type;}//// length_of: returns the length of the value in a value node//static int length_of(NODE *n){ return n->u.VALUE.len;}//// value_of: returns the value of a value node// The caller will get a fresh copy of the value, in string form.// We assume the caller will free() the memory pointed to by the// return value of this function.//static void *value_of(NODE *n){ char *newvalue; char value[255]; switch(type_of(n)) { case INTEGER: sprintf(value, "%d", n->u.VALUE.u.ival); break; case FLOAT: sprintf(value, "%f", n->u.VALUE.u.rval); break; case STRING: sprintf(value, "%s", n->u.VALUE.u.sval); } if (!(newvalue = new char [strlen(value)+1])) { fprintf(stderr, "could not allocate memory\n"); exit(1); } strcpy(newvalue, value); return (void *)newvalue;}//// print_error: prints an error message corresponding to errval//static void print_error(char *errmsg, int errval){ if (errmsg != NULL) fprintf(stderr, "%s: ", errmsg); switch(errval) { case E_OK: fprintf(ERRFP, "no error\n"); break; case E_INCOMPATIBLE: fprintf(ERRFP, "attributes must be from selected relation(s)\n"); break; case E_TOOMANYATTRS: fprintf(ERRFP, "too many attributes\n"); break; case E_NOLENGTH: fprintf(ERRFP, "length must be specified for STRING attribute\n"); break; case E_INVINTSIZE: fprintf(ERRFP, "invalid size for INTEGER attribute (should be %d)\n", (int) sizeof(int)); break; case E_INVFLOATSIZE: fprintf(ERRFP, "invalid size for FLOAT attribute (should be %d)\n", (int) sizeof(float)); break; case E_INVFORMATSTRING: fprintf(ERRFP, "invalid format string\n"); break; case E_INVSTRLEN: fprintf(ERRFP, "invalid length for string attribute\n"); break; case E_DUPLICATEATTR: fprintf(ERRFP, "duplicated attribute name\n"); break; case E_TOOLONG: fprintf(stderr, "relation name or attribute name too long\n"); break; case E_STRINGTOOLONG: fprintf(stderr, "string attribute too long\n"); break; default: fprintf(ERRFP, "unrecognized errval: %d\n", errval); }}//// quit procedure (makes sure that we exit, even it UT_Quit doesn't)//void quit(void){ UT_Quit(); // if UT_Quit didn't exit, then print a warning and quit fprintf(stderr, "*** ERROR: UT_quit failed to exit. ***\n"); exit(1);}static void echo_query(NODE *n){ switch(n->kind) { case N_QUERY: printf("select"); if (n->u.QUERY.relname != NULL) printf(" into %s", n->u.QUERY.relname); printf(" ("); print_attrnames(n->u.QUERY.attrlist); printf(")"); print_qual(n->u.QUERY.qual); printf(";\n"); break; case N_INSERT: printf("insert %s (", n->u.INSERT.relname); print_attrvals(n->u.INSERT.attrlist); printf(");\n"); break; case N_DELETE: printf("delete %s", n->u.DELETE.relname); print_qual(n->u.DELETE.qual); printf(";\n"); break; case N_UPDATE: printf("update %s", n->u.UPDATE.relname); print_attrvals(n->u.UPDATE.attrlist); print_qual(n->u.UPDATE.qual); printf(";\n"); break; case N_CREATE: printf("create %s (", n->u.CREATE.relname); print_attrdescrs(n->u.CREATE.attrlist); printf(")"); print_primattr(n->u.CREATE.primattr); printf(";\n"); break; case N_DESTROY: printf("destroy %s;\n", n->u.DESTROY.relname); break; case N_BUILD: printf("buildindex %s(%s);\n", n->u.BUILD.relname, n->u.BUILD.attrname);#if 0 printf("buildindex %s(%s) numbuckets = %d;\n", n->u.BUILD.relname, n->u.BUILD.attrname, n->u.BUILD.nbuckets);#endif break; case N_REBUILD: printf("rebuildindex %s(%s) numbuckets = %d;\n", n->u.BUILD.relname, n->u.BUILD.attrname, n->u.BUILD.nbuckets); break; case N_DROP: printf("dropindex %s", n->u.DROP.relname); if (n->u.DROP.attrname != NULL) printf("(%s)", n->u.DROP.attrname); printf(";\n"); break; case N_LOAD: printf("load %s(\"%s\");\n", n->u.LOAD.relname, n->u.LOAD.filename); break; case N_PRINT: printf("print %s;\n", n->u.PRINT.relname); break; case N_HELP: printf("help"); if (n->u.HELP.relname != NULL) printf(" %s", n->u.HELP.relname); printf(";\n"); break; default: // so that compiler won't complain assert(0); }}static void print_attrnames(NODE *n){ for(; n != NULL; n = n->u.LIST.next) { print_qualattr(n->u.LIST.self); if (n->u.LIST.next != NULL) printf(", "); }}static void print_attrvals(NODE *n){ NODE *attr; for(; n != NULL; n = n->u.LIST.next) { attr = n->u.LIST.self; printf("%s =", attr->u.ATTRVAL.attrname); print_val(attr->u.ATTRVAL.value); if (n->u.LIST.next != NULL) printf(", "); }}static void print_attrdescrs(NODE *n){ NODE *attr; for(; n != NULL; n = n->u.LIST.next) { attr = n->u.LIST.self; printf("%s = ", attr->u.ATTRTYPE.attrname); int format = attr->u.ATTRTYPE.type; if (format == ('i'-128)) { printf("int"); } else if (format == ('f'-128)) { printf("real"); } else if ((format<=255)&&(format>=1)) { printf("char(%d)", attr->u.ATTRTYPE.type); } if (n->u.LIST.next != NULL) printf(", "); }}static void print_primattr(NODE *n){ if (n == NULL) return; printf(" primary %s numbuckets = %d", n->u.PRIMATTR.attrname, n->u.PRIMATTR.nbuckets);}static void print_qual(NODE *n){ if (n == NULL) return; printf(" where "); if (n->kind == N_SELECT) { print_qualattr(n->u.SELECT.selattr); print_op(n->u.SELECT.op); print_val(n->u.SELECT.value); } else { print_qualattr(n->u.JOIN.joinattr1); print_op(n->u.JOIN.op); printf(" "); print_qualattr(n->u.JOIN.joinattr2); }}static void print_qualattr(NODE *n){ printf("%s.%s", n->u.QUALATTR.relname, n->u.QUALATTR.attrname);}static void print_op(int op){ switch(op) { case LT: printf(" <"); break; case LTE: printf(" <="); break; case EQ: printf(" ="); break; case GT: printf(" >"); break; case GTE: printf(" >="); break; case NE: printf(" <>"); break; }}static void print_val(NODE *n){ switch(n->u.VALUE.type) { case INTEGER: printf(" %d", n->u.VALUE.u.ival); break; case FLOAT: printf(" %f", n->u.VALUE.u.rval); break; case STRING: printf(" \"%s\"", n->u.VALUE.u.sval); break; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -