/* SDB - select data from the database */ /* -*-c,save-*- */ #include "sdbio.h" /* #define DEBUG 1 /* debug hackery */ #ifdef DEBUG #define LOCAL #else #define LOCAL static #endif extern int dbv_token; extern char dbv_tstring[]; extern int dbv_tvalue; #ifdef CPM68K struct scan *db_ropen(); #endif /* db_select - select a set of tuples from a set of relations */ struct sel *db_select(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9) char *fmt; { struct sel *slptr; struct sel *db_nerror(); /* check for a command line */ if (fmt != NULL) db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9); /* allocate a sel structure */ if ((slptr = malloc(sizeof(struct sel))) == NULL) return (db_nerror(INSMEM)); /* initialize the structure */ slptr->sl_rels = NULL; slptr->sl_attrs = NULL; slptr->sl_where = NULL; slptr->sl_bindings = NULL; /* parse the list of selected attributes */ if (!get_sattrs(slptr)) { db_done(slptr); return (NULL); } /* check for "from" clause */ if (db_token() == FROM) { db_ntoken(); if (!get_srels(slptr)) { db_done(slptr); return (NULL); } } else { if (!srelation(slptr,"sdbcur",NULL)) { db_done(slptr); return (NULL); } } /* check the list of selected attributes */ if (!check_attrs(slptr)) { db_done(slptr); return (NULL); } /* check for the existance of a "where" clause */ if (db_token() == WHERE) { db_ntoken(); /* parse the boolean expression */ if (!db_compile(slptr)) { db_done(slptr); return (FALSE); } } /* return the new selection structure */ return (slptr); } /* db_retrieve - retrieve a set of tuples from a set of relations */ struct sel *db_retrieve(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9) char *fmt; { struct sel *slptr; struct sel *db_nerror(); /* check for a command line */ if (fmt != NULL) db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9); /* allocate a sel structure */ if ((slptr = malloc(sizeof(struct sel))) == NULL) return (db_nerror(INSMEM)); /* initialize the structure */ slptr->sl_rels = NULL; slptr->sl_attrs = NULL; slptr->sl_where = NULL; slptr->sl_bindings = NULL; /* check for selected relations clause */ if (db_token() == ID) { if (!get_srels(slptr)) { db_done(slptr); return (NULL); } } else { if (!srelation(slptr,"sdbcur",NULL)) { db_done(slptr); return (NULL); } } /* check the list of selected attributes */ if (!check_attrs(slptr)) { db_done(slptr); return (NULL); } /* check for the existance of a "where" clause */ if (db_token() == WHERE) { db_ntoken(); /* parse the boolean expression */ if (!db_compile(slptr)) { db_done(slptr); return (FALSE); } } /* return the new selection structure */ return (slptr); } /* db_done(slptr) - finish a selection */ db_done(slptr) struct sel *slptr; { struct sattr *saptr,*nxtsa; struct srel *srptr,*nxtsr; struct binding *bdptr,*nxtbd; /* free the selected attribute blocks */ for (saptr = slptr->sl_attrs; saptr != NULL; saptr = nxtsa) { nxtsa = saptr->sa_next; if (saptr->sa_rname != NULL) free(saptr->sa_rname); free(saptr->sa_aname); if (saptr->sa_name != NULL) free(saptr->sa_name); free(saptr); } /* close the scans and free the selected relation blocks */ for (srptr = slptr->sl_rels; srptr != NULL; srptr = nxtsr) { nxtsr = srptr->sr_next; if (srptr->sr_name != NULL) free(srptr->sr_name); db_rclose(srptr->sr_scan); free(srptr); } /* free the where clause */ db_fcode(slptr); /* free the user bindings */ for (bdptr = slptr->sl_bindings; bdptr != NULL; bdptr = nxtbd) { nxtbd = bdptr->bd_next; free(bdptr); } /* free the selection structure */ free(slptr); } /* db_fetch(slptr) - fetch the next tuple from a selection */ int db_fetch(slptr) struct sel *slptr; { struct srel *srptr; struct binding *bdptr; /* clear the update flags */ for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) srptr->sr_update = FALSE; /* find a matching tuple */ while (process(slptr->sl_rels)) if (db_interpret(slptr)) { for (bdptr = slptr->sl_bindings; bdptr != NULL; bdptr = bdptr->bd_next) db_aget(bdptr->bd_attr,bdptr->bd_vtuple,bdptr->bd_vuser); return (TRUE); } /* no matches, failure return */ return (FALSE); } /* db_update - update modified tuples */ int db_update(slptr) struct sel *slptr; { struct srel *srptr; /* check each selected relation for updates */ for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) if (srptr->sr_update) if (!db_rupdate(srptr->sr_scan)) return (FALSE); /* return successfully */ return (TRUE); } /* db_store - store tuples */ int db_store(slptr) struct sel *slptr; { struct srel *srptr; /* check each selected relation for stores */ for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) if (srptr->sr_update) if (!db_rstore(srptr->sr_scan)) return (FALSE); /* return successfully */ return (TRUE); } /* db_bind - bind a user buffer to the value of an attribute */ int db_bind(slptr,rname,aname,avalue) struct sel *slptr; char *rname,*aname,*avalue; { struct binding *newbd; struct srel *srptr; /* allocate and initialize a binding structure */ if ((newbd = malloc(sizeof(struct binding))) == NULL) return (db_ferror(INSMEM)); newbd->bd_vuser = avalue; /* find the attribute */ if (!find_attr(slptr,rname,aname,&newbd->bd_vtuple,&srptr,&newbd->bd_attr)) return (FALSE); /* link the new binding into the binding list */ newbd->bd_next = slptr->sl_bindings; slptr->sl_bindings = newbd; /* return successfully */ return (TRUE); } /* db_get - get the value of an attribute */ int db_get(slptr,rname,aname,avalue) struct sel *slptr; char *rname,*aname,*avalue; { struct srel *srptr; struct attribute *aptr; char *vptr; /* find the attribute */ if (!find_attr(slptr,rname,aname,&vptr,&srptr,&aptr)) return (FALSE); /* get the attribute value */ db_aget(aptr,vptr,avalue); /* return successfully */ return (TRUE); } /* db_put - put the value of an attribute */ int db_put(slptr,rname,aname,avalue) struct sel *slptr; char *rname,*aname,*avalue; { struct srel *srptr; struct attribute *aptr; char *vptr; /* find the attribute */ if (!find_attr(slptr,rname,aname,&vptr,&srptr,&aptr)) return (FALSE); /* put the attribute value */ db_aput(aptr,vptr,avalue); /* mark the tuple as updated */ srptr->sr_update = TRUE; /* return successfully */ return (TRUE); } /* db_sattr - get selected attribute type, pointer, and length */ int db_sattr(slptr,rname,aname,ptype,pptr,plen) struct sel *slptr; char *rname,*aname; int *ptype; char **pptr; int *plen; { struct srel *srptr; struct attribute *aptr; if (!find_attr(slptr,rname,aname,pptr,&srptr,&aptr)) return (FALSE); *ptype = aptr->at_type; *plen = aptr->at_size; return (TRUE); } /* get_sattrs(slptr) - get selected attributes */ LOCAL get_sattrs(slptr) struct sel *slptr; { struct sattr *newsattr,*lastsattr; /* check for "*" or blank field meaning all attributes are selected */ if (db_token() == '*') { db_ntoken(); return (TRUE); } else if (db_token() != ID) return (TRUE); /* parse a list of attribute names */ lastsattr = NULL; while (TRUE) { /* get attribute name */ if (db_ntoken() != ID) return (db_ferror(SYNTAX)); /* allocate a selected attribute structure */ if ((newsattr = malloc(sizeof(struct sattr))) == NULL) return (db_ferror(INSMEM)); /* initialize the selected attribute structure */ newsattr->sa_next = NULL; /* save the attribute name */ if ((newsattr->sa_aname = malloc(strlen(dbv_tstring)+1)) == NULL) { free(newsattr); return (db_ferror(INSMEM)); } strcpy(newsattr->sa_aname,dbv_tstring); /* check for "." meaning "." */ if (db_token() == '.') { db_ntoken(); /* the previous ID was really the relation name */ newsattr->sa_rname = newsattr->sa_aname; /* check for attribute name */ if (db_ntoken() != ID) { free(newsattr->sa_aname); free(newsattr); return (db_ferror(SYNTAX)); } /* save the attribute name */ if ((newsattr->sa_aname = malloc(strlen(dbv_tstring)+1)) == NULL) { free(newsattr->sa_aname); free(newsattr); return (db_ferror(INSMEM)); } strcpy(newsattr->sa_aname,dbv_tstring); } else newsattr->sa_rname = NULL; /* check for alternate attribute name */ if (db_token() == ID) { db_ntoken(); /* allocate space for the alternate name */ if ((newsattr->sa_name = malloc(strlen(dbv_tstring)+1)) == NULL) { if (newsattr->sa_rname != NULL) free(newsattr->sa_rname); free(newsattr->sa_aname); free(newsattr); return (db_ferror(INSMEM)); } strcpy(newsattr->sa_name,dbv_tstring); } else newsattr->sa_name = NULL; /* link the selected attribute structure into the list */ if (lastsattr == NULL) slptr->sl_attrs = newsattr; else lastsattr->sa_next = newsattr; lastsattr = newsattr; /* check for more attributes */ if (db_token() != ',') break; db_ntoken(); } /* return successfully */ return (TRUE); } /* get_srels(slptr) - get selected relations */ LOCAL get_srels(slptr) struct sel *slptr; { char rname[KEYWORDMAX+1],*aname; /* get the list of selected relations */ while (TRUE) { /* check for relation name */ if (db_ntoken() != ID) return (db_ferror(SYNTAX)); strcpy(rname,dbv_tstring); /* check for alternate relation name */ if (db_token() == ID) { db_ntoken(); aname = dbv_tstring; } else aname = NULL; /* add the relation name to the list */ if (!srelation(slptr,rname,aname)) return (FALSE); /* check for more selected relations */ if (db_token() != ',') break; db_ntoken(); } /* return successfully */ return (TRUE); } /* srelation - select a relation */ LOCAL srelation(slptr,rname,aname) struct sel *slptr; char *rname,*aname; { struct srel *srptr,*newsrel; /* allocate a new selected relation structure */ if ((newsrel = malloc(sizeof(struct srel))) == NULL) return (db_ferror(INSMEM)); /* initialize the new selected relation structure */ newsrel->sr_ctuple = FALSE; newsrel->sr_update = FALSE; newsrel->sr_next = NULL; /* open the relation */ if ((newsrel->sr_scan = db_ropen(rname)) == NULL) { free(newsrel); return (FALSE); } /* check for alternate relation name */ if (aname != NULL) { /* allocate space for the alternate name */ if ((newsrel->sr_name = malloc(strlen(aname)+1)) == NULL) { free(newsrel); return (db_ferror(INSMEM)); } strcpy(newsrel->sr_name,aname); } else newsrel->sr_name = NULL; /* find the end of the list of relation names */ for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) if (srptr->sr_next == NULL) break; /* link the new selected relation structure into the list */ if (srptr == NULL) slptr->sl_rels = newsrel; else srptr->sr_next = newsrel; /* return successfully */ return (TRUE); } /* check_attrs(slptr) - check the list of selected attributes */ LOCAL int check_attrs(slptr) struct sel *slptr; { struct sattr *saptr; /* check for all attributes selected */ if (slptr->sl_attrs == NULL) return (all_attrs(slptr)); /* check each selected attribute */ for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) if (!find_attr(slptr,saptr->sa_rname,saptr->sa_aname, &saptr->sa_aptr,&saptr->sa_srel,&saptr->sa_attr)) return (FALSE); /* return successfully */ return (TRUE); } /* all_attrs(slptr) - create a list of all attributes */ LOCAL int all_attrs(slptr) struct sel *slptr; { struct sattr *newsattr,*lastsattr; struct srel *srptr; struct attribute *aptr; int i,astart; /* loop through each selected relation */ lastsattr = NULL; for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) { /* loop through each attribute within the relation */ astart = 1; for (i = 0; i < NATTRS; i++) { /* get a pointer to the current attribute */ aptr = &srptr->sr_scan->sc_relation->rl_header.hd_attrs[i]; /* check for last attribute */ if (aptr->at_name[0] == 0) break; /* allocate a new selected attribute structure */ if ((newsattr = malloc(sizeof(struct sattr))) == NULL) return (db_ferror(INSMEM)); /* initialize the new selected attribute structure */ newsattr->sa_name = NULL; newsattr->sa_srel = srptr; newsattr->sa_aptr = srptr->sr_scan->sc_tuple + astart; newsattr->sa_attr = aptr; newsattr->sa_next = NULL; /* save the relation name */ if ((newsattr->sa_rname = malloc(RNSIZE+1)) == NULL) { free(newsattr); return (db_ferror(INSMEM)); } strncpy(newsattr->sa_rname, srptr->sr_scan->sc_relation->rl_name, RNSIZE); newsattr->sa_rname[RNSIZE] = 0; /* save the attribute name */ if ((newsattr->sa_aname = malloc(ANSIZE+1)) == NULL) { free(newsattr->sa_rname); free(newsattr); return (db_ferror(INSMEM)); } strncpy(newsattr->sa_aname, srptr->sr_scan->sc_relation->rl_header.hd_attrs[i].at_name, ANSIZE); newsattr->sa_aname[ANSIZE] = 0; /* link the selected attribute into the list */ if (lastsattr == NULL) slptr->sl_attrs = newsattr; else lastsattr->sa_next = newsattr; lastsattr = newsattr; /* update the attribute start */ astart += aptr->at_size; } } /* return successfully */ return (TRUE); } /* find_attr - find a named attribute */ LOCAL int find_attr(slptr,rname,aname,paptr,psrel,pattr) struct sel *slptr; char *rname,*aname; char **paptr; struct attribute **pattr; struct srel **psrel; { #ifdef DEBUG printf("*** find_attr(): rname = %s, aname = %s\n", rname, aname); #endif /* check for unqualified or qualified attribute names */ if (rname == NULL) return (uattr(slptr,aname,paptr,psrel,pattr)); else return (qattr(slptr,rname,aname,paptr,psrel,pattr)); } /* uattr - find an unqualified attribute name */ LOCAL int uattr(slptr,aname,paptr,psrel,pattr) struct sel *slptr; char *aname; char **paptr; struct srel **psrel; struct attribute **pattr; { struct srel *srptr; struct attribute *aptr; int i,astart; /* loop through each selected relation */ *pattr = NULL; for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) { /* loop through each attribute within the relation */ astart = 1; for (i = 0; i < NATTRS; i++) { /* get a pointer to the current attribute */ aptr = &srptr->sr_scan->sc_relation->rl_header.hd_attrs[i]; /* check for last attribute */ if (aptr->at_name[0] == 0) break; /* check for attribute name match */ if (db_sncmp(aname,aptr->at_name,ANSIZE) == 0) { if (*pattr != NULL) return (db_ferror(ATAMBG)); *paptr = srptr->sr_scan->sc_tuple + astart; *psrel = srptr; *pattr = aptr; } /* update the attribute start */ astart += aptr->at_size; } } /* check whether attribute was found */ if (*pattr == NULL) return (db_ferror(ATUNDF)); /* return successfully */ return (TRUE); } /* qattr - find a qualified attribute name */ LOCAL int qattr(slptr,rname,aname,paptr,psrel,pattr) struct sel *slptr; char *rname,*aname; char **paptr; struct srel **psrel; struct attribute **pattr; { register struct srel *srptr; register struct attribute *aptr; register char *crname; register int i,astart; /* loop through each selected relation */ for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) { /* get relation name */ if ((crname = srptr->sr_name) == NULL) crname = srptr->sr_scan->sc_relation->rl_name; /* check for relation name match */ if (db_sncmp(rname,crname,RNSIZE) == 0) { /* loop through each attribute within the relation */ astart = 1; for (i = 0; i < NATTRS; i++) { /* get a pointer to the current attribute */ aptr = &srptr->sr_scan->sc_relation->rl_header.hd_attrs[i]; /* check for last attribute */ if (aptr->at_name[0] == 0) break; /* check for attribute name match */ if (db_sncmp(aname,aptr->at_name,ANSIZE) == 0) { *paptr = srptr->sr_scan->sc_tuple + astart; *psrel = srptr; *pattr = aptr; return (TRUE); } /* update the attribute start */ astart += aptr->at_size; } /* attribute name not found */ return (db_ferror(ATUNDF)); } } /* relation name not found */ return (db_ferror(RLUNDF)); } /* process(srptr) - process each tuple in a relation cross-product */ LOCAL int process(srptr) struct srel *srptr; { /* always get a new tuple if this is the last relation in the list */ if (srptr->sr_next == NULL) { /* check for beginning of new scan */ if (!srptr->sr_ctuple) db_rbegin(srptr->sr_scan); /* return the next tuple in the relation */ return (srptr->sr_ctuple = db_rfetch(srptr->sr_scan)); } /* check for beginning of new scan */ if (!srptr->sr_ctuple) { db_rbegin(srptr->sr_scan); /* get the first tuple */ if (!db_rfetch(srptr->sr_scan)) return (FALSE); } /* look for a match with the remaining relations in list */ while (!process(srptr->sr_next)) /* get the next tuple in the scan */ if (!db_rfetch(srptr->sr_scan)) return (srptr->sr_ctuple = FALSE); /* found a match at this level */ return (srptr->sr_ctuple = TRUE); } /* db_aget - get the value of an attribute */ db_aget(aptr,vptr,avalue) struct attribute *aptr; char *vptr,*avalue; { int i; /* get the attribute value */ for (i = 0; i < aptr->at_size; i++) *avalue++ = vptr[i]; *avalue = EOS; } /* db_aput - put the value of an attribute */ db_aput(aptr,vptr,avalue) struct attribute *aptr; char *vptr,*avalue; { int i; /* initialize counter */ i = 0; /* right justify numbers */ if (aptr->at_type == TNUM) for (; i < aptr->at_size - strlen(avalue); i++) vptr[i] = ' '; /* put the attribute value */ for (; i < aptr->at_size; i++) if (*avalue == 0) vptr[i] = 0; else vptr[i] = *avalue++; }