Next: References
Up: An ASCII Database
Previous: 10 Discussion
Qddb is available as a set of utility programs and a library of routines that
are useful for building other programs.
This code and documentation is available by anonymous ftp from
ftp.ms.uky.edu:pub/unix/qddb/.
A listing for the qs program is given in Figure 8 to
demonstrate how utility programs are easily built upon the library
routines.
void main(argc, argv)
int argc;
char *argv[];
{
Schema *schema;
char String[BUFSIZ];
char Relation[BUFSIZ], *rel;
KeyList *list = NULL;
size_t Length;
Qddb_SearchArg search_args;
Qddb_Init();
rel = Qddb_FindRelation(argv[1]);
strcpy(Relation, rel);
schema = Qddb_InitSchema(Relation);
while (fgets(String, sizeof(String), stdin) != NULL) {
char *ptr;
KeyList *LastList = NULL;
ptr = String;
while (*ptr != '\0') {
char *token;
token = ptr;
while (!isspace(*ptr) && *ptr != '\0')
ptr++;
if (*ptr != '\0') {
*ptr++ = '\0';
while (isspace(*ptr))
ptr++;
}
search_args.Alpha = token;
search_args.Type = ALPHA;
list = Qddb_Search(schema, &search_args, &Length, -1);
if (LastList != NULL)
list = LastList =
Qddb_KeyListOp(schema, list, LastList,
QDDB_KEYLIST_OP_INTERSECTION,
QDDB_KEYLIST_FLAG_DELDUP_SAMEENTRY);
else
LastList = list;
}
if ((argc == 3 && strcmp(argv[2],"-p") == 0) || (argc == 2))
PrintKeyList(schema, list, True);
else if (argc == 3 && strcmp(argv[2],"-n") == 0)
PrintKeyList(schema, list, False);
}
exit(0);
}
void PrintKeyList(schema, list, Print)
Schema *schema;
KeyList *list;
Boolean Print;
{
char *Buffer = Malloc(BUFSIZ), Valid;
int DBFile;
unsigned len = BUFSIZ;
DBFile = OpenDatabase(schema->RelationName, 0);
while (list != NULL) {
switch(QDDB_KEYLIST_TYPE(list)) {
case ORIGINAL:
if (list->Length > len) {
len = list->Length;
free(Buffer);
Buffer = Malloc(len);
}
lseek(DBFile, list->Start, 0);
Read(DBFile, Buffer, list->Length);
sscanf(Buffer, "%%0 %c", &Valid);
if (Valid == 'I')
break;
if (Print == True)
Write(1, Buffer, list->Length);
break;
case CHANGE:
if (Print == False)
break;
sprintf(Buffer, "cat %s/Changes/%d", schema->RelationName, (int)list->Number);
system(Buffer);
break;
case ADDITION:
if (Print == False)
break;
sprintf(Buffer, "cat %s/Additions/%d", schema->RelationName,
(int)list->Number);
system(Buffer);
break;
default:
PANIC("BAD TYPE IN KeyList");
}
if (Print == True)
write(1, "\n", 1);
list = list->next;
}
free(Buffer);
close(DBFile);
}
Figure 8: C Listing forqs
Some of the programs in the suite are:
- newdb - Create an empty relation and build a schema file.
- qadd - Add a tuple to the specified relation.
- qconv - Convert a relation in presentation format to
qddb internal format.
- qedit - Search a qddb database for a Boolean combination
of single-key queries and edit or list all entries found.
- qindex - Rebuild structure files, such as
HashTable, Index, KeyIndex, and
NumericIndex.
The current implementation requires that all
keys fit into memory. On small machines, such as a PC, this restriction is
unacceptable. We plan to build a second version of
qindex that uses temporary files instead of memory;
however, the stabilization process will be considerably slower.
We recommend that stabilization occur on large machines when they
are available. The relation files can then be transferred to a PC for
query sessions, since our format is machine-independent.
- qkeys - Rebuild Stable.keys.
- qs - Perform interactive queries; initializes by
reading HashTable.
- qstab - Merge all changes and additions into
Stable.
- qschemamod - Allows arbitrary update of
Schema.
- qsql - Interactively process QSQL queries and
updates.
The principal library routines are:
- void InitHash() -
Initialize the internal hash table.
- void MakeHash(char *RelationName) -
Read HashTable for the given relation.
- void ChangeEntry(char *RelationName, Entry TheEntry) -
Make a change
to a tuple by invalidating the old entry and adding the new one to the
appropriate location.
- void AddEntry(char *RelationName, Entry TheEntry) -
Add a new tuple to the relation.
- Schema *ReadRelationSchema(char *RelationName) -
Read the Schema file for the relation, parse it and return
an internally represented schema.
- TupleList *Search(char *RelationName, char *SearchString,
unsigned long *NumberOfEntriesRead) -
Search the relation for a particular string and return
the TupleList and the number of entries found.
- TupleList *TupleListUnion(TupleList *TupleList1, TupleList *TupleList2) -
Perform the set union on the given TupleLists and return the result.
The given TupleLists are destroyed upon return from this routine.
- TupleList *TupleListIntersection(TupleList *TupleList1, TupleList *TupleList2) -
Perform the set intersection on the given TupleLists and return the
result.
The given TupleLists are destroyed upon return from this routine.
- TupleList *TupleListNot(TupleList *In, TupleList *ButNotIn) -
Perform the set exclusion on the given TupleLists; return all
nodes in In but not in ButNotIn.
The given TupleLists are destroyed upon return from this routine.
- unsigned long SizeOfFile(int FileDesc) -
Return the size of the
given file; usually used to read the contents of a file in a single read.
- void ReadEntry(int FileDesc, Entry ThisEntry, unsigned long
Start, unsigned long Length) - Read an entry with the given offset and
length in the file.
- void WriteEntry(int FileDesc, Entry ThisEntry) -
Write the entry into the file at the current location.
- unsigned long GetEntryNumber(Entry TheEntry) -
Return the unique identifier of the entry.
- Boolean EntryInvalid(Entry TheEntry) -
Return True if the entry has been updated; false otherwise.
Next: References
Up: An ASCII Database
Previous: 10 Discussion
Herrin Software Development, Inc.