mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 16:34:07 +00:00
1 line
21 KiB
C
1 line
21 KiB
C
/* 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 "<rel-name>.<att-name>" */
|
||
|
||
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++;
|
||
|
||
}
|
||
|
||
|