diff options
Diffstat (limited to 'slib_6.html')
-rw-r--r-- | slib_6.html | 3658 |
1 files changed, 3658 insertions, 0 deletions
diff --git a/slib_6.html b/slib_6.html new file mode 100644 index 0000000..804d4e9 --- /dev/null +++ b/slib_6.html @@ -0,0 +1,3658 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html40/loose.dtd"> +<HTML> +<!-- Created on January, 10 2005 by texi2html 1.66 --> +<!-- +Written by: Lionel Cons <Lionel.Cons@cern.ch> (original author) + Karl Berry <karl@freefriends.org> + Olaf Bachmann <obachman@mathematik.uni-kl.de> + and many others. +Maintained by: Many creative people <dev@texi2html.cvshome.org> +Send bugs and suggestions to <users@texi2html.cvshome.org> + +--> +<HEAD> +<TITLE>SLIB: Database Packages</TITLE> + +<META NAME="description" CONTENT="SLIB: Database Packages"> +<META NAME="keywords" CONTENT="SLIB: Database Packages"> +<META NAME="resource-type" CONTENT="document"> +<META NAME="distribution" CONTENT="global"> +<META NAME="Generator" CONTENT="texi2html 1.66"> + +</HEAD> + +<BODY LANG="en" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080" ALINK="#FF0000"> + +<A NAME="SEC140"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_5.html#SEC139"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC141"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_5.html#SEC88"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H1> 6. Database Packages </H1> +<!--docid::SEC140::--> +<P> + +<TABLE BORDER="0" CELLSPACING="0"> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC141">6.1 Relational Database</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">'relational-database</TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC165">6.2 Relational Infrastructure</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC178">6.3 Weight-Balanced Trees</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">'wt-tree</TD></TR> +</TABLE> +<P> + +<A NAME="Relational Database"></A> +<HR SIZE="6"> +<A NAME="SEC141"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC142"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H2> 6.1 Relational Database </H2> +<!--docid::SEC141::--> +<P> + +<CODE>(require 'relational-database)</CODE> +<A NAME="IDX917"></A> +</P> +<P> + +This package implements a database system inspired by the Relational +Model (<CITE>E. F. Codd, A Relational Model of Data for Large Shared +Data Banks</CITE>). An SLIB relational database implementation can be created +from any <A HREF="slib_6.html#SEC166">6.2.1 Base Table</A> implementation. +</P> +<P> + +Why relational database? For motivations and design issues see<BR> +<A HREF="http://swissnet.ai.mit.edu/~jaffer/DBManifesto.html">http://swissnet.ai.mit.edu/~jaffer/DBManifesto.html</A>. +</P> +<P> + +<TABLE BORDER="0" CELLSPACING="0"> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC142">6.1.1 Using Databases</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">'databases</TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC147">6.1.2 Table Operations</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC154">6.1.3 Database Interpolation</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">'database-interpolate</TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC155">6.1.4 Embedded Commands</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">'database-commands</TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC162">6.1.5 Database Macros</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">'within-database</TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC164">6.1.6 Database Browser</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">'database-browse</TD></TR> +</TABLE> +<P> + +<A NAME="Using Databases"></A> +<HR SIZE="6"> +<A NAME="SEC142"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC141"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC147"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC141"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 6.1.1 Using Databases </H3> +<!--docid::SEC142::--> +<P> + +<CODE>(require 'databases)</CODE> +<A NAME="IDX918"></A> +</P> +<P> + +This enhancement wraps a utility layer on <CODE>relational-database</CODE> +which provides: +</P> +<P> + +<UL> +<LI> +Identification of open databases by filename. +<LI> +Automatic sharing of open (immutable) databases. +<LI> +Automatic loading of base-table package when creating a database. +<LI> +Detection and automatic loading of the appropriate base-table package +when opening a database. +<LI> +Table and data definition from Scheme lists. +</UL> +<P> + +<A NAME="SEC143"></A> +<H4> Database Sharing </H4> +<!--docid::SEC143::--> +<P> + +<EM>Auto-sharing</EM> refers to a call to the procedure +<A NAME="IDX919"></A> +<CODE>open-database</CODE> returning an already open database (procedure), +rather than opening the database file a second time. +</P> +<P> + +<BLOCKQUOTE> +<EM>Note:</EM> Databases returned by <CODE>open-database</CODE> do not include +wrappers applied by packages like <A HREF="slib_6.html#SEC155">6.1.4 Embedded Commands</A>. But +wrapped databases do work as arguments to these functions. +</BLOCKQUOTE> +<P> + +When a database is created, it is mutable by the creator and not +auto-sharable. A database opened mutably is also not auto-sharable. +But any number of readers can (open) share a non-mutable database file. +</P> +<P> + +This next set of procedures mirror the whole-database methods in +<A HREF="slib_6.html#SEC177">6.2.4 Database Operations</A>. Except for <CODE>create-database</CODE>, each +procedure will accept either a filename or database procedure for its +first argument. +</P> +<P> + +<A NAME="IDX920"></A> +</P> +<DL> +<DT><U>Function:</U> <B>create-database</B> <I>filename base-table-type</I> +<DD><P> + +<VAR>filename</VAR> should be a string naming a file; or <CODE>#f</CODE>. <VAR>base-table-type</VAR> must be a +symbol naming a feature which can be passed to <CODE>require</CODE>. <CODE>create-database</CODE> +returns a new, open relational database (with base-table type <VAR>base-table-type</VAR>) +associated with <VAR>filename</VAR>, or a new ephemeral database if <VAR>filename</VAR> is <CODE>#f</CODE>. +</P> +<P> + +<CODE>create-database</CODE> is the only run-time use of require in SLIB +which crosses module boundaries. When <VAR>base-table-type</VAR> is <CODE>require</CODE>d by <CODE>create-database</CODE>; it +adds an association of <VAR>base-table-type</VAR> with its <EM>relational-system</EM> procedure +<A NAME="IDX921"></A> +to <VAR>mdbm:*databases*</VAR>. +</P> +<P> + +alist-table is the default base-table type: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(require 'databases) +(define my-rdb (create-database "my.db" 'alist-table)) +</pre></td></tr></table></DL> +Only <CODE>alist-table</CODE> and base-table modules which have been +<CODE>require</CODE>d will dispatch correctly from the +<CODE>open-database</CODE> procedures. Therefore, either pass two +arguments to <CODE>open-database</CODE>, or require the base-table of your +database file uses before calling <CODE>open-database</CODE> with one +argument. +<P> + +<A NAME="IDX922"></A> +</P> +<DL> +<DT><U>Procedure:</U> <B>open-database!</B> <I>rdb base-table-type</I> +<DD><P> + +Returns <EM>mutable</EM> open relational database or #f. +</P> +</DL> +<P> + +<A NAME="IDX923"></A> +</P> +<DL> +<DT><U>Function:</U> <B>open-database</B> <I>rdb base-table-type</I> +<DD><P> + +Returns an open relational database associated with <VAR>rdb</VAR>. The +database will be opened with base-table type <VAR>base-table-type</VAR>). +</P> +<P> + +<A NAME="IDX924"></A> +<DT><U>Function:</U> <B>open-database</B> <I>rdb</I> +<DD>Returns an open relational database associated with <VAR>rdb</VAR>. +<CODE>open-database</CODE> will attempt to deduce the correct base-table-type. +</P> +</DL> +<P> + +<A NAME="IDX925"></A> +</P> +<DL> +<DT><U>Function:</U> <B>write-database</B> <I>rdb filename</I> +<DD><P> + +Writes the mutable relational-database <VAR>rdb</VAR> to <VAR>filename</VAR>. +</P> +</DL> +<P> + +<A NAME="IDX926"></A> +</P> +<DL> +<DT><U>Function:</U> <B>sync-database</B> <I>rdb</I> +<DD><P> + +Writes the mutable relational-database <VAR>rdb</VAR> to the filename it was +opened with. +</P> +</DL> +<P> + +<A NAME="IDX927"></A> +</P> +<DL> +<DT><U>Function:</U> <B>solidify-database</B> <I>rdb</I> +<DD><P> + +Syncs <VAR>rdb</VAR> and makes it immutable. +</P> +</DL> +<P> + +<A NAME="IDX928"></A> +</P> +<DL> +<DT><U>Function:</U> <B>close-database</B> <I>rdb</I> +<DD><P> + +<VAR>rdb</VAR> will only be closed when the count of <CODE>open-database</CODE> - <CODE>close-database</CODE> +calls for <VAR>rdb</VAR> (and its filename) is 0. <CODE>close-database</CODE> returns #t if successful; +and #f otherwise. +</P> +</DL> +<P> + +<A NAME="IDX929"></A> +</P> +<DL> +<DT><U>Function:</U> <B>mdbm:report</B> +<DD><P> + +Prints a table of open database files. The columns are the +base-table type, number of opens, `<SAMP>!</SAMP>' for mutable, the +filename, and the lock certificate (if locked). +</P> +</DL> +<TABLE><tr><td> </td><td class=example><pre>(mdbm:report) +-| + alist-table 003 /usr/local/lib/slib/clrnamdb.scm + alist-table 001 ! sdram.db jaffer@aubrey.jaffer.3166:1038628199 +</pre></td></tr></table><P> + +<A NAME="SEC144"></A> +<H4> Opening Tables </H4> +<!--docid::SEC144::--> +<P> + +<A NAME="IDX930"></A> +</P> +<DL> +<DT><U>Function:</U> <B>open-table</B> <I>rdb table-name</I> +<DD><P> + +<VAR>rdb</VAR> must be a relational database and <VAR>table-name</VAR> a symbol. +</P> +<P> + +<CODE>open-table</CODE> returns a "methods" procedure for an existing relational table in +<VAR>rdb</VAR> if it exists and can be opened for reading, otherwise returns +<CODE>#f</CODE>. +</P> +</DL> +<P> + +<A NAME="IDX931"></A> +</P> +<DL> +<DT><U>Procedure:</U> <B>open-table!</B> <I>rdb table-name</I> +<DD><P> + +<VAR>rdb</VAR> must be a relational database and <VAR>table-name</VAR> a symbol. +</P> +<P> + +<CODE>open-table!</CODE> returns a "methods" procedure for an existing relational table in +<VAR>rdb</VAR> if it exists and can be opened in mutable mode, otherwise returns +<CODE>#f</CODE>. +</P> +</DL> +<A NAME="SEC145"></A> +<H4> Defining Tables </H4> +<!--docid::SEC145::--> +<P> + +<A NAME="IDX932"></A> +</P> +<DL> +<DT><U>Function:</U> <B>define-domains</B> <I>rdb row5 <small>...</small></I> +<DD><P> + +Adds the domain rows <VAR>row5</VAR> <small>...</small> to the `<SAMP>*domains-data*</SAMP>' table +in <VAR>rdb</VAR>. The format of the row is given in <A HREF="slib_6.html#SEC175">6.2.2 Catalog Representation</A>. +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(define-domains rdb '(permittivity #f complex? c64 #f)) +</pre></td></tr></table></DL> +<P> + +<A NAME="IDX933"></A> +</P> +<DL> +<DT><U>Function:</U> <B>add-domain</B> <I>rdb row5</I> +<DD><P> + +Use <CODE>define-domains</CODE> instead. +</P> +</DL> +<P> + +<A NAME="IDX934"></A> +</P> +<DL> +<DT><U>Function:</U> <B>define-tables</B> <I>rdb spec-0 <small>...</small></I> +<DD><P> + +Adds tables as specified in <VAR>spec-0</VAR> <small>...</small> to the open +relational-database <VAR>rdb</VAR>. Each <VAR>spec</VAR> has the form: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(<name> <descriptor-name> <descriptor-name> <rows>) +</pre></td></tr></table>or +<TABLE><tr><td> </td><td class=example><pre>(<name> <primary-key-fields> <other-fields> <rows>) +</pre></td></tr></table><P> + +where <name> is the table name, <descriptor-name> is the symbol +name of a descriptor table, <primary-key-fields> and +<other-fields> describe the primary keys and other fields +respectively, and <rows> is a list of data rows to be added to the +table. +</P> +<P> + +<primary-key-fields> and <other-fields> are lists of field +descriptors of the form: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(<column-name> <domain>) +</pre></td></tr></table>or +<TABLE><tr><td> </td><td class=example><pre>(<column-name> <domain> <column-integrity-rule>) +</pre></td></tr></table><P> + +where <column-name> is the column name, <domain> is the domain +of the column, and <column-integrity-rule> is an expression whose +value is a procedure of one argument (which returns <CODE>#f</CODE> to signal +an error). +</P> +<P> + +If <domain> is not a defined domain name and it matches the name of +this table or an already defined (in one of <VAR>spec-0</VAR> <small>...</small>) single +key field table, a foreign-key domain will be created for it. +</P> +</DL> +<A NAME="SEC146"></A> +<H4> Listing Tables </H4> +<!--docid::SEC146::--> +<P> + +<A NAME="IDX935"></A> +</P> +<DL> +<DT><U>Function:</U> <B>list-table-definition</B> <I>rdb table-name</I> +<DD><P> + +If symbol <VAR>table-name</VAR> exists in the open relational-database +<VAR>rdb</VAR>, then returns a list of the table-name, its primary key names +and domains, its other key names and domains, and the table's records +(as lists). Otherwise, returns #f. +</P> +<P> + +The list returned by <CODE>list-table-definition</CODE>, when passed as an +argument to <CODE>define-tables</CODE>, will recreate the table. +</P> +</DL> +<P> + +<A NAME="Table Operations"></A> +<HR SIZE="6"> +<A NAME="SEC147"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC142"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC148"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC141"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 6.1.2 Table Operations </H3> +<!--docid::SEC147::--> +<P> + +These are the descriptions of the methods available from an open +relational table. A method is retrieved from a table by calling +the table with the symbol name of the operation. For example: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>((plat 'get 'processor) 'djgpp) => i386 +</pre></td></tr></table><P> + +Some operations described below require primary key arguments. Primary +keys arguments are denoted <VAR>key1</VAR> <VAR>key2</VAR> <small>...</small>. It is an +error to call an operation for a table which takes primary key arguments +with the wrong number of primary keys for that table. +</P> +<P> + +<A NAME="IDX936"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-table <B>get</B> <I>column-name</I> +<DD>Returns a procedure of arguments <VAR>key1</VAR> <VAR>key2</VAR> <small>...</small> which +returns the value for the <VAR>column-name</VAR> column of the row associated +with primary keys <VAR>key1</VAR>, <VAR>key2</VAR> <small>...</small> if that row exists in +the table, or <CODE>#f</CODE> otherwise. +<P> + +<TABLE><tr><td> </td><td class=example><pre>((plat 'get 'processor) 'djgpp) => i386 +((plat 'get 'processor) 'be-os) => #f +</pre></td></tr></table></DL> +<P> + +<TABLE BORDER="0" CELLSPACING="0"> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC148">6.1.2.1 Single Row Operations</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC149">6.1.2.2 Match-Keys</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC150">6.1.2.3 Multi-Row Operations</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC151">6.1.2.4 Indexed Sequential Access Methods</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC152">6.1.2.5 Sequential Index Operations</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC153">6.1.2.6 Table Administration</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +</TABLE> +<P> + +<A NAME="Single Row Operations"></A> +<HR SIZE="6"> +<A NAME="SEC148"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC147"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC149"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC147"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.1.2.1 Single Row Operations </H4> +<!--docid::SEC148::--> +<P> + +The term <EM>row</EM> used below refers to a Scheme list of values (one for +each column) in the order specified in the descriptor (table) for this +table. Missing values appear as <CODE>#f</CODE>. Primary keys must not +be missing. +</P> +<P> + +<A NAME="IDX937"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-table <B>row:insert</B> +<DD>Adds the row <VAR>row</VAR> to this table. If a row for the primary key(s) +specified by <VAR>row</VAR> already exists in this table an error is +signaled. The value returned is unspecified. +</DL> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(define telephone-table-desc + ((my-database 'create-table) 'telephone-table-desc)) +(define ndrp (telephone-table-desc 'row:insert)) +(ndrp '(1 #t name #f string)) +(ndrp '(2 #f telephone + (lambda (d) + (and (string? d) (> (string-length d) 2) + (every + (lambda (c) + (memv c '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 + #\+ #\( #\ #\) #\-))) + (string->list d)))) + string)) +</pre></td></tr></table><P> + +<A NAME="IDX938"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-table <B>row:update</B> +<DD>Returns a procedure of one argument, <VAR>row</VAR>, which adds the row, +<VAR>row</VAR>, to this table. If a row for the primary key(s) specified by +<VAR>row</VAR> already exists in this table, it will be overwritten. The +value returned is unspecified. +</DL> +<P> + +<A NAME="IDX939"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-table <B>row:retrieve</B> +<DD>Returns a procedure of arguments <VAR>key1</VAR> <VAR>key2</VAR> <small>...</small> which +returns the row associated with primary keys <VAR>key1</VAR>, <VAR>key2</VAR> +<small>...</small> if it exists, or <CODE>#f</CODE> otherwise. +</DL> +<P> + +<TABLE><tr><td> </td><td class=example><pre>((plat 'row:retrieve) 'linux) => (linux i386 linux gcc) +((plat 'row:retrieve) 'multics) => #f +</pre></td></tr></table><P> + +<A NAME="IDX940"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-table <B>row:remove</B> +<DD>Returns a procedure of arguments <VAR>key1</VAR> <VAR>key2</VAR> <small>...</small> which +removes and returns the row associated with primary keys <VAR>key1</VAR>, +<VAR>key2</VAR> <small>...</small> if it exists, or <CODE>#f</CODE> otherwise. +</DL> +<P> + +<A NAME="IDX941"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-table <B>row:delete</B> +<DD>Returns a procedure of arguments <VAR>key1</VAR> <VAR>key2</VAR> <small>...</small> which +deletes the row associated with primary keys <VAR>key1</VAR>, <VAR>key2</VAR> +<small>...</small> if it exists. The value returned is unspecified. +</DL> +<P> + +<A NAME="Match-Keys"></A> +<HR SIZE="6"> +<A NAME="SEC149"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC148"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC150"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC147"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.1.2.2 Match-Keys </H4> +<!--docid::SEC149::--> +<P> + +<A NAME="IDX942"></A> +The (optional) <VAR>match-key1</VAR> <small>...</small> arguments are used to restrict +actions of a whole-table operation to a subset of that table. Those +procedures (returned by methods) which accept match-key arguments will +accept any number of match-key arguments between zero and the number of +primary keys in the table. Any unspecified <VAR>match-key</VAR> arguments +default to <CODE>#f</CODE>. +</P> +<P> + +The <VAR>match-key1</VAR> <small>...</small> restrict the actions of the table command +to those records whose primary keys each satisfy the corresponding +<VAR>match-key</VAR> argument. The arguments and their actions are: +</P> +<P> + +<BLOCKQUOTE> +<DL COMPACT> +<DT><CODE>#f</CODE> +<DD>The false value matches any key in the corresponding position. +<DT>an object of type procedure +<DD>This procedure must take a single argument, the key in the corresponding +position. Any key for which the procedure returns a non-false value is +a match; Any key for which the procedure returns a <CODE>#f</CODE> is not. +<DT>other values +<DD>Any other value matches only those keys <CODE>equal?</CODE> to it. +</DL> +</BLOCKQUOTE> +<P> + +<A NAME="IDX943"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-table <B>get*</B> <I>column-name</I> +<DD>Returns a procedure of optional arguments <VAR>match-key1</VAR> <small>...</small> which +returns a list of the values for the specified column for all rows in +this table. The optional <VAR>match-key1</VAR> <small>...</small> arguments restrict +actions to a subset of the table. +<P> + +<TABLE><tr><td> </td><td class=example><pre>((plat 'get* 'processor)) => +(i386 i8086 i386 i8086 i386 i386 i8086 m68000 + m68000 m68000 m68000 m68000 powerpc) + +((plat 'get* 'processor) #f) => +(i386 i8086 i386 i8086 i386 i386 i8086 m68000 + m68000 m68000 m68000 m68000 powerpc) + +(define (a-key? key) + (char=? #\a (string-ref (symbol->string key) 0))) + +((plat 'get* 'processor) a-key?) => +(m68000 m68000 m68000 m68000 m68000 powerpc) + +((plat 'get* 'name) a-key?) => +(atari-st-turbo-c atari-st-gcc amiga-sas/c-5.10 + amiga-aztec amiga-dice-c aix) +</pre></td></tr></table></DL> +<P> + +<A NAME="Multi-Row Operations"></A> +<HR SIZE="6"> +<A NAME="SEC150"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC149"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC151"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC147"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.1.2.3 Multi-Row Operations </H4> +<!--docid::SEC150::--> +<P> + +<A NAME="IDX944"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-table <B>row:retrieve*</B> +<DD>Returns a procedure of optional arguments <VAR>match-key1</VAR> <small>...</small> +which returns a list of all rows in this table. The optional +<VAR>match-key1</VAR> <small>...</small> arguments restrict actions to a subset of the +table. For details see See section <A HREF="slib_6.html#SEC149">6.1.2.2 Match-Keys</A>. +</DL> +<P> + +<TABLE><tr><td> </td><td class=example><pre>((plat 'row:retrieve*) a-key?) => +((atari-st-turbo-c m68000 atari turbo-c) + (atari-st-gcc m68000 atari gcc) + (amiga-sas/c-5.10 m68000 amiga sas/c) + (amiga-aztec m68000 amiga aztec) + (amiga-dice-c m68000 amiga dice-c) + (aix powerpc aix -)) +</pre></td></tr></table><P> + +<A NAME="IDX945"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-table <B>row:remove*</B> +<DD>Returns a procedure of optional arguments <VAR>match-key1</VAR> <small>...</small> which +removes and returns a list of all rows in this table. The optional +<VAR>match-key1</VAR> <small>...</small> arguments restrict actions to a subset of the +table. +</DL> +<P> + +<A NAME="IDX946"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-table <B>row:delete*</B> +<DD>Returns a procedure of optional arguments <VAR>match-key1</VAR> <small>...</small> +which Deletes all rows from this table. The optional <VAR>match-key1</VAR> +<small>...</small> arguments restrict deletions to a subset of the table. The +value returned is unspecified. The descriptor table and catalog entry +for this table are not affected. +</DL> +<P> + +<A NAME="IDX947"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-table <B>for-each-row</B> +<DD>Returns a procedure of arguments <VAR>proc</VAR> <VAR>match-key1</VAR> <small>...</small> +which calls <VAR>proc</VAR> with each <VAR>row</VAR> in this table. The +optional <VAR>match-key1</VAR> <small>...</small> arguments restrict actions to a +subset of the table. For details see See section <A HREF="slib_6.html#SEC149">6.1.2.2 Match-Keys</A>. +</DL> +<P> + +Note that <CODE>row:insert*</CODE> and <CODE>row:update*</CODE> do <EM>not</EM> use +match-keys. +</P> +<P> + +<A NAME="IDX948"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-table <B>row:insert*</B> +<DD>Returns a procedure of one argument, <VAR>rows</VAR>, which adds each row in +the list of rows, <VAR>rows</VAR>, to this table. If a row for the primary +key specified by an element of <VAR>rows</VAR> already exists in this table, +an error is signaled. The value returned is unspecified. +</DL> +<P> + +<A NAME="IDX949"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-table <B>row:update*</B> +<DD>Returns a procedure of one argument, <VAR>rows</VAR>, which adds each row in +the list of rows, <VAR>rows</VAR>, to this table. If a row for the primary +key specified by an element of <VAR>rows</VAR> already exists in this table, +it will be overwritten. The value returned is unspecified. +</DL> +<P> + +<A NAME="Indexed Sequential Access Methods"></A> +<HR SIZE="6"> +<A NAME="SEC151"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC150"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC152"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC147"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.1.2.4 Indexed Sequential Access Methods </H4> +<!--docid::SEC151::--> +<P> + +<A NAME="IDX950"></A> +<EM>Indexed Sequential Access Methods</EM> are a way of arranging +database information so that records can be accessed both by key and +by key sequence (ordering). <EM>ISAM</EM> is not part of Codd's +relational model. Hardcore relational programmers might use some +least-upper-bound join for every row to get them into an order. +</P> +<P> + +Associative memory in B-Trees is an example of a database +implementation which can support a native key ordering. SLIB's +<CODE>alist-table</CODE> implementation uses <CODE>sort</CODE> to implement +<CODE>for-each-row-in-order</CODE>, but does not support <CODE>isam-next</CODE> +and <CODE>isam-prev</CODE>. +</P> +<P> + +The multi-primary-key ordering employed by these operations is the +lexicographic collation of those primary-key fields in their given +order. For example: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(12 a 34) < (12 a 36) < (12 b 1) < (13 a 0) +</pre></td></tr></table><P> + +<A NAME="Sequential Index Operations"></A> +<HR SIZE="6"> +<A NAME="SEC152"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC151"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC153"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC147"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.1.2.5 Sequential Index Operations </H4> +<!--docid::SEC152::--> +<P> + +The following procedures are individually optional depending on the +base-table implememtation. If an operation is <EM>not</EM> supported, +then calling the table with that operation symbol will return false. +</P> +<P> + +<A NAME="IDX951"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-table <B>for-each-row-in-order</B> +<DD>Returns a procedure of arguments <VAR>proc</VAR> <VAR>match-key1</VAR> <small>...</small> +which calls <VAR>proc</VAR> with each <VAR>row</VAR> in this table in the +(implementation-dependent) natural, repeatable ordering for rows. The +optional <VAR>match-key1</VAR> <small>...</small> arguments restrict actions to a +subset of the table. For details see See section <A HREF="slib_6.html#SEC149">6.1.2.2 Match-Keys</A>. +</DL> +<P> + +<A NAME="IDX952"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-table <B>isam-next</B> +<DD>Returns a procedure of arguments <VAR>key1</VAR> <VAR>key2</VAR> <small>...</small> which +returns the key-list identifying the lowest record higher than +<VAR>key1</VAR> <VAR>key2</VAR> <small>...</small> which is stored in the relational-table; +or false if no higher record is present. +<P> + +<A NAME="IDX953"></A> +<DT><U>Operation:</U> relational-table <B>isam-next</B> <I>column-name</I> +<DD>The symbol <VAR>column-name</VAR> names a key field. In the list returned +by <CODE>isam-next</CODE>, that field, or a field to its left, will be +changed. This allows one to skip over less significant key fields. +</P> +</DL> +<P> + +<A NAME="IDX954"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-table <B>isam-prev</B> +<DD>Returns a procedure of arguments <VAR>key1</VAR> <VAR>key2</VAR> <small>...</small> which +returns the key-list identifying the highest record less than +<VAR>key1</VAR> <VAR>key2</VAR> <small>...</small> which is stored in the relational-table; +or false if no lower record is present. +<P> + +<A NAME="IDX955"></A> +<DT><U>Operation:</U> relational-table <B>isam-prev</B> <I>index</I> +<DD>The symbol <VAR>column-name</VAR> names a key field. In the list returned +by <CODE>isam-next</CODE>, that field, or a field to its left, will be +changed. This allows one to skip over less significant key fields. +</P> +</DL> +<P> + +For example, if a table has key fields: +<TABLE><tr><td> </td><td class=example><pre>(col1 col2) +(9 5) +(9 6) +(9 7) +(9 8) +(12 5) +(12 6) +(12 7) +</pre></td></tr></table><P> + +Then: +<TABLE><tr><td> </td><td class=example><pre>((table 'isam-next) '(9 5)) => (9 6) +((table 'isam-next 'col2) '(9 5)) => (9 6) +((table 'isam-next 'col1) '(9 5)) => (12 5) +((table 'isam-prev) '(12 7)) => (12 6) +((table 'isam-prev 'col2) '(12 7)) => (12 6) +((table 'isam-prev 'col1) '(12 7)) => (9 8) +</pre></td></tr></table><P> + +<A NAME="Table Administration"></A> +<HR SIZE="6"> +<A NAME="SEC153"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC152"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC154"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC147"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.1.2.6 Table Administration </H4> +<!--docid::SEC153::--> +<P> + +<A NAME="IDX956"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-table <B>column-names</B> +<DD><A NAME="IDX957"></A> +<DT><U>Operation:</U> relational-table <B>column-foreigns</B> +<DD><A NAME="IDX958"></A> +<DT><U>Operation:</U> relational-table <B>column-domains</B> +<DD><A NAME="IDX959"></A> +<DT><U>Operation:</U> relational-table <B>column-types</B> +<DD>Return a list of the column names, foreign-key table names, domain +names, or type names respectively for this table. These 4 methods are +different from the others in that the list is returned, rather than a +procedure to obtain the list. +<P> + +<A NAME="IDX960"></A> +<DT><U>Operation:</U> relational-table <B>primary-limit</B> +<DD>Returns the number of primary keys fields in the relations in this +table. +</P> +</DL> +<P> + +<A NAME="IDX961"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-table <B>close-table</B> +<DD>Subsequent operations to this table will signal an error. +</DL> +<P> + +<A NAME="Database Interpolation"></A> +<HR SIZE="6"> +<A NAME="SEC154"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC153"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC155"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC141"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 6.1.3 Database Interpolation </H3> +<!--docid::SEC154::--> +<P> + +<CODE>(require 'database-interpolate)</CODE> +</P> +<P> + +Indexed sequential access methods allow finding the keys (having +associations) closest to a given value. This facilitates the +interpolation of associations between those in the table. +</P> +<P> + +<A NAME="IDX962"></A> +</P> +<DL> +<DT><U>Function:</U> <B>interpolate-from-table</B> <I>table column</I> +<DD><VAR>Table</VAR> should be a relational table with one numeric primary key +field which supports the <CODE>isam-prev</CODE> and <CODE>isam-next</CODE> +operations. <VAR>column</VAR> should be a symbol or exact positive integer +designating a numerically valued column of <VAR>table</VAR>. +<P> + +<CODE>interpolate-from-table</CODE> calculates and returns a value +proportionally intermediate between its values in the next and +previous key records contained in <VAR>table</VAR>. For keys larger than +all the stored keys the value associated with the largest stored key +is used. For keys smaller than all the stored keys the value +associated with the smallest stored key is used. +</P> +</DL> +<P> + +<A NAME="Embedded Commands"></A> +<HR SIZE="6"> +<A NAME="SEC155"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC154"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC156"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC141"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 6.1.4 Embedded Commands </H3> +<!--docid::SEC155::--> +<P> + +<CODE>(require 'database-commands)</CODE> +</P> +<P> + +This enhancement wraps a utility layer on <CODE>relational-database</CODE> +which provides: +</P> +<P> + +<UL> +<LI> +Automatic execution of initialization commands stored in database. +<LI> +Transparent execution of database commands stored in <CODE>*commands*</CODE> +table in database. +</UL> +<P> + +When an enhanced relational-database is called with a symbol which +matches a <VAR>name</VAR> in the <CODE>*commands*</CODE> table, the associated +procedure expression is evaluated and applied to the enhanced +relational-database. A procedure should then be returned which the user +can invoke on (optional) arguments. +</P> +<P> + +The command <CODE>*initialize*</CODE> is special. If present in the +<CODE>*commands*</CODE> table, <CODE>open-database</CODE> or <CODE>open-database!</CODE> +will return the value of the <CODE>*initialize*</CODE> command. Notice that +arbitrary code can be run when the <CODE>*initialize*</CODE> procedure is +automatically applied to the enhanced relational-database. +</P> +<P> + +Note also that if you wish to shadow or hide from the user +relational-database methods described in <A HREF="slib_6.html#SEC177">6.2.4 Database Operations</A>, this +can be done by a dispatch in the closure returned by the +<CODE>*initialize*</CODE> expression rather than by entries in the +<CODE>*commands*</CODE> table if it is desired that the underlying methods +remain accessible to code in the <CODE>*commands*</CODE> table. +</P> +<P> + +<TABLE BORDER="0" CELLSPACING="0"> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC156">6.1.4.1 Database Extension</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC157">6.1.4.2 Command Intrinsics</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC158">6.1.4.3 Define-tables Example</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC159">6.1.4.4 The *commands* Table</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC160">6.1.4.5 Command Service</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC161">6.1.4.6 Command Example</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +</TABLE> +<P> + +<A NAME="Database Extension"></A> +<HR SIZE="6"> +<A NAME="SEC156"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC155"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC157"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC155"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.1.4.1 Database Extension </H4> +<!--docid::SEC156::--> +<P> + +<A NAME="IDX963"></A> +</P> +<DL> +<DT><U>Function:</U> <B>wrap-command-interface</B> <I>rdb</I> +<DD>Returns relational database <VAR>rdb</VAR> wrapped with additional commands +defined in its *commands* table. +</DL> +<P> + +<A NAME="IDX964"></A> +</P> +<DL> +<DT><U>Function:</U> <B>add-command-tables</B> <I>rdb</I> +<DD>The relational database <VAR>rdb</VAR> must be mutable. +<VAR>add-command-tables</VAR> adds a *command* table to <VAR>rdb</VAR>; then +returns <CODE>(wrap-command-interface <VAR>rdb</VAR>)</CODE>. +</DL> +<P> + +<A NAME="IDX965"></A> +</P> +<DL> +<DT><U>Function:</U> <B>define-*commands*</B> <I>rdb spec-0 <small>...</small></I> +<DD><P> + +Adds commands to the <CODE>*commands*</CODE> table as specified in +<VAR>spec-0</VAR> <small>...</small> to the open relational-database <VAR>rdb</VAR>. Each +<VAR>spec</VAR> has the form: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>((<name> <rdb>) "comment" <expression1> <expression2> <small>...</small>) +</pre></td></tr></table>or +<TABLE><tr><td> </td><td class=example><pre>((<name> <rdb>) <expression1> <expression2> <small>...</small>) +</pre></td></tr></table><P> + +where <name> is the command name, <rdb> is a formal passed the +calling relational database, "comment" describes the +command, and <expression1>, <expression1>, <small>...</small> are the +body of the procedure. +</P> +<P> + +<CODE>define-*commands*</CODE> adds to the <CODE>*commands*</CODE> table a command +<name>: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(lambda (<name> <rdb>) <expression1> <expression2> <small>...</small>) +</pre></td></tr></table><P> + +</P> +</DL> +<P> + +<A NAME="IDX966"></A> +</P> +<DL> +<DT><U>Function:</U> <B>open-command-database</B> <I>filename</I> +<DD><A NAME="IDX967"></A> +<DT><U>Function:</U> <B>open-command-database</B> <I>filename base-table-type</I> +<DD>Returns an open enhanced relational database associated with +<VAR>filename</VAR>. The database will be opened with base-table type +<VAR>base-table-type</VAR>) if supplied. If <VAR>base-table-type</VAR> is not +supplied, <CODE>open-command-database</CODE> will attempt to deduce the correct +base-table-type. If the database can not be opened or if it lacks the +<CODE>*commands*</CODE> table, <CODE>#f</CODE> is returned. +<P> + +<A NAME="IDX968"></A> +<DT><U>Function:</U> <B>open-command-database!</B> <I>filename</I> +<DD><A NAME="IDX969"></A> +<DT><U>Function:</U> <B>open-command-database!</B> <I>filename base-table-type</I> +<DD>Returns <EM>mutable</EM> open enhanced relational database <small>...</small> +</P> +<P> + +<A NAME="IDX970"></A> +<DT><U>Function:</U> <B>open-command-database</B> <I>database</I> +<DD>Returns <VAR>database</VAR> if it is an immutable relational database; #f +otherwise. +</P> +<P> + +<A NAME="IDX971"></A> +<DT><U>Function:</U> <B>open-command-database!</B> <I>database</I> +<DD>Returns <VAR>database</VAR> if it is a mutable relational database; #f +otherwise. +</P> +</DL> +<P> + +<A NAME="Command Intrinsics"></A> +<HR SIZE="6"> +<A NAME="SEC157"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC156"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC158"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC155"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.1.4.2 Command Intrinsics </H4> +<!--docid::SEC157::--> +<P> + +Some commands are defined in all extended relational-databases. The are +called just like <A HREF="slib_6.html#SEC177">6.2.4 Database Operations</A>. +</P> +<P> + +<A NAME="IDX972"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-database <B>add-domain</B> <I>domain-row</I> +<DD>Adds <VAR>domain-row</VAR> to the <EM>domains</EM> table if there is no row in +the domains table associated with key <CODE>(car <VAR>domain-row</VAR>)</CODE> and +returns <CODE>#t</CODE>. Otherwise returns <CODE>#f</CODE>. +<P> + +For the fields and layout of the domain table, See section <A HREF="slib_6.html#SEC175">6.2.2 Catalog Representation</A>. Currently, these fields are +<UL> +<LI> +domain-name +<LI> +foreign-table +<LI> +domain-integrity-rule +<LI> +type-id +<LI> +type-param +</UL> +<P> + +The following example adds 3 domains to the `<SAMP>build</SAMP>' database. +`<SAMP>Optstring</SAMP>' is either a string or <CODE>#f</CODE>. <CODE>filename</CODE> is a +string and <CODE>build-whats</CODE> is a symbol. +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(for-each (build 'add-domain) + '((optstring #f + (lambda (x) (or (not x) (string? x))) + string + #f) + (filename #f #f string #f) + (build-whats #f #f symbol #f))) +</pre></td></tr></table></DL> +<P> + +<A NAME="IDX973"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-database <B>delete-domain</B> <I>domain-name</I> +<DD>Removes and returns the <VAR>domain-name</VAR> row from the <EM>domains</EM> +table. +</DL> +<P> + +<A NAME="IDX974"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-database <B>domain-checker</B> <I>domain</I> +<DD>Returns a procedure to check an argument for conformance to domain +<VAR>domain</VAR>. +</DL> +<P> + +<A NAME="Define-tables Example"></A> +<HR SIZE="6"> +<A NAME="SEC158"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC157"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC159"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC155"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.1.4.3 Define-tables Example </H4> +<!--docid::SEC158::--> +<P> + +The following example shows a new database with the name of +`<TT>foo.db</TT>' being created with tables describing processor families +and processor/os/compiler combinations. The database is then +solidified; saved and changed to immutable. +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(require 'databases) +<A NAME="IDX975"></A>(define my-rdb (create-database "foo.db" 'alist-table)) +(define-tables my-rdb + '(processor-family + ((family atom)) + ((also-ran processor-family)) + ((m68000 #f) + (m68030 m68000) + (i386 i8086) + (i8086 #f) + (powerpc #f))) + + '(platform + ((name symbol)) + ((processor processor-family) + (os symbol) + (compiler symbol)) + ((aix powerpc aix -) + (amiga-dice-c m68000 amiga dice-c) + (amiga-aztec m68000 amiga aztec) + (amiga-sas/c-5.10 m68000 amiga sas/c) + (atari-st-gcc m68000 atari gcc) + (atari-st-turbo-c m68000 atari turbo-c) + (borland-c-3.1 i8086 ms-dos borland-c) + (djgpp i386 ms-dos gcc) + (linux i386 linux gcc) + (microsoft-c i8086 ms-dos microsoft-c) + (os/2-emx i386 os/2 gcc) + (turbo-c-2 i8086 ms-dos turbo-c) + (watcom-9.0 i386 ms-dos watcom)))) + +(solidify-database my-rdb) +</pre></td></tr></table><P> + +<A NAME="The *commands* Table"></A> +<HR SIZE="6"> +<A NAME="SEC159"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC158"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC160"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC155"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.1.4.4 The *commands* Table </H4> +<!--docid::SEC159::--> +<P> + +The table <CODE>*commands*</CODE> in an <EM>enhanced</EM> relational-database has +the fields (with domains): +<TABLE><tr><td> </td><td class=example><pre>PRI name symbol + parameters parameter-list + procedure expression + documentation string +</pre></td></tr></table><P> + +The <CODE>parameters</CODE> field is a foreign key (domain +<CODE>parameter-list</CODE>) of the <CODE>*catalog-data*</CODE> table and should +have the value of a table described by <CODE>*parameter-columns*</CODE>. This +<CODE>parameter-list</CODE> table describes the arguments suitable for passing +to the associated command. The intent of this table is to be of a form +such that different user-interfaces (for instance, pull-down menus or +plain-text queries) can operate from the same table. A +<CODE>parameter-list</CODE> table has the following fields: +<TABLE><tr><td> </td><td class=example><pre>PRI index ordinal + name symbol + arity parameter-arity + domain domain + defaulter expression + expander expression + documentation string +</pre></td></tr></table><P> + +The <CODE>arity</CODE> field can take the values: +</P> +<P> + +</P> +<DL COMPACT> +<DT><CODE>single</CODE> +<DD>Requires a single parameter of the specified domain. +<DT><CODE>optional</CODE> +<DD>A single parameter of the specified domain or zero parameters is +acceptable. +<DT><CODE>boolean</CODE> +<DD>A single boolean parameter or zero parameters (in which case <CODE>#f</CODE> +is substituted) is acceptable. +<DT><CODE>nary</CODE> +<DD>Any number of parameters of the specified domain are acceptable. The +argument passed to the command function is always a list of the +parameters. +<DT><CODE>nary1</CODE> +<DD>One or more of parameters of the specified domain are acceptable. The +argument passed to the command function is always a list of the +parameters. +</DL> +<P> + +The <CODE>domain</CODE> field specifies the domain which a parameter or +parameters in the <CODE>index</CODE>th field must satisfy. +</P> +<P> + +The <CODE>defaulter</CODE> field is an expression whose value is either +<CODE>#f</CODE> or a procedure of one argument (the parameter-list) which +returns a <EM>list</EM> of the default value or values as appropriate. +Note that since the <CODE>defaulter</CODE> procedure is called every time a +default parameter is needed for this column, <EM>sticky</EM> defaults can +be implemented using shared state with the domain-integrity-rule. +</P> +<P> + +<A NAME="Command Service"></A> +<HR SIZE="6"> +<A NAME="SEC160"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC159"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC161"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC155"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.1.4.5 Command Service </H4> +<!--docid::SEC160::--> +<P> + +<A NAME="IDX976"></A> +</P> +<DL> +<DT><U>Function:</U> <B>make-command-server</B> <I>rdb table-name</I> +<DD>Returns a procedure of 2 arguments, a (symbol) command and a call-back +procedure. When this returned procedure is called, it looks up +<VAR>command</VAR> in table <VAR>table-name</VAR> and calls the call-back +procedure with arguments: +<DL COMPACT> +<DT><VAR>command</VAR> +<DD>The <VAR>command</VAR> +<DT><VAR>command-value</VAR> +<DD>The result of evaluating the expression in the <VAR>procedure</VAR> field of +<VAR>table-name</VAR> and calling it with <VAR>rdb</VAR>. +<DT><VAR>parameter-name</VAR> +<DD>A list of the <EM>official</EM> name of each parameter. Corresponds to the +<CODE>name</CODE> field of the <VAR>command</VAR>'s parameter-table. +<DT><VAR>positions</VAR> +<DD>A list of the positive integer index of each parameter. Corresponds to +the <CODE>index</CODE> field of the <VAR>command</VAR>'s parameter-table. +<DT><VAR>arities</VAR> +<DD>A list of the arities of each parameter. Corresponds to the +<CODE>arity</CODE> field of the <VAR>command</VAR>'s parameter-table. For a +description of <CODE>arity</CODE> see table above. +<DT><VAR>types</VAR> +<DD>A list of the type name of each parameter. Correspnds to the +<CODE>type-id</CODE> field of the contents of the <CODE>domain</CODE> of the +<VAR>command</VAR>'s parameter-table. +<DT><VAR>defaulters</VAR> +<DD>A list of the defaulters for each parameter. Corresponds to +the <CODE>defaulters</CODE> field of the <VAR>command</VAR>'s parameter-table. +<DT><VAR>domain-integrity-rules</VAR> +<DD>A list of procedures (one for each parameter) which tests whether a +value for a parameter is acceptable for that parameter. The procedure +should be called with each datum in the list for <CODE>nary</CODE> arity +parameters. +<DT><VAR>aliases</VAR> +<DD>A list of lists of <CODE>(alias parameter-name)</CODE>. There can be +more than one alias per <VAR>parameter-name</VAR>. +</DL> +</DL> +<P> + +For information about parameters, See section <A HREF="slib_4.html#SEC65">4.4.4 Parameter lists</A>. +</P> +<P> + +<A NAME="Command Example"></A> +<HR SIZE="6"> +<A NAME="SEC161"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC160"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC162"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC155"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.1.4.6 Command Example </H4> +<!--docid::SEC161::--> +<P> + +Here is an example of setting up a command with arguments and parsing +those arguments from a <CODE>getopt</CODE> style argument list +(see section <A HREF="slib_4.html#SEC62">4.4.1 Getopt</A>). +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(require 'database-commands) +<A NAME="IDX977"></A>(require 'databases) +<A NAME="IDX978"></A>(require 'getopt-parameters) +<A NAME="IDX979"></A>(require 'parameters) +<A NAME="IDX980"></A>(require 'getopt) +<A NAME="IDX981"></A>(require 'fluid-let) +(require 'printf) + +(define my-rdb (add-command-tables (create-database #f 'alist-table))) + +(define-tables my-rdb + '(foo-params + *parameter-columns* + *parameter-columns* + ((1 single-string single string + (lambda (pl) '("str")) #f "single string") + (2 nary-symbols nary symbol + (lambda (pl) '()) #f "zero or more symbols") + (3 nary1-symbols nary1 symbol + (lambda (pl) '(symb)) #f "one or more symbols") + (4 optional-number optional ordinal + (lambda (pl) '()) #f "zero or one number") + (5 flag boolean boolean + (lambda (pl) '(#f)) #f "a boolean flag"))) + '(foo-pnames + ((name string)) + ((parameter-index ordinal)) + (("s" 1) + ("single-string" 1) + ("n" 2) + ("nary-symbols" 2) + ("N" 3) + ("nary1-symbols" 3) + ("o" 4) + ("optional-number" 4) + ("f" 5) + ("flag" 5))) + '(my-commands + ((name symbol)) + ((parameters parameter-list) + (parameter-names parameter-name-translation) + (procedure expression) + (documentation string)) + ((foo + foo-params + foo-pnames + (lambda (rdb) (lambda args (print args))) + "test command arguments")))) + +(define (dbutil:serve-command-line rdb command-table command argv) + (set! *argv* (if (vector? argv) (vector->list argv) argv)) + ((make-command-server rdb command-table) + command + (lambda (comname comval options positions + arities types defaulters dirs aliases) + (apply comval (getopt->arglist options positions + arities types defaulters dirs aliases))))) + +(define (cmd . opts) + (fluid-let ((*optind* 1)) + (printf "%-34s => " + (call-with-output-string + (lambda (pt) (write (cons 'cmd opts) pt)))) + (set! opts (cons "cmd" opts)) + (force-output) + (dbutil:serve-command-line + my-rdb 'my-commands 'foo (length opts) opts))) + +(cmd) => ("str" () (symb) () #f) +(cmd "-f") => ("str" () (symb) () #t) +(cmd "--flag") => ("str" () (symb) () #t) +(cmd "-o177") => ("str" () (symb) (177) #f) +(cmd "-o" "177") => ("str" () (symb) (177) #f) +(cmd "--optional" "621") => ("str" () (symb) (621) #f) +(cmd "--optional=621") => ("str" () (symb) (621) #f) +(cmd "-s" "speciality") => ("speciality" () (symb) () #f) +(cmd "-sspeciality") => ("speciality" () (symb) () #f) +(cmd "--single" "serendipity") => ("serendipity" () (symb) () #f) +(cmd "--single=serendipity") => ("serendipity" () (symb) () #f) +(cmd "-n" "gravity" "piety") => ("str" () (piety gravity) () #f) +(cmd "-ngravity" "piety") => ("str" () (piety gravity) () #f) +(cmd "--nary" "chastity") => ("str" () (chastity) () #f) +(cmd "--nary=chastity" "") => ("str" () ( chastity) () #f) +(cmd "-N" "calamity") => ("str" () (calamity) () #f) +(cmd "-Ncalamity") => ("str" () (calamity) () #f) +(cmd "--nary1" "surety") => ("str" () (surety) () #f) +(cmd "--nary1=surety") => ("str" () (surety) () #f) +(cmd "-N" "levity" "fealty") => ("str" () (fealty levity) () #f) +(cmd "-Nlevity" "fealty") => ("str" () (fealty levity) () #f) +(cmd "--nary1" "surety" "brevity") => ("str" () (brevity surety) () #f) +(cmd "--nary1=surety" "brevity") => ("str" () (brevity surety) () #f) +(cmd "-?") +-| +Usage: cmd [OPTION ARGUMENT ...] ... + + -f, --flag + -o, --optional[=]<number> + -n, --nary[=]<symbols> ... + -N, --nary1[=]<symbols> ... + -s, --single[=]<string> + +ERROR: getopt->parameter-list "unrecognized option" "-?" +</pre></td></tr></table><P> + +<A NAME="Database Macros"></A> +<HR SIZE="6"> +<A NAME="SEC162"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC161"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC163"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC141"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 6.1.5 Database Macros </H3> +<!--docid::SEC162::--> +<P> + +<CODE>(require 'within-database)</CODE> +</P> +<P> + +The object-oriented programming interface to SLIB relational databases +has failed to support clear, understandable, and modular code-writing +for database applications. +</P> +<P> + +This seems to be a failure of the object-oriented paradigm where the +type of an object is not manifest (or even traceable) in source code. +</P> +<P> + +<CODE>within-database</CODE>, along with the `<SAMP>databases</SAMP>' package, +reorganizes high-level database functions toward a more declarative +style. Using this package, one can tag database table and command +declarations for emacs: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>etags -lscheme -r'/ *(define-\(command\|table\) (\([^; \t]+\)/\2/' \ + source1.scm ... +</pre></td></tr></table><P> + +<TABLE BORDER="0" CELLSPACING="0"> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC163">6.1.5.1 Within-database Example</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +</TABLE> +<P> + +<A NAME="IDX982"></A> +</P> +<DL> +<DT><U>Function:</U> <B>within-database</B> <I>database statement-1 <small>...</small></I> +<DD><P> + +<CODE>within-database</CODE> creates a lexical scope in which the commands +<CODE>define-table</CODE> and <CODE>define-command</CODE> create tables and +<CODE>*commands*</CODE>-table entries respectively in open relational +database <VAR>database</VAR>. +</P> +<P> + +<CODE>within-database</CODE> Returns <VAR>database</VAR>. +</P> +</DL> +<P> + +<A NAME="IDX983"></A> +</P> +<DL> +<DT><U>Syntax:</U> <B>define-command</B> <I>(<name> <rdb>) "comment" <expression1> <expression2> <small>...</small></I> +<DD><A NAME="IDX984"></A> +<DT><U>Syntax:</U> <B>define-command</B> <I>(<name> <rdb>) <expression1> <expression2> <small>...</small></I> +<DD><P> + +Adds to the <CODE>*commands*</CODE> table a command +<name>: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(lambda (<name> <rdb>) <expression1> <expression2> <small>...</small>) +</pre></td></tr></table><P> + +</P> +</DL> +<P> + +<A NAME="IDX985"></A> +</P> +<DL> +<DT><U>Syntax:</U> <B>define-table</B> <I><name> <descriptor-name> <descriptor-name> <rows></I> +<DD><A NAME="IDX986"></A> +<DT><U>Syntax:</U> <B>define-table</B> <I><name> <primary-key-fields> <other-fields> <rows></I> +<DD><P> + +where <name> is the table name, <descriptor-name> is the symbol +name of a descriptor table, <primary-key-fields> and +<other-fields> describe the primary keys and other fields +respectively, and <rows> is a list of data rows to be added to the +table. +</P> +<P> + +<primary-key-fields> and <other-fields> are lists of field +descriptors of the form: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(<column-name> <domain>) +</pre></td></tr></table>or +<TABLE><tr><td> </td><td class=example><pre>(<column-name> <domain> <column-integrity-rule>) +</pre></td></tr></table><P> + +where <column-name> is the column name, <domain> is the domain +of the column, and <column-integrity-rule> is an expression whose +value is a procedure of one argument (which returns <CODE>#f</CODE> to signal +an error). +</P> +<P> + +If <domain> is not a defined domain name and it matches the name of +this table or an already defined (in one of <VAR>spec-0</VAR> <small>...</small>) single +key field table, a foreign-key domain will be created for it. +</P> +<P> + +</P> +</DL> +<P> + +<A NAME="Within-database Example"></A> +<HR SIZE="6"> +<A NAME="SEC163"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC162"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC164"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC162"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.1.5.1 Within-database Example </H4> +<!--docid::SEC163::--> +<P> + +Here is an example of <CODE>within-database</CODE> macros: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(require 'within-database) + +(define my-rdb + (add-command-tables + (create-database "foo.db" 'alist-table))) + +(within-database my-rdb + (define-command (*initialize* rdb) + "Print Welcome" + (display "Welcome") + (newline) + rdb) + (define-command (without-documentation rdb) + (display "without-documentation called") + (newline)) + (define-table (processor-family + ((family atom)) + ((also-ran processor-family))) + (m68000 #f) + (m68030 m68000) + (i386 i8086) + (i8086 #f) + (powerpc #f)) + (define-table (platform + ((name symbol)) + ((processor processor-family) + (os symbol) + (compiler symbol))) + (aix powerpc aix -) + ;; ... + (amiga-aztec m68000 amiga aztec) + (amiga-sas/c-5.10 m68000 amiga sas/c) + (atari-st-gcc m68000 atari gcc) + ;; ... + (watcom-9.0 i386 ms-dos watcom)) + (define-command (get-processor rdb) + "Get processor for given platform." + (((rdb 'open-table) 'platform #f) 'get 'processor))) + +(close-database my-rdb) + +(set! my-rdb (open-command-database! "foo.db")) +-| +Welcome + +(my-rdb 'without-documentation) +-| +without-documentation called + +((my-rdb 'get-processor) 'amiga-sas/c-5.10) +=> m68000 + +(close-database my-rdb) +</pre></td></tr></table><P> + +<A NAME="Database Browser"></A> +<HR SIZE="6"> +<A NAME="SEC164"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC163"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC165"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC141"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 6.1.6 Database Browser </H3> +<!--docid::SEC164::--> +<P> + +(require 'database-browse) +</P> +<P> + +<A NAME="IDX987"></A> +</P> +<DL> +<DT><U>Procedure:</U> <B>browse</B> <I>database</I> +<DD><P> + +Prints the names of all the tables in <VAR>database</VAR> and sets browse's +default to <VAR>database</VAR>. +</P> +<P> + +<A NAME="IDX988"></A> +<DT><U>Procedure:</U> <B>browse</B> +<DD></P> +<P> + +Prints the names of all the tables in the default database. +</P> +<P> + +<A NAME="IDX989"></A> +<DT><U>Procedure:</U> <B>browse</B> <I>table-name</I> +<DD></P> +<P> + +For each record of the table named by the symbol <VAR>table-name</VAR>, +prints a line composed of all the field values. +</P> +<P> + +<A NAME="IDX990"></A> +<DT><U>Procedure:</U> <B>browse</B> <I>pathname</I> +<DD></P> +<P> + +Opens the database named by the string <VAR>pathname</VAR>, prints the names +of all its tables, and sets browse's default to the database. +</P> +<P> + +<A NAME="IDX991"></A> +<DT><U>Procedure:</U> <B>browse</B> <I>database table-name</I> +<DD></P> +<P> + +Sets browse's default to <VAR>database</VAR> and prints the records of the +table named by the symbol <VAR>table-name</VAR>. +</P> +<P> + +<A NAME="IDX992"></A> +<DT><U>Procedure:</U> <B>browse</B> <I>pathname table-name</I> +<DD></P> +<P> + +Opens the database named by the string <VAR>pathname</VAR> and sets browse's +default to it; <CODE>browse</CODE> prints the records of the table named by +the symbol <VAR>table-name</VAR>. +</P> +<P> + +</P> +</DL> +<P> + +<A NAME="Relational Infrastructure"></A> +<HR SIZE="6"> +<A NAME="SEC165"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC164"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC166"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H2> 6.2 Relational Infrastructure </H2> +<!--docid::SEC165::--> +<P> + +<TABLE BORDER="0" CELLSPACING="0"> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC166">6.2.1 Base Table</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC175">6.2.2 Catalog Representation</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC176">6.2.3 Relational Database Objects</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC177">6.2.4 Database Operations</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +</TABLE> +<P> + +<A NAME="Base Table"></A> +<HR SIZE="6"> +<A NAME="SEC166"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC165"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC167"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC165"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 6.2.1 Base Table </H3> +<!--docid::SEC166::--> +<P> + +<A NAME="IDX993"></A> +A <EM>base-table</EM> is the primitive database layer upon which SLIB +relational databases are built. At the minimum, it must support the +types integer, symbol, string, and boolean. The base-table may restrict +the size of integers, symbols, and strings it supports. +</P> +<P> + +A base table implementation is available as the value of the identifier +naming it (eg. <VAR>alist-table</VAR>) after requiring the symbol of that +name. +</P> +<P> + +<A NAME="IDX994"></A> +</P> +<DL> +<DT><U>Feature:</U> <B>alist-table</B> +<DD><CODE>(require 'alist-table)</CODE> +<A NAME="IDX995"></A> +<P> + +Association-list base tables support all Scheme types and are suitable +for small databases. In order to be retrieved after being written to a +file, the data stored should include only objects which are readable and +writeable in the Scheme implementation. +</P> +<P> + +The <EM>alist-table</EM> base-table implementation is included in the +SLIB distribution. +</P> +</DL> +<P> + +<EM>WB</EM> is a B-tree database package with SCM interfaces. Being +disk-based, WB databases readily store and access hundreds of +megabytes of data. WB comes with two base-table embeddings. +</P> +<P> + +<A NAME="IDX996"></A> +</P> +<DL> +<DT><U>Feature:</U> <B>wb-table</B> +<DD><CODE>(require 'wb-table)</CODE> +<A NAME="IDX997"></A> +<P> + +<A NAME="IDX998"></A> +<CODE>wb-table</CODE> supports scheme expressions for keys and values whose +text representations are less than 255 characters in length. +See section `wb-table' in <CITE>WB</CITE>. +</P> +</DL> +<P> + +<A NAME="IDX999"></A> +</P> +<DL> +<DT><U>Feature:</U> <B>rwb-isam</B> +<DD><CODE>(require 'rwb-isam)</CODE> +<A NAME="IDX1000"></A> +<P> + +<EM>rwb-isam</EM> is a sophisticated base-table implementation built on +WB and SCM which uses binary numerical formats for key and non-key +fields. It supports IEEE floating-point and fixed-precision integer +keys with the correct numerical collation order. +</P> +</DL> +<P> + +This rest of this section documents the interface for a base table +implementation from which the <A HREF="slib_6.html#SEC141">6.1 Relational Database</A> package +constructs a Relational system. It will be of interest primarily to +those wishing to port or write new base-table implementations. +</P> +<P> + +<A NAME="IDX1001"></A> +</P> +<DL> +<DT><U>Variable:</U> <B>*base-table-implementations*</B> +<DD>To support automatic dispatch for <CODE>open-database</CODE>, each base-table +module adds an association to <VAR>*base-table-implementations*</VAR> when +loaded. This association is the list of the base-table symbol and the +value returned by <CODE>(make-relational-system <VAR>base-table</VAR>)</CODE>. +</DL> +<P> + +<TABLE BORDER="0" CELLSPACING="0"> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC167">6.2.1.1 The Base</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC168">6.2.1.2 Base Tables</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC169">6.2.1.3 Base Field Types</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC170">6.2.1.4 Composite Keys</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC171">6.2.1.5 Base Record Operations</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC172">6.2.1.6 Match Keys</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC173">6.2.1.7 Aggregate Base Operations</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC174">6.2.1.8 Base ISAM Operations</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +</TABLE> +<P> + +<A NAME="The Base"></A> +<HR SIZE="6"> +<A NAME="SEC167"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC166"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC168"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC166"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.2.1.1 The Base </H4> +<!--docid::SEC167::--> +<P> + +All of these functions are accessed through a single procedure by +calling that procedure with the symbol name of the operation. A +procedure will be returned if that operation is supported and <CODE>#f</CODE> +otherwise. For example: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(require 'alist-table) +<A NAME="IDX1002"></A><A NAME="IDX1003"></A>(define my-base (alist-table 'make-base)) +my-base => *a procedure* +(define foo (alist-table 'foo)) +foo => #f +</pre></td></tr></table><P> + +<A NAME="IDX1004"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>make-base</B> <I>filename key-dimension column-types</I> +<DD>Returns a new, open, low-level database (collection of tables) +associated with <VAR>filename</VAR>. This returned database has an empty +table associated with <VAR>catalog-id</VAR>. The positive integer +<VAR>key-dimension</VAR> is the number of keys composed to make a +<VAR>primary-key</VAR> for the catalog table. The list of symbols +<VAR>column-types</VAR> describes the types of each column for that table. +If the database cannot be created as specified, <CODE>#f</CODE> is returned. +<P> + +Calling the <CODE>close-base</CODE> method on this database and possibly other +operations will cause <VAR>filename</VAR> to be written to. If +<VAR>filename</VAR> is <CODE>#f</CODE> a temporary, non-disk based database will be +created if such can be supported by the base table implelentation. +</P> +</DL> +<P> + +<A NAME="IDX1005"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>open-base</B> <I>filename mutable</I> +<DD>Returns an open low-level database associated with <VAR>filename</VAR>. If +<VAR>mutable</VAR> is <CODE>#t</CODE>, this database will have methods capable of +effecting change to the database. If <VAR>mutable</VAR> is <CODE>#f</CODE>, only +methods for inquiring the database will be available. If the database +cannot be opened as specified <CODE>#f</CODE> is returned. +<P> + +Calling the <CODE>close-base</CODE> (and possibly other) method on a +<VAR>mutable</VAR> database will cause <VAR>filename</VAR> to be written to. +</P> +</DL> +<P> + +<A NAME="IDX1006"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>write-base</B> <I>lldb filename</I> +<DD>Causes the low-level database <VAR>lldb</VAR> to be written to +<VAR>filename</VAR>. If the write is successful, also causes <VAR>lldb</VAR> to +henceforth be associated with <VAR>filename</VAR>. Calling the +<CODE>close-database</CODE> (and possibly other) method on <VAR>lldb</VAR> may +cause <VAR>filename</VAR> to be written to. If <VAR>filename</VAR> is <CODE>#f</CODE> +this database will be changed to a temporary, non-disk based database if +such can be supported by the underlying base table implelentation. If +the operations completed successfully, <CODE>#t</CODE> is returned. +Otherwise, <CODE>#f</CODE> is returned. +</DL> +<P> + +<A NAME="IDX1007"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>sync-base</B> <I>lldb</I> +<DD>Causes the file associated with the low-level database <VAR>lldb</VAR> to be +updated to reflect its current state. If the associated filename is +<CODE>#f</CODE>, no action is taken and <CODE>#f</CODE> is returned. If this +operation completes successfully, <CODE>#t</CODE> is returned. Otherwise, +<CODE>#f</CODE> is returned. +</DL> +<P> + +<A NAME="IDX1008"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>close-base</B> <I>lldb</I> +<DD>Causes the low-level database <VAR>lldb</VAR> to be written to its associated +file (if any). If the write is successful, subsequent operations to +<VAR>lldb</VAR> will signal an error. If the operations complete +successfully, <CODE>#t</CODE> is returned. Otherwise, <CODE>#f</CODE> is returned. +</DL> +<P> + +<A NAME="Base Tables"></A> +<HR SIZE="6"> +<A NAME="SEC168"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC167"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC169"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC166"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.2.1.2 Base Tables </H4> +<!--docid::SEC168::--> +<P> + +<A NAME="IDX1009"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>make-table</B> <I>lldb key-dimension column-types</I> +<DD>Returns the ordinal <VAR>base-id</VAR> for a new base table, otherwise +returns <CODE>#f</CODE>. The base table can then be opened using +<CODE>(open-table <VAR>lldb</VAR> <VAR>base-id</VAR>)</CODE>. The positive integer +<VAR>key-dimension</VAR> is the number of keys composed to make a +<VAR>primary-key</VAR> for this table. The list of symbols +<VAR>column-types</VAR> describes the types of each column. +</DL> +<P> + +<A NAME="IDX1010"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>open-table</B> <I>lldb base-id key-dimension column-types</I> +<DD>Returns a <VAR>handle</VAR> for an existing base table in the low-level +database <VAR>lldb</VAR> if that table exists and can be opened in the mode +indicated by <VAR>mutable</VAR>, otherwise returns <CODE>#f</CODE>. +<P> + +As with <CODE>make-table</CODE>, the positive integer <VAR>key-dimension</VAR> is +the number of keys composed to make a <VAR>primary-key</VAR> for this table. +The list of symbols <VAR>column-types</VAR> describes the types of each +column. +</P> +</DL> +<P> + +<A NAME="IDX1011"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>kill-table</B> <I>lldb base-id key-dimension column-types</I> +<DD>Returns <CODE>#t</CODE> if the base table associated with <VAR>base-id</VAR> was +removed from the low level database <VAR>lldb</VAR>, and <CODE>#f</CODE> otherwise. +</DL> +<P> + +<A NAME="IDX1012"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>catalog-id</B> +<DD>A constant <VAR>base-id</VAR> ordinal suitable for passing as a parameter to +<CODE>open-table</CODE>. <VAR>catalog-id</VAR> will be used as the base table for +the system catalog. +</DL> +<P> + +<A NAME="Base Field Types"></A> +<HR SIZE="6"> +<A NAME="SEC169"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC168"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC170"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC166"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.2.1.3 Base Field Types </H4> +<!--docid::SEC169::--> +<P> + +<A NAME="IDX1013"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>supported-type?</B> <I>symbol</I> +<DD>Returns <CODE>#t</CODE> if <VAR>symbol</VAR> names a type allowed as a column +value by the implementation, and <CODE>#f</CODE> otherwise. At a minimum, +an implementation must support the types <CODE>integer</CODE>, +<CODE>ordinal</CODE>, <CODE>symbol</CODE>, <CODE>string</CODE>, and <CODE>boolean</CODE>. +</DL> +<P> + +<A NAME="IDX1014"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>supported-key-type?</B> <I>symbol</I> +<DD>Returns <CODE>#t</CODE> if <VAR>symbol</VAR> names a type allowed as a key value +by the implementation, and <CODE>#f</CODE> otherwise. At a minimum, an +implementation must support the types <CODE>ordinal</CODE>, and +<CODE>symbol</CODE>. +</DL> +<P> + +An <EM>ordinal</EM> is an exact positive integer. The other types are +standard Scheme. +</P> +<P> + +<A NAME="Composite Keys"></A> +<HR SIZE="6"> +<A NAME="SEC170"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC169"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC171"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC166"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.2.1.4 Composite Keys </H4> +<!--docid::SEC170::--> +<P> + +<A NAME="IDX1015"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>make-keyifier-1</B> <I>type</I> +<DD>Returns a procedure which accepts a single argument which must be of +type <VAR>type</VAR>. This returned procedure returns an object suitable for +being a <VAR>key</VAR> argument in the functions whose descriptions follow. +<P> + +Any 2 arguments of the supported type passed to the returned function +which are not <CODE>equal?</CODE> must result in returned values which are not +<CODE>equal?</CODE>. +</P> +</DL> +<P> + +<A NAME="IDX1016"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>make-list-keyifier</B> <I>key-dimension types</I> +<DD>The list of symbols <VAR>types</VAR> must have at least <VAR>key-dimension</VAR> +elements. Returns a procedure which accepts a list of length +<VAR>key-dimension</VAR> and whose types must corresopond to the types named +by <VAR>types</VAR>. This returned procedure combines the elements of its +list argument into an object suitable for being a <VAR>key</VAR> argument in +the functions whose descriptions follow. +<P> + +Any 2 lists of supported types (which must at least include symbols and +non-negative integers) passed to the returned function which are not +<CODE>equal?</CODE> must result in returned values which are not +<CODE>equal?</CODE>. +</P> +</DL> +<P> + +<A NAME="IDX1017"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>make-key-extractor</B> <I>key-dimension types column-number</I> +<DD>Returns a procedure which accepts objects produced by application of the +result of <CODE>(make-list-keyifier <VAR>key-dimension</VAR> <VAR>types</VAR>)</CODE>. +This procedure returns a <VAR>key</VAR> which is <CODE>equal?</CODE> to the +<VAR>column-number</VAR>th element of the list which was passed to create +<VAR>composite-key</VAR>. The list <VAR>types</VAR> must have at least +<VAR>key-dimension</VAR> elements. +</DL> +<P> + +<A NAME="IDX1018"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>make-key->list</B> <I>key-dimension types</I> +<DD>Returns a procedure which accepts objects produced by application of +the result of <CODE>(make-list-keyifier <VAR>key-dimension</VAR> +<VAR>types</VAR>)</CODE>. This procedure returns a list of <VAR>key</VAR>s which are +elementwise <CODE>equal?</CODE> to the list which was passed to create +<VAR>composite-key</VAR>. +</DL> +<P> + +<A NAME="Base Record Operations"></A> +<HR SIZE="6"> +<A NAME="SEC171"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC170"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC172"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC166"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.2.1.5 Base Record Operations </H4> +<!--docid::SEC171::--> +<P> + +In the following functions, the <VAR>key</VAR> argument can always be assumed +to be the value returned by a call to a <EM>keyify</EM> routine. +</P> +<P> + +<A NAME="IDX1019"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>present?</B> <I>handle key</I> +<DD>Returns a non-<CODE>#f</CODE> value if there is a row associated with +<VAR>key</VAR> in the table opened in <VAR>handle</VAR> and <CODE>#f</CODE> otherwise. +</DL> +<P> + +<A NAME="IDX1020"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>make-getter</B> <I>key-dimension types</I> +<DD>Returns a procedure which takes arguments <VAR>handle</VAR> and <VAR>key</VAR>. +This procedure returns a list of the non-primary values of the relation +(in the base table opened in <VAR>handle</VAR>) whose primary key is +<VAR>key</VAR> if it exists, and <CODE>#f</CODE> otherwise. +</DL> +<P> + +<CODE>make-getter-1</CODE> is a new operation. The relational-database +module works with older base-table implementations by using +<CODE>make-getter</CODE>. +</P> +<P> + +<A NAME="IDX1021"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>make-getter-1</B> <I>key-dimension types index</I> +<DD>Returns a procedure which takes arguments <VAR>handle</VAR> and <VAR>key</VAR>. +This procedure returns the value of the <VAR>index</VAR>th field (in the +base table opened in <VAR>handle</VAR>) whose primary key is <VAR>key</VAR> if +it exists, and <CODE>#f</CODE> otherwise. +<P> + +<VAR>index</VAR> must be larger than <VAR>key-dimension</VAR>. +</P> +</DL> +<P> + +<A NAME="IDX1022"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>make-putter</B> <I>key-dimension types</I> +<DD>Returns a procedure which takes arguments <VAR>handle</VAR> and <VAR>key</VAR> and +<VAR>value-list</VAR>. This procedure associates the primary key <VAR>key</VAR> +with the values in <VAR>value-list</VAR> (in the base table opened in +<VAR>handle</VAR>) and returns an unspecified value. +</DL> +<P> + +<A NAME="IDX1023"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>delete</B> <I>handle key</I> +<DD>Removes the row associated with <VAR>key</VAR> from the table opened in +<VAR>handle</VAR>. An unspecified value is returned. +</DL> +<P> + +<A NAME="Match Keys"></A> +<HR SIZE="6"> +<A NAME="SEC172"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC171"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC173"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC166"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.2.1.6 Match Keys </H4> +<!--docid::SEC172::--> +<P> + +<A NAME="IDX1024"></A> +<A NAME="IDX1025"></A> +<A NAME="IDX1026"></A> +A <VAR>match-keys</VAR> argument is a list of length equal to +the number of primary keys. The <VAR>match-keys</VAR> restrict the actions +of the table command to those records whose primary keys all satisfy the +corresponding element of the <VAR>match-keys</VAR> list. The elements and +their actions are: +</P> +<P> + +<BLOCKQUOTE> +<DL COMPACT> +<DT><CODE>#f</CODE> +<DD>The false value matches any key in the corresponding position. +<DT>an object of type procedure +<DD>This procedure must take a single argument, the key in the corresponding +position. Any key for which the procedure returns a non-false value is +a match; Any key for which the procedure returns a <CODE>#f</CODE> is not. +<DT>other values +<DD>Any other value matches only those keys <CODE>equal?</CODE> to it. +</DL> +</BLOCKQUOTE> +<P> + +<A NAME="Aggregate Base Operations"></A> +<HR SIZE="6"> +<A NAME="SEC173"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC172"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC174"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC166"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.2.1.7 Aggregate Base Operations </H4> +<!--docid::SEC173::--> +<P> + +The <VAR>key-dimension</VAR> and <VAR>column-types</VAR> arguments are needed to +decode the composite-keys for matching with <VAR>match-keys</VAR>. +</P> +<P> + +<A NAME="IDX1027"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>delete*</B> <I>handle key-dimension column-types match-keys</I> +<DD>Removes all rows which satisfy <VAR>match-keys</VAR> from the table opened in +<VAR>handle</VAR>. An unspecified value is returned. +</DL> +<P> + +<A NAME="IDX1028"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>for-each-key</B> <I>handle procedure key-dimension column-types match-keys</I> +<DD>Calls <VAR>procedure</VAR> once with each <VAR>key</VAR> in the table opened in +<VAR>handle</VAR> which satisfy <VAR>match-keys</VAR> in an unspecified order. +An unspecified value is returned. +</DL> +<P> + +<A NAME="IDX1029"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>map-key</B> <I>handle procedure key-dimension column-types match-keys</I> +<DD>Returns a list of the values returned by calling <VAR>procedure</VAR> once +with each <VAR>key</VAR> in the table opened in <VAR>handle</VAR> which satisfy +<VAR>match-keys</VAR> in an unspecified order. +</DL> +<P> + +<A NAME="Base ISAM Operations"></A> +<HR SIZE="6"> +<A NAME="SEC174"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC173"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC175"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC166"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 6.2.1.8 Base ISAM Operations </H4> +<!--docid::SEC174::--> +<P> + +These operations are optional for a Base-Table implementation. +</P> +<P> + +<A NAME="IDX1030"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>ordered-for-each-key</B> <I>handle procedure key-dimension column-types match-keys</I> +<DD>Calls <VAR>procedure</VAR> once with each <VAR>key</VAR> in the table opened in +<VAR>handle</VAR> which satisfy <VAR>match-keys</VAR> in the natural order for +the types of the primary key fields of that table. An unspecified value +is returned. +</DL> +<P> + +<A NAME="IDX1031"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>make-nexter</B> <I>handle key-dimension column-types index</I> +<DD>Returns a procedure of arguments <VAR>key1</VAR> <VAR>key2</VAR> <small>...</small> which +returns the key-list identifying the lowest record higher than +<VAR>key1</VAR> <VAR>key2</VAR> <small>...</small> which is stored in the base-table and +which differs in column <VAR>index</VAR> or a lower indexed key; or false +if no higher record is present. +</DL> +<P> + +<A NAME="IDX1032"></A> +</P> +<DL> +<DT><U>Operation:</U> base-table <B>make-prever</B> <I>handle key-dimension column-types index</I> +<DD>Returns a procedure of arguments <VAR>key1</VAR> <VAR>key2</VAR> <small>...</small> which +returns the key-list identifying the highest record less than +<VAR>key1</VAR> <VAR>key2</VAR> <small>...</small> which is stored in the base-table and +which differs in column <VAR>index</VAR> or a lower indexed key; or false +if no higher record is present. +</DL> +<P> + +<A NAME="Catalog Representation"></A> +<HR SIZE="6"> +<A NAME="SEC175"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC174"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC176"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC165"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 6.2.2 Catalog Representation </H3> +<!--docid::SEC175::--> +<P> + +Each database (in an implementation) has a <EM>system catalog</EM> which +describes all the user accessible tables in that database (including +itself). +</P> +<P> + +The system catalog base table has the following fields. <CODE>PRI</CODE> +indicates a primary key for that table. +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>PRI table-name + column-limit the highest column number + coltab-name descriptor table name + bastab-id data base table identifier + user-integrity-rule + view-procedure A scheme thunk which, when called, + produces a handle for the view. coltab + and bastab are specified if and only if + view-procedure is not. +</pre></td></tr></table><P> + +Descriptors for base tables (not views) are tables (pointed to by +system catalog). Descriptor (base) tables have the fields: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>PRI column-number sequential integers from 1 + primary-key? boolean TRUE for primary key components + column-name + column-integrity-rule + domain-name +</pre></td></tr></table><P> + +A <EM>primary key</EM> is any column marked as <CODE>primary-key?</CODE> in the +corresponding descriptor table. All the <CODE>primary-key?</CODE> columns +must have lower column numbers than any non-<CODE>primary-key?</CODE> columns. +Every table must have at least one primary key. Primary keys must be +sufficient to distinguish all rows from each other in the table. All of +the system defined tables have a single primary key. +</P> +<P> + +A <EM>domain</EM> is a category describing the allowable values to occur in +a column. It is described by a (base) table with the fields: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>PRI domain-name + foreign-table + domain-integrity-rule + type-id + type-param +</pre></td></tr></table><P> + +The <EM>type-id</EM> field value is a symbol. This symbol may be used by +the underlying base table implementation in storing that field. +</P> +<P> + +If the <CODE>foreign-table</CODE> field is non-<CODE>#f</CODE> then that field names +a table from the catalog. The values for that domain must match a +primary key of the table referenced by the <VAR>type-param</VAR> (or +<CODE>#f</CODE>, if allowed). This package currently does not support +composite foreign-keys. +</P> +<P> + +The types for which support is planned are: +<TABLE><tr><td> </td><td class=example><pre> atom + symbol + string [<length>] + number [<base>] + money <currency> + date-time + boolean + + foreign-key <table-name> + expression + virtual <expression> +</pre></td></tr></table><P> + +<A NAME="Relational Database Objects"></A> +<HR SIZE="6"> +<A NAME="SEC176"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC175"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC177"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC165"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 6.2.3 Relational Database Objects </H3> +<!--docid::SEC176::--> +<P> + +This object-oriented interface is deprecated for typical database +applications; <A HREF="slib_6.html#SEC142">6.1.1 Using Databases</A> provides an application programmer +interface which is easier to understand and use. +</P> +<P> + +<A NAME="IDX1033"></A> +</P> +<DL> +<DT><U>Function:</U> <B>make-relational-system</B> <I>base-table-implementation</I> +<DD><P> + +Returns a procedure implementing a relational database using the +<VAR>base-table-implementation</VAR>. +</P> +<P> + +All of the operations of a base table implementation are accessed +through a procedure defined by <CODE>require</CODE>ing that implementation. +Similarly, all of the operations of the relational database +implementation are accessed through the procedure returned by +<CODE>make-relational-system</CODE>. For instance, a new relational database +could be created from the procedure returned by +<CODE>make-relational-system</CODE> by: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(require 'alist-table) +<A NAME="IDX1034"></A>(define relational-alist-system + (make-relational-system alist-table)) +(define create-alist-database + (relational-alist-system 'create-database)) +(define my-database + (create-alist-database "mydata.db")) +</pre></td></tr></table></DL> +<P> + +What follows are the descriptions of the methods available from +relational system returned by a call to <CODE>make-relational-system</CODE>. +</P> +<P> + +<A NAME="IDX1035"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-system <B>create-database</B> <I>filename</I> +<DD><P> + +Returns an open, nearly empty relational database associated with +<VAR>filename</VAR>. The only tables defined are the system catalog and +domain table. Calling the <CODE>close-database</CODE> method on this database +and possibly other operations will cause <VAR>filename</VAR> to be written +to. If <VAR>filename</VAR> is <CODE>#f</CODE> a temporary, non-disk based database +will be created if such can be supported by the underlying base table +implelentation. If the database cannot be created as specified +<CODE>#f</CODE> is returned. For the fields and layout of descriptor tables, +<A HREF="slib_6.html#SEC175">6.2.2 Catalog Representation</A> +</P> +</DL> +<P> + +<A NAME="IDX1036"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-system <B>open-database</B> <I>filename mutable?</I> +<DD><P> + +Returns an open relational database associated with <VAR>filename</VAR>. If +<VAR>mutable?</VAR> is <CODE>#t</CODE>, this database will have methods capable of +effecting change to the database. If <VAR>mutable?</VAR> is <CODE>#f</CODE>, only +methods for inquiring the database will be available. Calling the +<CODE>close-database</CODE> (and possibly other) method on a <VAR>mutable?</VAR> +database will cause <VAR>filename</VAR> to be written to. If the database +cannot be opened as specified <CODE>#f</CODE> is returned. +</P> +</DL> +<P> + +<A NAME="Database Operations"></A> +<HR SIZE="6"> +<A NAME="SEC177"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC176"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC178"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC165"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 6.2.4 Database Operations </H3> +<!--docid::SEC177::--> +<P> + +This object-oriented interface is deprecated for typical database +applications; <A HREF="slib_6.html#SEC142">6.1.1 Using Databases</A> provides an application programmer +interface which is easier to understand and use. +</P> +<P> + +These are the descriptions of the methods available from an open +relational database. A method is retrieved from a database by calling +the database with the symbol name of the operation. For example: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(define my-database + (create-alist-database "mydata.db")) +(define telephone-table-desc + ((my-database 'create-table) 'telephone-table-desc)) +</pre></td></tr></table><P> + +<A NAME="IDX1037"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-database <B>close-database</B> +<DD>Causes the relational database to be written to its associated file (if +any). If the write is successful, subsequent operations to this +database will signal an error. If the operations completed +successfully, <CODE>#t</CODE> is returned. Otherwise, <CODE>#f</CODE> is returned. +</DL> +<P> + +<A NAME="IDX1038"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-database <B>write-database</B> <I>filename</I> +<DD>Causes the relational database to be written to <VAR>filename</VAR>. If the +write is successful, also causes the database to henceforth be +associated with <VAR>filename</VAR>. Calling the <CODE>close-database</CODE> (and +possibly other) method on this database will cause <VAR>filename</VAR> to be +written to. If <VAR>filename</VAR> is <CODE>#f</CODE> this database will be +changed to a temporary, non-disk based database if such can be supported +by the underlying base table implelentation. If the operations +completed successfully, <CODE>#t</CODE> is returned. Otherwise, <CODE>#f</CODE> is +returned. +</DL> +<P> + +<A NAME="IDX1039"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-database <B>sync-database</B> +<DD>Causes any pending updates to the database file to be written out. If +the operations completed successfully, <CODE>#t</CODE> is returned. +Otherwise, <CODE>#f</CODE> is returned. +</DL> +<P> + +<A NAME="IDX1040"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-database <B>solidify-database</B> +<DD>Causes any pending updates to the database file to be written out. If +the writes completed successfully, then the database is changed to be +immutable and <CODE>#t</CODE> is returned. Otherwise, <CODE>#f</CODE> is returned. +</DL> +<P> + +<A NAME="IDX1041"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-database <B>table-exists?</B> <I>table-name</I> +<DD>Returns <CODE>#t</CODE> if <VAR>table-name</VAR> exists in the system catalog, +otherwise returns <CODE>#f</CODE>. +</DL> +<P> + +<A NAME="IDX1042"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-database <B>open-table</B> <I>table-name mutable?</I> +<DD>Returns a <EM>methods</EM> procedure for an existing relational table in +this database if it exists and can be opened in the mode indicated by +<VAR>mutable?</VAR>, otherwise returns <CODE>#f</CODE>. +</DL> +<P> + +These methods will be present only in mutable databases. +</P> +<P> + +<A NAME="IDX1043"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-database <B>delete-table</B> <I>table-name</I> +<DD>Removes and returns the <VAR>table-name</VAR> row from the system catalog if +the table or view associated with <VAR>table-name</VAR> gets removed from the +database, and <CODE>#f</CODE> otherwise. +</DL> +<P> + +<A NAME="IDX1044"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-database <B>create-table</B> <I>table-desc-name</I> +<DD>Returns a methods procedure for a new (open) relational table for +describing the columns of a new base table in this database, otherwise +returns <CODE>#f</CODE>. For the fields and layout of descriptor tables, +See section <A HREF="slib_6.html#SEC175">6.2.2 Catalog Representation</A>. +<P> + +<A NAME="IDX1045"></A> +<DT><U>Operation:</U> relational-database <B>create-table</B> <I>table-name table-desc-name</I> +<DD>Returns a methods procedure for a new (open) relational table with +columns as described by <VAR>table-desc-name</VAR>, otherwise returns +<CODE>#f</CODE>. +</P> +</DL> +<P> + +<A NAME="IDX1046"></A> +</P> +<DL> +<DT><U>Operation:</U> relational-database <B>create-view</B> <I>??</I> +<DD><A NAME="IDX1047"></A> +<DT><U>Operation:</U> relational-database <B>project-table</B> <I>??</I> +<DD><A NAME="IDX1048"></A> +<DT><U>Operation:</U> relational-database <B>restrict-table</B> <I>??</I> +<DD><A NAME="IDX1049"></A> +<DT><U>Operation:</U> relational-database <B>cart-prod-tables</B> <I>??</I> +<DD>Not yet implemented. +</DL> +<P> + +<A NAME="Weight-Balanced Trees"></A> +<HR SIZE="6"> +<A NAME="SEC178"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC177"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC179"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H2> 6.3 Weight-Balanced Trees </H2> +<!--docid::SEC178::--> +<P> + +<CODE>(require 'wt-tree)</CODE> +<A NAME="IDX1050"></A> +</P> +<P> + +<A NAME="IDX1051"></A> +<A NAME="IDX1052"></A> +<A NAME="IDX1053"></A> +<A NAME="IDX1054"></A> +Balanced binary trees are a useful data structure for maintaining large +sets of ordered objects or sets of associations whose keys are ordered. +MIT Scheme has an comprehensive implementation of weight-balanced binary +trees which has several advantages over the other data structures for +large aggregates: +</P> +<P> + +<UL> +<LI> +In addition to the usual element-level operations like insertion, +deletion and lookup, there is a full complement of collection-level +operations, like set intersection, set union and subset test, all of +which are implemented with good orders of growth in time and space. +This makes weight balanced trees ideal for rapid prototyping of +functionally derived specifications. +<P> + +</P> +<LI> +An element in a tree may be indexed by its position under the ordering +of the keys, and the ordinal position of an element may be determined, +both with reasonable efficiency. +<P> + +</P> +<LI> +Operations to find and remove minimum element make weight balanced trees +simple to use for priority queues. +<P> + +</P> +<LI> +The implementation is <EM>functional</EM> rather than <EM>imperative</EM>. +This means that operations like `inserting' an association in a tree do +not destroy the old tree, in much the same way that <CODE>(+ 1 x)</CODE> +modifies neither the constant 1 nor the value bound to <CODE>x</CODE>. The +trees are referentially transparent thus the programmer need not worry +about copying the trees. Referential transparency allows space +efficiency to be achieved by sharing subtrees. +<P> + +</UL> +<P> + +These features make weight-balanced trees suitable for a wide range of +applications, especially those that +require large numbers of sets or discrete maps. Applications that have +a few global databases and/or concentrate on element-level operations like +insertion and lookup are probably better off using hash-tables or +red-black trees. +</P> +<P> + +The <EM>size</EM> of a tree is the number of associations that it +contains. Weight balanced binary trees are balanced to keep the sizes +of the subtrees of each node within a constant factor of each other. +This ensures logarithmic times for single-path operations (like lookup +and insertion). A weight balanced tree takes space that is proportional +to the number of associations in the tree. For the current +implementation, the constant of proportionality is six words per +association. +</P> +<P> + +<A NAME="IDX1055"></A> +<A NAME="IDX1056"></A> +<A NAME="IDX1057"></A> +<A NAME="IDX1058"></A> +Weight balanced trees can be used as an implementation for either +discrete sets or discrete maps (associations). Sets are implemented by +ignoring the datum that is associated with the key. Under this scheme +if an associations exists in the tree this indicates that the key of the +association is a member of the set. Typically a value such as +<CODE>()</CODE>, <CODE>#t</CODE> or <CODE>#f</CODE> is associated with the key. +</P> +<P> + +Many operations can be viewed as computing a result that, depending on +whether the tree arguments are thought of as sets or maps, is known by +two different names. An example is <CODE>wt-tree/member?</CODE>, which, when +regarding the tree argument as a set, computes the set membership +operation, but, when regarding the tree as a discrete map, +<CODE>wt-tree/member?</CODE> is the predicate testing if the map is defined at +an element in its domain. Most names in this package have been chosen +based on interpreting the trees as sets, hence the name +<CODE>wt-tree/member?</CODE> rather than <CODE>wt-tree/defined-at?</CODE>. +</P> +<P> + +<A NAME="IDX1059"></A> +<A NAME="IDX1060"></A> +The weight balanced tree implementation is a run-time-loadable option. +To use weight balanced trees, execute +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(load-option 'wt-tree) +</pre></td></tr></table><A NAME="IDX1061"></A> +<P> + +once before calling any of the procedures defined here. +</P> +<P> + +<TABLE BORDER="0" CELLSPACING="0"> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC179">6.3.1 Construction of Weight-Balanced Trees</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC180">6.3.2 Basic Operations on Weight-Balanced Trees</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC181">6.3.3 Advanced Operations on Weight-Balanced Trees</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_6.html#SEC182">6.3.4 Indexing Operations on Weight-Balanced Trees</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP"></TD></TR> +</TABLE> +<P> + +<A NAME="Construction of Weight-Balanced Trees"></A> +<HR SIZE="6"> +<A NAME="SEC179"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC178"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC180"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC178"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 6.3.1 Construction of Weight-Balanced Trees </H3> +<!--docid::SEC179::--> +<P> + +Binary trees require there to be a total order on the keys used to +arrange the elements in the tree. Weight balanced trees are organized +by <EM>types</EM>, where the type is an object encapsulating the ordering +relation. Creating a tree is a two-stage process. First a tree type +must be created from the predicate which gives the ordering. The tree +type is then used for making trees, either empty or singleton trees or +trees from other aggregate structures like association lists. Once +created, a tree `knows' its type and the type is used to test +compatibility between trees in operations taking two trees. Usually a +small number of tree types are created at the beginning of a program and +used many times throughout the program's execution. +</P> +<P> + +<A NAME="IDX1062"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>make-wt-tree-type</B> <I>key<?</I> +<DD>This procedure creates and returns a new tree type based on the ordering +predicate <VAR>key<?</VAR>. +<VAR>Key<?</VAR> must be a total ordering, having the property that for all +key values <CODE>a</CODE>, <CODE>b</CODE> and <CODE>c</CODE>: +<P> + +<TABLE><tr><td> </td><td class=example><pre>(key<? a a) => #f +(and (key<? a b) (key<? b a)) => #f +(if (and (key<? a b) (key<? b c)) + (key<? a c) + #t) => #t +</pre></td></tr></table><P> + +Two key values are assumed to be equal if neither is less than the other +by <VAR>key<?</VAR>. +</P> +<P> + +Each call to <CODE>make-wt-tree-type</CODE> returns a distinct value, and +trees are only compatible if their tree types are <CODE>eq?</CODE>. A +consequence is that trees that are intended to be used in binary tree +operations must all be created with a tree type originating from the +same call to <CODE>make-wt-tree-type</CODE>. +</P> +</DL> +<P> + +<A NAME="IDX1063"></A> +</P> +<DL> +<DT><U>variable+:</U> <B>number-wt-type</B> +<DD>A standard tree type for trees with numeric keys. <CODE>Number-wt-type</CODE> +could have been defined by +<P> + +<TABLE><tr><td> </td><td class=example><pre>(define number-wt-type (make-wt-tree-type <)) +</pre></td></tr></table></DL> +<P> + +<A NAME="IDX1064"></A> +</P> +<DL> +<DT><U>variable+:</U> <B>string-wt-type</B> +<DD>A standard tree type for trees with string keys. <CODE>String-wt-type</CODE> +could have been defined by +<P> + +<TABLE><tr><td> </td><td class=example><pre>(define string-wt-type (make-wt-tree-type string<?)) +</pre></td></tr></table></DL> +<P> + +<A NAME="IDX1065"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>make-wt-tree</B> <I>wt-tree-type</I> +<DD>This procedure creates and returns a newly allocated weight balanced +tree. The tree is empty, i.e. it contains no associations. +<VAR>Wt-tree-type</VAR> is a weight balanced tree type obtained by calling +<CODE>make-wt-tree-type</CODE>; the returned tree has this type. +</DL> +<P> + +<A NAME="IDX1066"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>singleton-wt-tree</B> <I>wt-tree-type key datum</I> +<DD>This procedure creates and returns a newly allocated weight balanced +tree. The tree contains a single association, that of <VAR>datum</VAR> with +<VAR>key</VAR>. <VAR>Wt-tree-type</VAR> is a weight balanced tree type obtained +by calling <CODE>make-wt-tree-type</CODE>; the returned tree has this type. +</DL> +<P> + +<A NAME="IDX1067"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>alist->wt-tree</B> <I>tree-type alist</I> +<DD>Returns a newly allocated weight-balanced tree that contains the same +associations as <VAR>alist</VAR>. This procedure is equivalent to: +<P> + +<TABLE><tr><td> </td><td class=example><pre>(lambda (type alist) + (let ((tree (make-wt-tree type))) + (for-each (lambda (association) + (wt-tree/add! tree + (car association) + (cdr association))) + alist) + tree)) +</pre></td></tr></table></DL> +<P> + +<A NAME="Basic Operations on Weight-Balanced Trees"></A> +<HR SIZE="6"> +<A NAME="SEC180"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC179"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC181"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC178"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 6.3.2 Basic Operations on Weight-Balanced Trees </H3> +<!--docid::SEC180::--> +<P> + +This section describes the basic tree operations on weight balanced +trees. These operations are the usual tree operations for insertion, +deletion and lookup, some predicates and a procedure for determining the +number of associations in a tree. +</P> +<P> + +<A NAME="IDX1068"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/empty?</B> <I>wt-tree</I> +<DD>Returns <CODE>#t</CODE> if <VAR>wt-tree</VAR> contains no associations, otherwise +returns <CODE>#f</CODE>. +</DL> +<P> + +<A NAME="IDX1069"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/size</B> <I>wt-tree</I> +<DD>Returns the number of associations in <VAR>wt-tree</VAR>, an exact +non-negative integer. This operation takes constant time. +</DL> +<P> + +<A NAME="IDX1070"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/add</B> <I>wt-tree key datum</I> +<DD>Returns a new tree containing all the associations in <VAR>wt-tree</VAR> and +the association of <VAR>datum</VAR> with <VAR>key</VAR>. If <VAR>wt-tree</VAR> already +had an association for <VAR>key</VAR>, the new association overrides the old. +The average and worst-case times required by this operation are +proportional to the logarithm of the number of associations in +<VAR>wt-tree</VAR>. +</DL> +<P> + +<A NAME="IDX1071"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/add!</B> <I>wt-tree key datum</I> +<DD>Associates <VAR>datum</VAR> with <VAR>key</VAR> in <VAR>wt-tree</VAR> and returns an +unspecified value. If <VAR>wt-tree</VAR> already has an association for +<VAR>key</VAR>, that association is replaced. The average and worst-case +times required by this operation are proportional to the logarithm of +the number of associations in <VAR>wt-tree</VAR>. +</DL> +<P> + +<A NAME="IDX1072"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/member?</B> <I>key wt-tree</I> +<DD>Returns <CODE>#t</CODE> if <VAR>wt-tree</VAR> contains an association for +<VAR>key</VAR>, otherwise returns <CODE>#f</CODE>. The average and worst-case +times required by this operation are proportional to the logarithm of +the number of associations in <VAR>wt-tree</VAR>. +</DL> +<P> + +<A NAME="IDX1073"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/lookup</B> <I>wt-tree key default</I> +<DD>Returns the datum associated with <VAR>key</VAR> in <VAR>wt-tree</VAR>. If +<VAR>wt-tree</VAR> doesn't contain an association for <VAR>key</VAR>, +<VAR>default</VAR> is returned. The average and worst-case times required by +this operation are proportional to the logarithm of the number of +associations in <VAR>wt-tree</VAR>. +</DL> +<P> + +<A NAME="IDX1074"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/delete</B> <I>wt-tree key</I> +<DD>Returns a new tree containing all the associations in <VAR>wt-tree</VAR>, +except that if <VAR>wt-tree</VAR> contains an association for <VAR>key</VAR>, it +is removed from the result. The average and worst-case times required +by this operation are proportional to the logarithm of the number of +associations in <VAR>wt-tree</VAR>. +</DL> +<P> + +<A NAME="IDX1075"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/delete!</B> <I>wt-tree key</I> +<DD>If <VAR>wt-tree</VAR> contains an association for <VAR>key</VAR> the association +is removed. Returns an unspecified value. The average and worst-case +times required by this operation are proportional to the logarithm of +the number of associations in <VAR>wt-tree</VAR>. +</DL> +<P> + +<A NAME="Advanced Operations on Weight-Balanced Trees"></A> +<HR SIZE="6"> +<A NAME="SEC181"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC180"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC182"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC178"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 6.3.3 Advanced Operations on Weight-Balanced Trees </H3> +<!--docid::SEC181::--> +<P> + +In the following the <EM>size</EM> of a tree is the number of associations +that the tree contains, and a <EM>smaller</EM> tree contains fewer +associations. +</P> +<P> + +<A NAME="IDX1076"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/split<</B> <I>wt-tree bound</I> +<DD>Returns a new tree containing all and only the associations in +<VAR>wt-tree</VAR> which have a key that is less than <VAR>bound</VAR> in the +ordering relation of the tree type of <VAR>wt-tree</VAR>. The average and +worst-case times required by this operation are proportional to the +logarithm of the size of <VAR>wt-tree</VAR>. +</DL> +<P> + +<A NAME="IDX1077"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/split></B> <I>wt-tree bound</I> +<DD>Returns a new tree containing all and only the associations in +<VAR>wt-tree</VAR> which have a key that is greater than <VAR>bound</VAR> in the +ordering relation of the tree type of <VAR>wt-tree</VAR>. The average and +worst-case times required by this operation are proportional to the +logarithm of size of <VAR>wt-tree</VAR>. +</DL> +<P> + +<A NAME="IDX1078"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/union</B> <I>wt-tree-1 wt-tree-2</I> +<DD>Returns a new tree containing all the associations from both trees. +This operation is asymmetric: when both trees have an association for +the same key, the returned tree associates the datum from <VAR>wt-tree-2</VAR> +with the key. Thus if the trees are viewed as discrete maps then +<CODE>wt-tree/union</CODE> computes the map override of <VAR>wt-tree-1</VAR> by +<VAR>wt-tree-2</VAR>. If the trees are viewed as sets the result is the set +union of the arguments. +The worst-case time required by this operation +is proportional to the sum of the sizes of both trees. +If the minimum key of one tree is greater than the maximum key of +the other tree then the time required is at worst proportional to +the logarithm of the size of the larger tree. +</DL> +<P> + +<A NAME="IDX1079"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/intersection</B> <I>wt-tree-1 wt-tree-2</I> +<DD>Returns a new tree containing all and only those associations from +<VAR>wt-tree-1</VAR> which have keys appearing as the key of an association +in <VAR>wt-tree-2</VAR>. Thus the associated data in the result are those +from <VAR>wt-tree-1</VAR>. If the trees are being used as sets the result is +the set intersection of the arguments. As a discrete map operation, +<CODE>wt-tree/intersection</CODE> computes the domain restriction of +<VAR>wt-tree-1</VAR> to (the domain of) <VAR>wt-tree-2</VAR>. +The time required by this operation is never worse that proportional to +the sum of the sizes of the trees. +</DL> +<P> + +<A NAME="IDX1080"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/difference</B> <I>wt-tree-1 wt-tree-2</I> +<DD>Returns a new tree containing all and only those associations from +<VAR>wt-tree-1</VAR> which have keys that <EM>do not</EM> appear as the key of +an association in <VAR>wt-tree-2</VAR>. If the trees are viewed as sets the +result is the asymmetric set difference of the arguments. As a discrete +map operation, it computes the domain restriction of <VAR>wt-tree-1</VAR> to +the complement of (the domain of) <VAR>wt-tree-2</VAR>. +The time required by this operation is never worse that proportional to +the sum of the sizes of the trees. +</DL> +<P> + +<A NAME="IDX1081"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/subset?</B> <I>wt-tree-1 wt-tree-2</I> +<DD>Returns <CODE>#t</CODE> iff the key of each association in <VAR>wt-tree-1</VAR> is +the key of some association in <VAR>wt-tree-2</VAR>, otherwise returns <CODE>#f</CODE>. +Viewed as a set operation, <CODE>wt-tree/subset?</CODE> is the improper subset +predicate. +A proper subset predicate can be constructed: +<P> + +<TABLE><tr><td> </td><td class=example><pre>(define (proper-subset? s1 s2) + (and (wt-tree/subset? s1 s2) + (< (wt-tree/size s1) (wt-tree/size s2)))) +</pre></td></tr></table><P> + +As a discrete map operation, <CODE>wt-tree/subset?</CODE> is the subset +test on the domain(s) of the map(s). In the worst-case the time +required by this operation is proportional to the size of +<VAR>wt-tree-1</VAR>. +</P> +</DL> +<P> + +<A NAME="IDX1082"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/set-equal?</B> <I>wt-tree-1 wt-tree-2</I> +<DD>Returns <CODE>#t</CODE> iff for every association in <VAR>wt-tree-1</VAR> there is +an association in <VAR>wt-tree-2</VAR> that has the same key, and <EM>vice +versa</EM>. +<P> + +Viewing the arguments as sets <CODE>wt-tree/set-equal?</CODE> is the set +equality predicate. As a map operation it determines if two maps are +defined on the same domain. +</P> +<P> + +This procedure is equivalent to +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(lambda (wt-tree-1 wt-tree-2) + (and (wt-tree/subset? wt-tree-1 wt-tree-2 + (wt-tree/subset? wt-tree-2 wt-tree-1))) +</pre></td></tr></table><P> + +In the worst-case the time required by this operation is proportional to +the size of the smaller tree. +</P> +</DL> +<P> + +<A NAME="IDX1083"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/fold</B> <I>combiner initial wt-tree</I> +<DD>This procedure reduces <VAR>wt-tree</VAR> by combining all the associations, +using an reverse in-order traversal, so the associations are visited in +reverse order. <VAR>Combiner</VAR> is a procedure of three arguments: a key, +a datum and the accumulated result so far. Provided <VAR>combiner</VAR> +takes time bounded by a constant, <CODE>wt-tree/fold</CODE> takes time +proportional to the size of <VAR>wt-tree</VAR>. +<P> + +A sorted association list can be derived simply: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(wt-tree/fold (lambda (key datum list) + (cons (cons key datum) list)) + '() + <VAR>wt-tree</VAR>)) +</pre></td></tr></table><P> + +The data in the associations can be summed like this: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(wt-tree/fold (lambda (key datum sum) (+ sum datum)) + 0 + <VAR>wt-tree</VAR>) +</pre></td></tr></table></DL> +<P> + +<A NAME="IDX1084"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/for-each</B> <I>action wt-tree</I> +<DD>This procedure traverses the tree in-order, applying <VAR>action</VAR> to +each association. +The associations are processed in increasing order of their keys. +<VAR>Action</VAR> is a procedure of two arguments which take the key and +datum respectively of the association. +Provided <VAR>action</VAR> takes time bounded by a constant, +<CODE>wt-tree/for-each</CODE> takes time proportional to in the size of +<VAR>wt-tree</VAR>. +The example prints the tree: +<P> + +<TABLE><tr><td> </td><td class=example><pre>(wt-tree/for-each (lambda (key value) + (display (list key value))) + <VAR>wt-tree</VAR>)) +</pre></td></tr></table></DL> +<P> + +<A NAME="Indexing Operations on Weight-Balanced Trees"></A> +<HR SIZE="6"> +<A NAME="SEC182"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC181"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC178"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 6.3.4 Indexing Operations on Weight-Balanced Trees </H3> +<!--docid::SEC182::--> +<P> + +Weight balanced trees support operations that view the tree as sorted +sequence of associations. Elements of the sequence can be accessed by +position, and the position of an element in the sequence can be +determined, both in logarthmic time. +</P> +<P> + +<A NAME="IDX1085"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/index</B> <I>wt-tree index</I> +<DD><A NAME="IDX1086"></A> +<DT><U>procedure+:</U> <B>wt-tree/index-datum</B> <I>wt-tree index</I> +<DD><A NAME="IDX1087"></A> +<DT><U>procedure+:</U> <B>wt-tree/index-pair</B> <I>wt-tree index</I> +<DD>Returns the 0-based <VAR>index</VAR>th association of <VAR>wt-tree</VAR> in the +sorted sequence under the tree's ordering relation on the keys. +<CODE>wt-tree/index</CODE> returns the <VAR>index</VAR>th key, +<CODE>wt-tree/index-datum</CODE> returns the datum associated with the +<VAR>index</VAR>th key and <CODE>wt-tree/index-pair</CODE> returns a new pair +<CODE>(<VAR>key</VAR> . <VAR>datum</VAR>)</CODE> which is the <CODE>cons</CODE> of the +<VAR>index</VAR>th key and its datum. The average and worst-case times +required by this operation are proportional to the logarithm of the +number of associations in the tree. +<P> + +These operations signal an error if the tree is empty, if +<VAR>index</VAR><CODE><0</CODE>, or if <VAR>index</VAR> is greater than or equal to the +number of associations in the tree. +</P> +<P> + +Indexing can be used to find the median and maximum keys in the tree as +follows: +</P> +</DL> +<P> + +<TABLE><tr><td> </td><td class=example><pre>median: (wt-tree/index <VAR>wt-tree</VAR> (quotient (wt-tree/size <VAR>wt-tree</VAR>) 2)) + +maximum: (wt-tree/index <VAR>wt-tree</VAR> (-1+ (wt-tree/size <VAR>wt-tree</VAR>))) +</pre></td></tr></table><P> + +<A NAME="IDX1088"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/rank</B> <I>wt-tree key</I> +<DD>Determines the 0-based position of <VAR>key</VAR> in the sorted sequence of +the keys under the tree's ordering relation, or <CODE>#f</CODE> if the tree +has no association with for <VAR>key</VAR>. This procedure returns either an +exact non-negative integer or <CODE>#f</CODE>. The average and worst-case +times required by this operation are proportional to the logarithm of +the number of associations in the tree. +</DL> +<P> + +<A NAME="IDX1089"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/min</B> <I>wt-tree</I> +<DD><A NAME="IDX1090"></A> +<DT><U>procedure+:</U> <B>wt-tree/min-datum</B> <I>wt-tree</I> +<DD><A NAME="IDX1091"></A> +<DT><U>procedure+:</U> <B>wt-tree/min-pair</B> <I>wt-tree</I> +<DD>Returns the association of <VAR>wt-tree</VAR> that has the least key under +the tree's ordering relation. <CODE>wt-tree/min</CODE> returns the least key, +<CODE>wt-tree/min-datum</CODE> returns the datum associated with the least key +and <CODE>wt-tree/min-pair</CODE> returns a new pair <CODE>(key . datum)</CODE> +which is the <CODE>cons</CODE> of the minimum key and its datum. The average +and worst-case times required by this operation are proportional to the +logarithm of the number of associations in the tree. +<P> + +These operations signal an error if the tree is empty. +They could be written +<TABLE><tr><td> </td><td class=example><pre>(define (wt-tree/min tree) (wt-tree/index tree 0)) +(define (wt-tree/min-datum tree) (wt-tree/index-datum tree 0)) +(define (wt-tree/min-pair tree) (wt-tree/index-pair tree 0)) +</pre></td></tr></table></DL> +<P> + +<A NAME="IDX1092"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/delete-min</B> <I>wt-tree</I> +<DD>Returns a new tree containing all of the associations in <VAR>wt-tree</VAR> +except the association with the least key under the <VAR>wt-tree</VAR>'s +ordering relation. An error is signalled if the tree is empty. The +average and worst-case times required by this operation are proportional +to the logarithm of the number of associations in the tree. This +operation is equivalent to +<P> + +<TABLE><tr><td> </td><td class=example><pre>(wt-tree/delete <VAR>wt-tree</VAR> (wt-tree/min <VAR>wt-tree</VAR>)) +</pre></td></tr></table></DL> +<P> + +<A NAME="IDX1093"></A> +</P> +<DL> +<DT><U>procedure+:</U> <B>wt-tree/delete-min!</B> <I>wt-tree</I> +<DD>Removes the association with the least key under the <VAR>wt-tree</VAR>'s +ordering relation. An error is signalled if the tree is empty. The +average and worst-case times required by this operation are proportional +to the logarithm of the number of associations in the tree. This +operation is equivalent to +<P> + +<TABLE><tr><td> </td><td class=example><pre>(wt-tree/delete! <VAR>wt-tree</VAR> (wt-tree/min <VAR>wt-tree</VAR>)) +</pre></td></tr></table></DL> +<P> + +<A NAME="Other Packages"></A> +<HR SIZE="6"> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_6.html#SEC140"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_7.html#SEC183"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<BR> +<FONT SIZE="-1"> +This document was generated +by <I>Steve Langasek</I> on <I>January, 10 2005</I> +using <A HREF="http://texi2html.cvshome.org"><I>texi2html</I></A> +</FONT> + +</BODY> +</HTML> |