Thread View: mod.amiga.sources
1 messages
1 total messages
Started by doc
Fri, 22 Aug 1986 22:46
sdb Database (3 of 3)
Author: doc
Date: Fri, 22 Aug 1986 22:46
Date: Fri, 22 Aug 1986 22:46
2005 lines
53789 bytes
53789 bytes
# This is a shell archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# err.c
# cre.c
# sel.c
# sdb.mem
# This archive created: Fri Aug 22 17:40:03 1986
# By: Craig Norborg (Purdue University Computing Center)
cat << \SHAR_EOF > err.c
/* SDB - error messages */
#include "sdbio.h"
char *db_ertxt(msg)
int msg;
{
char *txt;
/* select the appropriate message text */
switch (msg) {
case INSMEM:
txt = "insufficient memory";
break;
case RELFNF:
txt = "relation file not found";
break;
case BADHDR:
txt = "bad relation header";
break;
case TUPINP:
txt = "tuple input error";
break;
case TUPOUT:
txt = "tuple output error";
break;
case RELFUL:
txt = "relation file full";
break;
case RELCRE:
txt = "error creating relation file";
break;
case DUPATT:
txt = "duplicate attribute";
break;
case MAXATT:
txt = "too many attributes";
break;
case INSBLK:
txt = "insufficient disk space";
break;
case SYNTAX:
txt = "syntax error";
break;
case ATUNDF:
txt = "undefined attribute";
break;
case ATAMBG:
txt = "ambiguous attribute";
break;
case RLUNDF:
txt = "undefined relation";
break;
case CDSIZE:
txt = "boolean expression too complex";
break;
case INPFNF:
txt = "input file not found";
break;
case OUTCRE:
txt = "error creating output file";
break;
case INDFNF:
txt = "indirect command file not found";
break;
case BADSET:
txt = "bad set parameter";
break;
default:
txt = "undefined error";
break;
}
/* return the message text */
return (txt);
}
SHAR_EOF
cat << \SHAR_EOF > cre.c
/* SDB - relation creation routines */
#include "sdbio.h"
/* db_rcreate(rname) - begin the creation of a new relation */
struct relation *db_rcreate(rname)
char *rname;
{
struct relation *rptr;
/* allocate the relation structure */
if ((rptr = calloc(1,sizeof(struct relation))) == NULL)
return (db_nerror(INSMEM));
/* initialize the relation structure */
strncpy(rptr->rl_name,rname,RNSIZE);
rptr->rl_tcnt = 0;
rptr->rl_tmax = 0;
rptr->rl_data = 512;
rptr->rl_size = 1;
rptr->rl_header.hd_attrs[0].at_name[0] = 0;
/* return the new relation structure pointer */
return (rptr);
}
/* db_rcheader - create the relation header */
int db_rcheader(rptr)
struct relation *rptr;
{
char rname[RNSIZE+1],filename[RNSIZE+13];
/* initialize the relation file header */
db_cvbytes(rptr->rl_tcnt,rptr->rl_header.hd_tcnt);
db_cvbytes(rptr->rl_tmax,rptr->rl_header.hd_tmax);
db_cvbytes(rptr->rl_data,rptr->rl_header.hd_data);
db_cvbytes(rptr->rl_size,rptr->rl_header.hd_size);
/* create the relation file name */
strncpy(rname,rptr->rl_name,RNSIZE); rname[RNSIZE] = 0;
sprintf(filename,"%s.sdb",rname);
/* create the relation file */
if ((rptr->rl_fd = creat(filename,0)) == -1) {
free(rptr);
return (db_ferror(RELCRE));
}
/* write the header to the relation file */
if (write(rptr->rl_fd,&rptr->rl_header,512) != 512) {
close(rptr->rl_fd);
free(rptr);
return (db_ferror(BADHDR));
}
/* return successfully */
return (TRUE);
}
/* db_rctuples - create the relation tuples */
int db_rctuples(rptr,tcnt)
struct relation *rptr; unsigned int tcnt;
{
unsigned int i;
char *tbuf;
/* store the number of tuples */
rptr->rl_tmax = tcnt;
/* allocate a tuple buffer */
if ((tbuf = calloc(1,rptr->rl_size)) == NULL)
return (db_ferror(INSMEM));
/* write null tuples into the file */
for (i = 0; i < tcnt; i++)
if (write(rptr->rl_fd,tbuf,rptr->rl_size) != rptr->rl_size) {
free(tbuf);
return (db_ferror(INSBLK));
}
/* free the tuple buffer */
free(tbuf);
/* return successfully */
return (TRUE);
}
/* db_rcdone(rptr) - finish the creation of a new relation */
int db_rcdone(rptr)
struct relation *rptr;
{
/* initialize the relation file header */
db_cvbytes(rptr->rl_tcnt,rptr->rl_header.hd_tcnt);
db_cvbytes(rptr->rl_tmax,rptr->rl_header.hd_tmax);
/* write the header to the relation file */
lseek(rptr->rl_fd,0L,0);
if (write(rptr->rl_fd,&rptr->rl_header,512) != 512) {
close(rptr->rl_fd);
free(rptr);
return (db_ferror(BADHDR));
}
/* close the relation file */
close(rptr->rl_fd);
/* free the relation structure */
free(rptr);
/* return successfully */
return (TRUE);
}
/* db_rcattr(rptr,aname,type,size) - add an attribute to relation being created */
int db_rcattr(rptr,aname,type,size)
struct relation *rptr; char *aname; int type,size;
{
int i;
/* look for attribute name */
for (i = 0; i < NATTRS; i++)
if (rptr->rl_header.hd_attrs[i].at_name[0] == 0)
break;
else if (db_sncmp(aname,rptr->rl_header.hd_attrs[i].at_name,ANSIZE) == 0)
return (db_ferror(DUPATT));
/* check for too many attributes */
if (i == NATTRS)
return (db_ferror(MAXATT));
/* store the new attribute */
strncpy(rptr->rl_header.hd_attrs[i].at_name,aname,ANSIZE);
rptr->rl_header.hd_attrs[i].at_type = type;
rptr->rl_header.hd_attrs[i].at_size = size;
/* terminate the attribute table */
if (++i != NATTRS)
rptr->rl_header.hd_attrs[i].at_name[0] = 0;
/* update the tuple size */
rptr->rl_size += size;
/* return successfully */
return (TRUE);
}
SHAR_EOF
cat << \SHAR_EOF > sel.c
/* SDB - select data from the database */
#include "sdbio.h"
extern int dbv_token;
extern char dbv_tstring[];
extern int dbv_tvalue;
/* 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;
/* 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;
/* 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 */
static 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 */
static 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 */
static 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 */
static 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 */
static 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 */
static int find_attr(slptr,rname,aname,paptr,psrel,pattr)
struct sel *slptr; char *rname,*aname;
char **paptr; struct attribute **pattr;
{
/* 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 */
static 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 */
static int qattr(slptr,rname,aname,paptr,psrel,pattr)
struct sel *slptr; char *rname,*aname;
char **paptr; struct srel **psrel; struct attribute **pattr;
{
struct srel *srptr;
struct attribute *aptr;
char *crname;
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 */
static 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++;
}
SHAR_EOF
cat << \SHAR_EOF > sdb.mem
SDB - a Simple Database System
by David Betz
114 Davenport Ave.
Manchester, NH 03103
(603) 625-4691
Converted to the IBM/PC by
David N. Smith
44 Ole Musket Lane
Danbury, CT 06810
(203) 748-5934
1.0 INTRODUCTION
SDB is a simple database manager for small systems. It was
developed to provide a relatively low overhead system for
storing data on machines with limited disk and memory
resources. The current version runs on a PDT-11/150 with 2
RX01 floppy disk drives and 60K bytes of memory under the
RT-11 operating system. (it also runs on the VAX under VMS)
SDB was originally intended to be a relational database
system, so many of the terms used in describing it are taken
from the relational database literature. Within the context
of SDB the user can safely make the following associations:
1. RELATION can be taken to mean FILE
2. TUPLE can be taken to mean RECORD
3. ATTRIBUTE can be taken to mean FIELD
It should be noted that SDB is not a relationally complete
system. It provides the relational operations of SELECT,
PROJECT, and JOIN, but does not provide the set operations
of UNION, INTERSECTION, or DIFFERENCE as well as some
others.
2.0 RELATION FILE FORMATS
SDB maintains a separate file for each relation that the
user creates. This file contains a header block containing
the definition of the relation including the names and types
of all of the relation's attributes. The remainder of the
file contains fixed length records each containing one tuple
from the relation.
Tuples can be of three types:
1. active - tuples that contain actual active data
2. deleted - tuples that have been deleted
3. unused - tuples that haven't been used yet
SDB - a Simple Database System Page 2
Initially, all tuples are unused. When a new tuple is
stored into a relation, the first unused tuple is found
(they are all contiguous at the end of the relation file).
The new tuple is stored as an active tuple.
When a tuple is deleted, it is marked as such. The space
previously allocated to the deleted tuple is left unused
until the relation is compressed.
It is possible that when attempting to store a new tuple, no
unused tuple can be found even though the relation contains
fewer than the maximum active tuples. This happens when
tuples have been deleted since the time the relation file
was last compressed.
The compress function allows all of the space lost by
deleting tuples to be regained. It does this by copying all
of the active tuples as far backward in the file as possible
leaving all of the available space toward the end of the
file.
3.0 SELECTION EXPRESSIONS
A selection expression specifies a set of tuples over which
some SDB operation is to be executed. The syntax for a
selection expression is:
<rse> ::= <rnames> [ where <boolean> ]
<rnames> ::= <rname> [ , <rname> ] ...
<rname> ::= <relation-name> [ <alias> ]
When a single relation name is specified in a selection
expression, each tuple within that relation becomes a
candidate for selection.
When more than one relation name is specified, the tuples
are formed by taking the cross product of all specified
relations. If a relation is to be crossed with itself, an
alias must be given to one or both of the occurances of that
relation name in the selection expression. This allows SDB
to determine which relation occurance is being refered to in
the boolean part of the selection expression.
After the set of candidate tuples is determined, the boolean
expression is evaluated for each candidate. The candidates
for which the boolean expression evaluates to TRUE become
the selected tuples.
SDB - a Simple Database System Page 3
4.0 INITIALIZATION FILE AND COMMAND FILES
When SDB is first run, it attempts to read and process
commands from a file named "SDB.INI". This file usually
contains macro definitions, but can contain any valid SDB
command. In addition, it is possible to process command
files from within SDB. This is done by typing an '@'
followed by the command file name after the SDB prompt.
5.0 FILE NAMES
Whenever a file name is allowed in the syntax for a command,
it is possible to use either an identifier or a quoted
string. An identifier is interpreted as the file name and a
string is interpreted as a full file specification. The
string form allows for the specification of an alternate
device or extension.
6.0 FORM DEFINITION FILES
A form definition file contains a template into which
attribute values are substituted during a print operation.
There are two types of information that can be included in a
form definition:
1. Literal text
2. Attribute references
Attribute references are indicated by placing the name of
the attribute being referenced between a pair of angle
brackets. Literal text is anything that is not enclosed in
angle brackets.
SDB - a Simple Database System Page 4
Example:
________
print using test amount,category from checks;
Where test.frm contains:
Amount: <amount>
Category: <category>
(MPK) For ease in generating English text, a $ character may
be placed before the attribute name inside an attribute
reference, in which case no trailing blanks will appear in
the output for that reference. For example:
print using test number,category from checks;
Where test.frm contains:
Check #<$number> was spent on <$category
7.0 ALIASES FOR RELATIONS AND ATTRIBUTES
When a relation or attribute name is specified in a print
statement, it is possible to provide an alternate name for
that relation or attribute. This is useful for relations,
when it is necessary to join a relation to itself. It is
useful for attributes when it is desired that the column
headers in a table be different from the actual attribute
names. Also, alternate attribute names can be used in
references to that attribute in the where clause as well as
in a form definition file. The syntax for specifying
aliases is:
<name> <alias>
Example:
________
print using test amount a,category c from checks;
Where test.frm contains:
Amount: <a>
Category: <c>
SDB - a Simple Database System Page 5
8.0 BOOLEAN EXPRESSIONS
The syntax for boolean expressions:
<expr> ::= <land> [ '|' <land> ]
<land> ::= <relat> [ '&' <relat> ]
<relat> ::= <primary> [ <relop> <primary> ]
<primary> ::= <term> [ <addop> <term> ]
<term> ::= <unary> [ <mulop> <unary> ]
<unary> ::= <factor> | <unop> <unary>
<factor> ::= <operand> | '(' <expr> ')'
<operand> ::= <number> | <string> | <attribute>
<attribute> ::= [ <rname> . ] <aname>
<relop> ::= '=' | '<>' | '<' | '>' | '<=' | '>='
<addop> ::= '+' | '-'
<mulop> ::= '*' | '/'
<unop> ::= '+' | '-' | '~'
Operators:
1. '=' - equal
2. '<>' - not equal
3. '<' - less than
4. '>' - greater than
5. '<=' - less than or equal
6. '>=' - greater than or equal
7. '+' - addition or unary plus (not implemented)
8. '-' - subraction or unary minus (not implemented)
9. '*' - multiplication (not implemented)
10. '/' - division (not implemented)
11. '&' - logical and
12. '|' - logical or
13. '~' - logical not
Operands:
1. number - a string of digits containing at most one
decimal point
2. string - a string of characters enclosed in double
quotes
SDB - a Simple Database System Page 6
3. attribute - an attribute name optionally qualified
by a relation name
SDB - a Simple Database System Page 7
9.0 INTERACTIVE COMMAND DESCRIPTIONS
Function:
_________
Create a relation file
Format:
_______
create <rname> ( <alist> ) <size>
Rules:
______
1. <rname> is the name of the relation file
2. <alist> is a list of attribute definitions of the
form:
<aname> { char | num } <size>
where:
1. <aname> is the name of the attribute
2. the type of the attribute is either "char" or
"num"
3. <size> is the number of bytes allocated to the
attribute value
3. <size> is the maximum number of tuples the file is
to hold
Example:
________
create checks (
number num 4
date char 8
payee char 20
amount num 8
category char 5
) 200
This command creates a relation file named "checks.sdb" with
attributes "number", "date", "payee", "amount", and
"category" and space to store 200 tuples.
SDB - a Simple Database System Page 8
Function:
_________
Insert tuples into a relation
Format:
_______
insert <rname>
Rules:
______
1. <rname> is the name of a relation
2. the user will be prompted for the values of the
attributes for the tuple to be inserted
3. a null response to an attribute prompt will
terminate tuple entry
4. if a null value is desired, a single space can be
entered
SDB - a Simple Database System Page 9
Function:
_________
Delete tuples from a set of relations
Format:
_______
delete <rse> ;
Rules:
______
1. <rse> is a tuple selection expression
2. selected tuples are deleted
Example:
________
delete checks where category = "junk";
SDB - a Simple Database System Page 10
Function:
_________
Update the values of selected attributes in selected tuples
Format:
_______
update { <attrs> | * } from <rse> ;
Rules:
______
1. <attrs> is a list of attribute names to be updated
2. * means all attributes
3. <rse> is a tuple selection expression
4. for each set of selected tuples, the user is
prompted for new values for the selected attributes
5. a null response to an attribute prompt will retain
the previous attribute value
6. if a null value is desired, a single space can be
entered
Example:
________
update amount,category from checks where number > 10;
SDB - a Simple Database System Page 11
Function:
_________
Print a table of values of selected attributes
Format:
_______
print [ using <fname> ] { <attrs> | * } from <rse> [ into
<fname> ] ;
Rules:
______
1. using <fname> indicates output using a form
definition file (.FRM)
2. <attrs> is a list of attribute names to be printed
3. * means all attributes
4. <rse> is a tuple selection expression
5. <fname> is the name of an file to which the table
will be output (.TXT)
6. if the output file name is omitted, output is to
the terminal
7. for each set of selected tuples, a table entry is
printed containing the selected attributes
Example:
________
print payee,amount from checks where category = "junk";
SDB - a Simple Database System Page 12
Function:
_________
Import tuples from a file into a relation
Format:
_______
import <fname> into <rname>
Rules:
______
1. <fname> is the name of the input file (.DAT)
2. the input file contains the values of the tuple
attributes with each on a separate line
3. <rname> is the name of a relation
4. tuples are appended to the named relation
SDB - a Simple Database System Page 13
Function:
_________
Export tuples from a relation into a file
Format:
_______
export <rname> [ into <fname> ] ;
Rules:
______
1. <rname> is the name of a relation
2. <fname> is the name of the output file (.DAT)
3. if the output file name is omitted, output is to
the terminal
4. tuples are written to the output file with one
attribute value per line
SDB - a Simple Database System Page 14
Function:
_________
Extract the definition of a relation into a file
Format:
_______
extract <rname> [ into <fname> ] ;
Rules:
______
1. <rname> is the name of a relation
2. <fname> is the name of the output file (.DEF)
3. if the output file name is omitted, output is to
the terminal
4. the definition of the relation is written to the
output file
SDB - a Simple Database System Page 15
Function:
_________
Compress a relation file
Format:
_______
compress <rname>
Rules:
______
1. <rname> is the name of a relation file
2. tuples are copied toward the front of the relation
file such that any space freed by previously
deleted tuples becomes adjacent to the free space
at the end of the file, thus becoming available for
use in inserting new tuples
SDB - a Simple Database System Page 16
Function:
_________
Sort a relation file
Format:
_______
sort <rname> by <sname> { , <sname } ... ;
Rules:
______
1. <rname> is the name of a relation file
2. <sname> is the name of an attribute to sort on
followed optionally by "ascending" or "descending"
3. if a sort order is not specified, ascending is
assumed
4. tuples within the relation are sorted in place
using the attributes indicated
SDB - a Simple Database System Page 17
Function:
_________
Define a macro
Format:
_______
define <mname>
Rules:
______
1. <mname> is the name of the macro being defined
2. if a macro with the specified name already exists,
it is replaced
3. after entering the define command, definition mode
is entered
4. definition mode is indicated by the prompt
"SDB-DEF>"
5. all lines typed in definition mode are added to the
macro definition
6. a blank line terminates definition mode
7. a macro can be deleted by entering a blank line as
the only line in the definition
8. after a macro is defined, every occurance of the
macro name is replaced by the macro definition
SDB - a Simple Database System Page 18
Function:
_________
Show a macro definition
Format:
_______
show <mname>
Rules:
______
1. <mname> is the name of a macro whose definition is
to be shown
SDB - a Simple Database System Page 19
Function:
_________
Print a short help message
Format:
_______
help
Rules:
______
1. (none)
SDB - a Simple Database System Page 20
Function:
_________
Exit from SDB
Format:
_______
exit
Rules:
______
1. (none)
SDB - a Simple Database System Page 21
10.0 PROGRAM INTERFACE
SDB provides a callable program interface to allow programs
written in DECUS-C to access relation files. In order to
use the call interface, the users program should be linked
with the SDBUSR.OBJ object library. Also, additional stack
space should be allocated at link time using the /BOTTOM
qualifier on the link command. /BOTTOM:3000 seems to work
well, but it is probably possible to get away with less.
Example:
________
#include <stdio.h>
#include "sdb.h"
main()
{
DB_SEL *sptr;
char payee[100],amount[100];
/* setup retrieval */
if ((sptr = db_retrieve("checks where amount > 25.00")) == NULL) {
printf("*** error: %s ***\n",db_ertxt(dbv_errcode));
exit();
}
/* bind user variables to attributes */
db_bind(sptr,"checks","payee",payee);
db_bind(sptr,"checks","amount",amount);
/* loop through selection */
while (db_fetch(sptr))
printf("%s\t%s\n",payee,amount);
/* finish selection */
db_done(sptr);
}
SDB - a Simple Database System Page 22
Function:
_________
Setup a tuple retrieval context
Format:
_______
dbptr = db_retrieve(sexpr [ ,arg ]...)
Rules:
______
1. sexpr is a pointer to a string containing an rse
2. arg is a "printf" argument
3. dbptr is a database context pointer
4. db_retrieve returns NULL on errors
5. on errors, the error code is in dbv_errcode
SDB - a Simple Database System Page 23
Function:
_________
Fetch the next set of tuples from a retrieval context
Format:
_______
db_fetch(dbptr)
Rules:
______
1. dbptr is a database context pointer
2. updates the values of all bound user variables
3. db_fetch returns FALSE if no more tuples match or
if an error occurs
4. on errors, the error code is in dbv_errcode
SDB - a Simple Database System Page 24
Function:
_________
Update the current tuple within a retrieval context
Format:
_______
db_update(dbptr)
Rules:
______
1. dbptr is a database context pointer
2. db_update returns FALSE if an error occurs
3. on errors, the error code is in dbv_errcode
SDB - a Simple Database System Page 25
Function:
_________
Store a new tuple within a retrieval context
Format:
_______
db_store(dbptr)
Rules:
______
1. dbptr is a database context pointer
2. db_store returns FALSE if an error occurs
3. on errors, the error code is in dbv_errcode
SDB - a Simple Database System Page 26
Function:
_________
Bind a user variable to the value of a tuple attribute
within a retrieval context
Format:
_______
db_bind(dbptr,rname,aname,value)
Rules:
______
1. dbptr is a database context pointer
2. rname is a pointer to the relation name
3. aname is a pointer to the attribute name
4. value is a pointer to a character array to receive
the attribute value
5. db_bind returns FALSE if an error occurs
6. on errors, the error code is in dbv_errcode
SDB - a Simple Database System Page 27
Function:
_________
Get the value of a tuple attribute within a retrieval
context
Format:
_______
db_get(dbptr,rname,aname,value)
Rules:
______
1. dbptr is a database context pointer
2. rname is a pointer to the relation name
3. aname is a pointer to the attribute name
4. value is a pointer to a character array to receive
the attribute value
5. db_get returns FALSE if an error occurs
6. on errors, the error code is in dbv_errcode
SDB - a Simple Database System Page 28
Function:
_________
Put the value of a tuple attribute within a retrieval
context
Format:
_______
db_put(dbptr,rname,aname,value)
Rules:
______
1. dbptr is a database context pointer
2. rname is a pointer to the relation name
3. aname is a pointer to the attribute name
4. value is a pointer to the new value
5. db_put returns FALSE if an error occurs
6. on errors, the error code is in dbv_errcode
SDB - a Simple Database System Page 29
Function:
_________
Discontinue usage of a retrieval context
Format:
_______
db_done(dbptr)
Rules:
______
1. dbptr is a database context pointer
SDB - a Simple Database System Page 30
Function:
_________
Translate an error code to an error message text
Format:
_______
db_ertxt(errcode)
Rules:
______
1. errcode is an SDB error code
SHAR_EOF
# End of shell archive
exit 0
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads