aboutsummaryrefslogtreecommitdiffstats
path: root/slib.info-2
diff options
context:
space:
mode:
Diffstat (limited to 'slib.info-2')
-rw-r--r--slib.info-21193
1 files changed, 0 insertions, 1193 deletions
diff --git a/slib.info-2 b/slib.info-2
deleted file mode 100644
index f1c31c5..0000000
--- a/slib.info-2
+++ /dev/null
@@ -1,1193 +0,0 @@
-This is Info file slib.info, produced by Makeinfo-1.64 from the input
-file slib.texi.
-
- This file documents SLIB, the portable Scheme library.
-
- Copyright (C) 1993 Todd R. Eigenschink Copyright (C) 1993, 1994, 1995
-Aubrey Jaffer
-
- Permission is granted to make and distribute verbatim copies of this
-manual provided the copyright notice and this permission notice are
-preserved on all copies.
-
- Permission is granted to copy and distribute modified versions of this
-manual under the conditions for verbatim copying, provided that the
-entire resulting derived work is distributed under the terms of a
-permission notice identical to this one.
-
- Permission is granted to copy and distribute translations of this
-manual into another language, under the above conditions for modified
-versions, except that this permission notice may be stated in a
-translation approved by the author.
-
-
-File: slib.info, Node: Records, Next: Base Table, Prev: Queues, Up: Data Structures
-
-Records
-=======
-
- `(require 'record)'
-
- The Record package provides a facility for user to define their own
-record data types.
-
- - Function: make-record-type TYPE-NAME FIELD-NAMES
- Returns a "record-type descriptor", a value representing a new data
- type disjoint from all others. The TYPE-NAME argument must be a
- string, but is only used for debugging purposes (such as the
- printed representation of a record of the new type). The
- FIELD-NAMES argument is a list of symbols naming the "fields" of a
- record of the new type. It is an error if the list contains any
- duplicates. It is unspecified how record-type descriptors are
- represented.
-
- - Function: record-constructor RTD [FIELD-NAMES]
- Returns a procedure for constructing new members of the type
- represented by RTD. The returned procedure accepts exactly as
- many arguments as there are symbols in the given list,
- FIELD-NAMES; these are used, in order, as the initial values of
- those fields in a new record, which is returned by the constructor
- procedure. The values of any fields not named in that list are
- unspecified. The FIELD-NAMES argument defaults to the list of
- field names in the call to `make-record-type' that created the
- type represented by RTD; if the FIELD-NAMES argument is provided,
- it is an error if it contains any duplicates or any symbols not in
- the default list.
-
- - Function: record-predicate RTD
- Returns a procedure for testing membership in the type represented
- by RTD. The returned procedure accepts exactly one argument and
- returns a true value if the argument is a member of the indicated
- record type; it returns a false value otherwise.
-
- - Function: record-accessor RTD FIELD-NAME
- Returns a procedure for reading the value of a particular field of
- a member of the type represented by RTD. The returned procedure
- accepts exactly one argument which must be a record of the
- appropriate type; it returns the current value of the field named
- by the symbol FIELD-NAME in that record. The symbol FIELD-NAME
- must be a member of the list of field-names in the call to
- `make-record-type' that created the type represented by RTD.
-
- - Function: record-modifier RTD FIELD-NAME
- Returns a procedure for writing the value of a particular field of
- a member of the type represented by RTD. The returned procedure
- accepts exactly two arguments: first, a record of the appropriate
- type, and second, an arbitrary Scheme value; it modifies the field
- named by the symbol FIELD-NAME in that record to contain the given
- value. The returned value of the modifier procedure is
- unspecified. The symbol FIELD-NAME must be a member of the list
- of field-names in the call to `make-record-type' that created the
- type represented by RTD.
-
- - Function: record? OBJ
- Returns a true value if OBJ is a record of any type and a false
- value otherwise. Note that `record?' may be true of any Scheme
- value; of course, if it returns true for some particular value,
- then `record-type-descriptor' is applicable to that value and
- returns an appropriate descriptor.
-
- - Function: record-type-descriptor RECORD
- Returns a record-type descriptor representing the type of the given
- record. That is, for example, if the returned descriptor were
- passed to `record-predicate', the resulting predicate would return
- a true value when passed the given record. Note that it is not
- necessarily the case that the returned descriptor is the one that
- was passed to `record-constructor' in the call that created the
- constructor procedure that created the given record.
-
- - Function: record-type-name RTD
- Returns the type-name associated with the type represented by rtd.
- The returned value is `eqv?' to the TYPE-NAME argument given in
- the call to `make-record-type' that created the type represented by
- RTD.
-
- - Function: record-type-field-names RTD
- Returns a list of the symbols naming the fields in members of the
- type represented by RTD. The returned value is `equal?' to the
- field-names argument given in the call to `make-record-type' that
- created the type represented by RTD.
-
-
-File: slib.info, Node: Base Table, Next: Relational Database, Prev: Records, Up: Data Structures
-
-Base Table
-==========
-
- A base table implementation using Scheme association lists is
-available as the value of the identifier `alist-table' after doing:
-
- (require 'alist-table)
-
- Association list base tables are suitable for small databases and
-support all Scheme types when temporary and readable/writeable Scheme
-types when saved. I hope support for other base table implementations
-will be added in the future.
-
- This rest of this section documents the interface for a base table
-implementation from which the *Note Relational Database:: package
-constructs a Relational system. It will be of interest primarily to
-those wishing to port or write new base-table implementations.
-
- 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 `#f'
-otherwise. For example:
-
- (require 'alist-table)
- (define open-base (alist-table 'make-base))
- make-base => *a procedure*
- (define foo (alist-table 'foo))
- foo => #f
-
- - Function: make-base FILENAME KEY-DIMENSION COLUMN-TYPES
- Returns a new, open, low-level database (collection of tables)
- associated with FILENAME. This returned database has an empty
- table associated with CATALOG-ID. The positive integer
- KEY-DIMENSION is the number of keys composed to make a PRIMARY-KEY
- for the catalog table. The list of symbols COLUMN-TYPES describes
- the types of each column for that table. If the database cannot
- be created as specified, `#f' is returned.
-
- Calling the `close-base' method on this database and possibly other
- operations will cause FILENAME to be written to. If FILENAME is
- `#f' a temporary, non-disk based database will be created if such
- can be supported by the base table implelentation.
-
- - Function: open-base FILENAME MUTABLE
- Returns an open low-level database associated with FILENAME. If
- MUTABLE? is `#t', this database will have methods capable of
- effecting change to the database. If MUTABLE? is `#f', only
- methods for inquiring the database will be available. If the
- database cannot be opened as specified `#f' is returned.
-
- Calling the `close-base' (and possibly other) method on a MUTABLE?
- database will cause FILENAME to be written to.
-
- - Function: write-base LLDB FILENAME
- Causes the low-level database LLDB to be written to FILENAME. If
- the write is successful, also causes LLDB to henceforth be
- associated with FILENAME. Calling the `close-database' (and
- possibly other) method on LLDB may cause FILENAME to be written
- to. If FILENAME is `#f' 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, `#t' is returned. Otherwise, `#f' is returned.
-
- - Function: sync-base LLDB
- Causes the file associated with the low-level database LLDB to be
- updated to reflect its current state. If the associated filename
- is `#f', no action is taken and `#f' is returned. If this
- operation completes successfully, `#t' is returned. Otherwise,
- `#f' is returned.
-
- - Function: close-base LLDB
- Causes the low-level database LLDB to be written to its associated
- file (if any). If the write is successful, subsequent operations
- to LLDB will signal an error. If the operations complete
- successfully, `#t' is returned. Otherwise, `#f' is returned.
-
- - Function: make-table LLDB KEY-DIMENSION COLUMN-TYPES
- Returns the BASE-ID for a new base table, otherwise returns `#f'.
- The base table can then be opened using `(open-table LLDB
- BASE-ID)'. The positive integer KEY-DIMENSION is the number of
- keys composed to make a PRIMARY-KEY for this table. The list of
- symbols COLUMN-TYPES describes the types of each column.
-
- - Constant: catalog-id
- A constant BASE-ID suitable for passing as a parameter to
- `open-table'. CATALOG-ID will be used as the base table for the
- system catalog.
-
- - Function: open-table LLDB BASE-ID KEY-DIMENSION COLUMN-TYPES
- Returns a HANDLE for an existing base table in the low-level
- database LLDB if that table exists and can be opened in the mode
- indicated by MUTABLE?, otherwise returns `#f'.
-
- As with `make-table', the positive integer KEY-DIMENSION is the
- number of keys composed to make a PRIMARY-KEY for this table. The
- list of symbols COLUMN-TYPES describes the types of each column.
-
- - Function: kill-table LLDB BASE-ID KEY-DIMENSION COLUMN-TYPES
- Returns `#t' if the base table associated with BASE-ID was removed
- from the low level database LLDB, and `#f' otherwise.
-
- - Function: make-keyifier-1 TYPE
- Returns a procedure which accepts a single argument which must be
- of type TYPE. This returned procedure returns an object suitable
- for being a KEY argument in the functions whose descriptions
- follow.
-
- Any 2 arguments of the supported type passed to the returned
- function which are not `equal?' must result in returned values
- which are not `equal?'.
-
- - Function: make-list-keyifier KEY-DIMENSION TYPES
- The list of symbols TYPES must have at least KEY-DIMENSION
- elements. Returns a procedure which accepts a list of length
- KEY-DIMENSION and whose types must corresopond to the types named
- by TYPES. This returned procedure combines the elements of its
- list argument into an object suitable for being a KEY argument in
- the functions whose descriptions follow.
-
- Any 2 lists of supported types (which must at least include
- symbols and non-negative integers) passed to the returned function
- which are not `equal?' must result in returned values which are not
- `equal?'.
-
- - Function: make-key-extractor KEY-DIMENSION TYPES COLUMN-NUMBER
- Returns a procedure which accepts objects produced by application
- of the result of `(make-list-keyifier KEY-DIMENSION TYPES)'. This
- procedure returns a KEY which is `equal?' to the COLUMN-NUMBERth
- element of the list which was passed to create COMBINED-KEY. The
- list TYPES must have at least KEY-DIMENSION elements.
-
- - Function: make-key->list KEY-DIMENSION TYPES
- Returns a procedure which accepts objects produced by application
- of the result of `(make-list-keyifier KEY-DIMENSION TYPES)'. This
- procedure returns a list of KEYs which are elementwise `equal?' to
- the list which was passed to create COMBINED-KEY.
-
-In the following functions, the KEY argument can always be assumed to
-be the value returned by a call to a *keyify* routine.
-
- - Function: for-each-key HANDLE PROCEDURE
- Calls PROCEDURE once with each KEY in the table opened in HANDLE
- in an unspecified order. An unspecified value is returned.
-
- - Function: map-key HANDLE PROCEDURE
- Returns a list of the values returned by calling PROCEDURE once
- with each KEY in the table opened in HANDLE in an unspecified
- order.
-
- - Function: ordered-for-each-key HANDLE PROCEDURE
- Calls PROCEDURE once with each KEY in the table opened in HANDLE
- in the natural order for the types of the primary key fields of
- that table. An unspecified value is returned.
-
- - Function: present? HANDLE KEY
- Returns a non-`#f' value if there is a row associated with KEY in
- the table opened in HANDLE and `#f' otherwise.
-
- - Function: delete HANDLE KEY
- Removes the row associated with KEY from the table opened in
- HANDLE. An unspecified value is returned.
-
- - Function: make-getter KEY-DIMENSION TYPES
- Returns a procedure which takes arguments HANDLE and KEY. This
- procedure returns a list of the non-primary values of the relation
- (in the base table opened in HANDLE) whose primary key is KEY if
- it exists, and `#f' otherwise.
-
- - Function: make-putter KEY-DIMENSION TYPES
- Returns a procedure which takes arguments HANDLE and KEY and
- VALUE-LIST. This procedure associates the primary key KEY with
- the values in VALUE-LIST (in the base table opened in HANDLE) and
- returns an unspecified value.
-
- - Function: supported-type? SYMBOL
- Returns `#t' if SYMBOL names a type allowed as a column value by
- the implementation, and `#f' otherwise. At a minimum, an
- implementation must support the types `integer', `symbol',
- `string', `boolean', and `base-id'.
-
- - Function: supported-key-type? SYMBOL
- Returns `#t' if SYMBOL names a type allowed as a key value by the
- implementation, and `#f' otherwise. At a minimum, an
- implementation must support the types `integer', and `symbol'.
-
-`integer'
- Scheme exact integer.
-
-`symbol'
- Scheme symbol.
-
-`boolean'
- `#t' or `#f'.
-
-`base-id'
- Objects suitable for passing as the BASE-ID parameter to
- `open-table'. The value of CATALOG-ID must be an acceptable
- `base-id'.
-
-
-File: slib.info, Node: Relational Database, Next: Weight-Balanced Trees, Prev: Base Table, Up: Data Structures
-
-Relational Database
-===================
-
- `(require 'relational-database)'
-
- This package implements a database system inspired by the Relational
-Model (`E. F. Codd, A Relational Model of Data for Large Shared Data
-Banks'). An SLIB relational database implementation can be created
-from any *Note Base Table:: implementation.
-
-* Menu:
-
-* Motivations:: Database Manifesto
-* Creating and Opening Relational Databases::
-* Relational Database Operations::
-* Table Operations::
-* Catalog Representation::
-* Unresolved Issues::
-* Database Utilities:: 'database-utilities
-
-
-File: slib.info, Node: Motivations, Next: Creating and Opening Relational Databases, Prev: Relational Database, Up: Relational Database
-
-Motivations
------------
-
- Most nontrivial programs contain databases: Makefiles, configure
-scripts, file backup, calendars, editors, source revision control, CAD
-systems, display managers, menu GUIs, games, parsers, debuggers,
-profilers, and even error reporting are all rife with databases. Coding
-databases is such a common activity in programming that many may not be
-aware of how often they do it.
-
- A database often starts as a dispatch in a program. The author,
-perhaps because of the need to make the dispatch configurable, the need
-for correlating dispatch in other routines, or because of changes or
-growth, devises a data structure to contain the information, a routine
-for interpreting that data structure, and perhaps routines for
-augmenting and modifying the stored data. The dispatch must be
-converted into this form and tested.
-
- The programmer may need to devise an interactive program for enabling
-easy examination and modification of the information contained in this
-database. Often, in an attempt to foster modularity and avoid delays in
-release, intermediate file formats for the database information are
-devised. It often turns out that users prefer modifying these
-intermediate files with a text editor to using the interactive program
-in order to do operations (such as global changes) not forseen by the
-program's author.
-
- In order to address this need, the concientous software engineer may
-even provide a scripting language to allow users to make repetitive
-database changes. Users will grumble that they need to read a large
-manual and learn yet another programming language (even if it *almost*
-has language "xyz" syntax) in order to do simple configuration.
-
- All of these facilities need to be designed, coded, debugged,
-documented, and supported; often causing what was very simple in concept
-to become a major developement project.
-
- This view of databases just outlined is somewhat the reverse of the
-view of the originators of the "Relational Model" of database
-abstraction. The relational model was devised to unify and allow
-interoperation of large multi-user databases running on diverse
-platforms. A fairly general purpose "Comprehensive Language" for
-database manipulations is mandated (but not specified) as part of the
-relational model for databases.
-
- One aspect of the Relational Model of some importance is that the
-"Comprehensive Language" must be expressible in some form which can be
-stored in the database. This frees the programmer from having to make
-programs data-driven in order to use a database.
-
- This package includes as one of its basic supported types Scheme
-"expression"s. This type allows expressions as defined by the Scheme
-standards to be stored in the database. Using `slib:eval' retrieved
-expressions can be evaluated (in the top-level environment). Scheme's
-`lambda' facilitates closure of environments, modularity, etc. so that
-procedures (which could not be stored directly most databases) can
-still be effectively retrieved. Since `slib:eval' evaluates
-expressions in the top-level environment, built-in and user defined
-procedures can be easily accessed by name.
-
- This package's purpose is to standardize (through a common interface)
-database creation and usage in Scheme programs. The relational model's
-provision for inclusion of language expressions as data as well as the
-description (in tables, of course) of all of its tables assures that
-relational databases are powerful enough to assume the roles currently
-played by thousands of ad-hoc routines and data formats.
-
-Such standardization to a relational-like model brings many benefits:
-
- * Tables, fields, domains, and types can be dealt with by name in
- programs.
-
- * The underlying database implementation can be changed (for
- performance or other reasons) by changing a single line of code.
-
- * The formats of tables can be easily extended or changed without
- altering code.
-
- * Consistency checks are specified as part of the table descriptions.
- Changes in checks need only occur in one place.
-
- * All the configuration information which the developer wishes to
- group together is easily grouped, without needing to change
- programs aware of only some of these tables.
-
- * Generalized report generators, interactive entry programs, and
- other database utilities can be part of a shared library. The
- burden of adding configurability to a program is greatly reduced.
-
- * Scheme is the "comprehensive language" for these databases.
- Scripting for configuration no longer needs to be in a separate
- language with additional documentation.
-
- * Scheme's latent types mesh well with the strict typing and logical
- requirements of the relational model.
-
- * Portable formats allow easy interchange of data. The included
- table descriptions help prevent misinterpretation of format.
-
-
-File: slib.info, Node: Creating and Opening Relational Databases, Next: Relational Database Operations, Prev: Motivations, Up: Relational Database
-
-Creating and Opening Relational Databases
------------------------------------------
-
- - Function: make-relational-system BASE-TABLE-IMPLEMENTATION
- Returns a procedure implementing a relational database using the
- BASE-TABLE-IMPLEMENTATION.
-
- All of the operations of a base table implementation are accessed
- through a procedure defined by `require'ing that implementation.
- Similarly, all of the operations of the relational database
- implementation are accessed through the procedure returned by
- `make-relational-system'. For instance, a new relational database
- could be created from the procedure returned by
- `make-relational-system' by:
-
- (require 'alist-table)
- (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"))
-
-What follows are the descriptions of the methods available from
-relational system returned by a call to `make-relational-system'.
-
- - Function: create-database FILENAME
- Returns an open, nearly empty relational database associated with
- FILENAME. The only tables defined are the system catalog and
- domain table. Calling the `close-database' method on this database
- and possibly other operations will cause FILENAME to be written
- to. If FILENAME is `#f' 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
- `#f' is returned. For the fields and layout of descriptor tables,
- *Note Catalog Representation::
-
- - Function: open-database FILENAME MUTABLE?
- Returns an open relational database associated with FILENAME. If
- MUTABLE? is `#t', this database will have methods capable of
- effecting change to the database. If MUTABLE? is `#f', only
- methods for inquiring the database will be available. Calling the
- `close-database' (and possibly other) method on a MUTABLE?
- database will cause FILENAME to be written to. If the database
- cannot be opened as specified `#f' is returned.
-
-
-File: slib.info, Node: Relational Database Operations, Next: Table Operations, Prev: Creating and Opening Relational Databases, Up: Relational Database
-
-Relational Database Operations
-------------------------------
-
-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:
-
- (define my-database
- (create-alist-database "mydata.db"))
- (define telephone-table-desc
- ((my-database 'create-table) 'telephone-table-desc))
-
- - Function: close-database
- 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, `#t' is returned. Otherwise, `#f' is returned.
-
- - Function: write-database FILENAME
- Causes the relational database to be written to FILENAME. If the
- write is successful, also causes the database to henceforth be
- associated with FILENAME. Calling the `close-database' (and
- possibly other) method on this database will cause FILENAME to be
- written to. If FILENAME is `#f' 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, `#t' is returned. Otherwise, `#f' is
- returned.
-
- - Function: table-exists? TABLE-NAME
- Returns `#t' if TABLE-NAME exists in the system catalog, otherwise
- returns `#f'.
-
- - Function: open-table TABLE-NAME MUTABLE?
- Returns a "methods" procedure for an existing relational table in
- this database if it exists and can be opened in the mode indicated
- by MUTABLE?, otherwise returns `#f'.
-
-These methods will be present only in databases which are MUTABLE?.
-
- - Function: delete-table TABLE-NAME
- Removes and returns the TABLE-NAME row from the system catalog if
- the table or view associated with TABLE-NAME gets removed from the
- database, and `#f' otherwise.
-
- - Function: create-table TABLE-DESC-NAME
- Returns a methods procedure for a new (open) relational table for
- describing the columns of a new base table in this database,
- otherwise returns `#f'. For the fields and layout of descriptor
- tables, *Note Catalog Representation::.
-
- - Function: create-table TABLE-NAME TABLE-DESC-NAME
- Returns a methods procedure for a new (open) relational table with
- columns as described by TABLE-DESC-NAME, otherwise returns `#f'.
-
- - Function: create-view ??
- - Function: project-table ??
- - Function: restrict-table ??
- - Function: cart-prod-tables ??
- Not yet implemented.
-
-
-File: slib.info, Node: Table Operations, Next: Catalog Representation, Prev: Relational Database Operations, Up: Relational Database
-
-Table Operations
-----------------
-
-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:
-
- (define telephone-table-desc
- ((my-database 'create-table) 'telephone-table-desc))
- (require 'common-list-functions)
- (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))
-
-Operations on a single column of a table are retrieved by giving the
-column name as the second argument to the methods procedure. For
-example:
-
- (define column-ids ((telephone-table-desc 'get* 'column-number)))
-
-Some operations described below require primary key arguments. Primary
-keys arguments are denoted KEY1 KEY2 .... 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.
-
-The term "row" 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 `#f'. Primary keys may not be missing.
-
- - Function: get KEY1 KEY2 ...
- Returns the value for the specified column of the row associated
- with primary keys KEY1, KEY2 ... if it exists, or `#f' otherwise.
-
- - Function: get*
- Returns a list of the values for the specified column for all rows
- in this table.
-
- - Function: row:retrieve KEY1 KEY2 ...
- Returns the row associated with primary keys KEY1, KEY2 ... if it
- exists, or `#f' otherwise.
-
- - Function: row:retrieve*
- Returns a list of all rows in this table.
-
- - Function: row:remove KEY1 KEY2 ...
- Removes and returns the row associated with primary keys KEY1,
- KEY2 ... if it exists, or `#f' otherwise.
-
- - Function: row:remove*
- Removes and returns a list of all rows in this table.
-
- - Function: row:delete KEY1 KEY2 ...
- Deletes the row associated with primary keys KEY1, KEY2 ... if it
- exists. The value returned is unspecified.
-
- - Function: row:delete*
- Deletes all rows in this table. The value returned is
- unspecified. The descriptor table and catalog entry for this
- table are not affected.
-
- - Function: row:update ROW
- Adds the row, ROW, to this table. If a row for the primary key(s)
- specified by ROW already exists in this table, it will be
- overwritten. The value returned is unspecified.
-
- - Function: row:update* ROWS
- Adds each row in the list ROWS, to this table. If a row for the
- primary key specified by an element of ROWS already exists in this
- table, it will be overwritten. The value returned is unspecified.
-
- - Function: row:insert ROW
- Adds the row ROW to this table. If a row for the primary key(s)
- specified by ROW already exists in this table an error is
- signaled. The value returned is unspecified.
-
- - Function: row:insert* ROWS
- Adds each row in the list ROWS, to this table. If a row for the
- primary key specified by an element of ROWS already exists in this
- table, an error is signaled. The value returned is unspecified.
-
- - Function: for-each-row PROC
- Calls PROC with each ROW in this table in the natural ordering for
- the primary key types. *Real* relational programmers would use
- some least-upper-bound join for every row to get them in order;
- But we don't have joins yet.
-
- - Function: close-table
- Subsequent operations to this table will signal an error.
-
- - Constant: column-names
- - Constant: column-foreigns
- - Constant: column-domains
- - Constant: column-types
- 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.
-
- - Constant: primary-limit
- Returns the number of primary keys fields in the relations in this
- table.
-
-
-File: slib.info, Node: Catalog Representation, Next: Unresolved Issues, Prev: Table Operations, Up: Relational Database
-
-Catalog Representation
-----------------------
-
-Each database (in an implementation) has a "system catalog" which
-describes all the user accessible tables in that database (including
-itself).
-
-The system catalog base table has the following fields. `PRI'
-indicates a primary key for that table.
-
- 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.
-
-Descriptors for base tables (not views) are tables (pointed to by
-system catalog). Descriptor (base) tables have the fields:
-
- PRI column-number sequential integers from 1
- primary-key? boolean TRUE for primary key components
- column-name
- column-integrity-rule
- domain-name
-
-A "primary key" is any column marked as `primary-key?' in the
-corresponding descriptor table. All the `primary-key?' columns must
-have lower column numbers than any non-`primary-key?' 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.
-
-This package currently supports tables having from 1 to 4 primary keys
-if there are non-primary columns, and any (natural) number if *all*
-columns are primary keys. If you need more than 4 primary keys, I would
-like to hear what you are doing!
-
-A "domain" is a category describing the allowable values to occur in a
-column. It is described by a (base) table with the fields:
-
- PRI domain-name
- foreign-table
- domain-integrity-rule
- type-id
- type-param
-
-The "type-id" field value is a symbol. This symbol may be used by the
-underlying base table implementation in storing that field.
-
-If the `foreign-table' field is non-`#f' 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 TYPE-PARAM (or `#f', if allowed). This
-package currently does not support composite foreign-keys.
-
-The types for which support is planned are:
- atom
- symbol
- string [<length>]
- number [<base>]
- money <currency>
- date-time
- boolean
-
- foreign-key <table-name>
- expression
- virtual <expression>
-
-
-File: slib.info, Node: Unresolved Issues, Next: Database Utilities, Prev: Catalog Representation, Up: Relational Database
-
-Unresolved Issues
------------------
-
- Although `rdms.scm' is not large I found it very difficult to write
-(six rewrites). I am not aware of any other examples of a generalized
-relational system (although there is little new in CS). I left out
-several aspects of the Relational model in order to simplify the job.
-The major features lacking (which might be addressed portably) are
-views, transaction boundaries, and protection.
-
- Protection needs a model for specifying priveledges. Given how
-operations are accessed from handles it should not be difficult to
-restrict table accesses to those allowed for that user.
-
- The system catalog has a field called `view-procedure'. This should
-allow a purely functional implementation of views. This will work but
-is unsatisfying for views resulting from a "select"ion (subset of
-rows); for whole table operations it will not be possible to reduce the
-number of keys scanned over when the selection is specified only by an
-opaque procedure.
-
- Transaction boundaries present the most intriguing area. Transaction
-boundaries are actually a feature of the "Comprehensive Language" of the
-Relational database and not of the database. Scheme would seem to
-provide the opportunity for an extremely clean semantics for transaction
-boundaries since the builtin procedures with side effects are small in
-number and easily identified.
-
- These side-effect builtin procedures might all be portably redefined
-to versions which properly handled transactions. Compiled library
-routines would need to be recompiled as well. Many system extensions
-(delete-file, system, etc.) would also need to be redefined.
-
-There are 2 scope issues that must be resolved for multiprocess
-transaction boundaries:
-
-Process scope
- The actions captured by a transaction should be only for the
- process which invoked the start of transaction. Although standard
- Scheme does not provide process primitives as such, `dynamic-wind'
- would provide a workable hook into process switching for many
- implementations.
-
-Shared utilities with state
- Some shared utilities have state which should *not* be part of a
- transaction. An example would be calling a pseudo-random number
- generator. If the success of a transaction depended on the
- pseudo-random number and failed, the state of the generator would
- be set back. Subsequent calls would keep returning the same
- number and keep failing.
-
- Pseudo-random number generators are not reentrant and so would
- require locks in order to operate properly in a multiprocess
- environment. Are all examples of utilities whose state should not
- part of transactions also non-reentrant? If so, perhaps
- suspending transaction capture for the duration of locks would fix
- it.
-
-
-File: slib.info, Node: Database Utilities, Prev: Unresolved Issues, Up: Relational Database
-
-Database Utilities
-------------------
-
- `(require 'database-utilities)'
-
-This enhancement wraps a utility layer on `relational-database' which
-provides:
- * Automatic loading of the appropriate base-table package when
- opening a database.
-
- * Automatic execution of initialization commands stored in database.
-
- * Transparent execution of database commands stored in `*commands*'
- table in database.
-
-Also included are utilities which provide:
- * Data definition from Scheme lists and
-
- * Report generation
-
-for any SLIB relational database.
-
- - Function: create-database FILENAME BASE-TABLE-TYPE
- Returns an open, nearly empty enhanced (with `*commands*' table)
- relational database (with base-table type BASE-TABLE-TYPE)
- associated with FILENAME.
-
- - Function: open-database FILENAME
- - Function: open-database FILENAME BASE-TABLE-TYPE
- Returns an open enchanced relational database associated with
- FILENAME. The database will be opened with base-table type
- BASE-TABLE-TYPE) if supplied. If BASE-TABLE-TYPE is not supplied,
- `open-database' will attempt to deduce the correct
- base-table-type. If the database can not be opened or if it lacks
- the `*commands*' table, `#f' is returned.
-
- - Function: open-database! FILENAME
- - Function: open-database! FILENAME BASE-TABLE-TYPE
- Returns *mutable* open enchanced relational database ...
-
-The table `*commands*' in an "enhanced" relational-database has the
-fields (with domains):
- PRI name symbol
- parameters parameter-list
- procedure expression
- documentation string
-
- The `parameters' field is a foreign key (domain `parameter-list') of
-the `*catalog-data*' table and should have the value of a table
-described by `*parameter-columns*'. This `parameter-list' 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 `parameter-list' table has the
-following fields:
- PRI index uint
- name symbol
- arity parameter-arity
- domain domain
- default expression
- documentation string
-
- The `arity' field can take the values:
-
-`single'
- Requires a single parameter of the specified domain.
-
-`optional'
- A single parameter of the specified domain or zero parameters is
- acceptable.
-
-`boolean'
- A single boolean parameter or zero parameters (in which case `#f'
- is substituted) is acceptable.
-
-`nary'
- Any number of parameters of the specified domain are acceptable.
- The argument passed to the command function is always a list of the
- parameters.
-
-`nary1'
- 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.
-
- The `domain' field specifies the domain which a parameter or
-parameters in the `index'th field must satisfy.
-
- The `default' field is an expression whose value is either `#f' or a
-procedure of no arguments which returns a parameter or parameter list
-as appropriate. If the expression's value is `#f' then no default is
-appropriate for this parameter. Note that since the `default'
-procedure is called every time a default parameter is needed for this
-column, "sticky" defaults can be implemented using shared state with
-the domain-integrity-rule.
-
-Invoking Commands
-.................
-
- When an enhanced relational-database is called with a symbol which
-matches a NAME in the `*commands*' 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.
-
- The command `*initialize*' is special. If present in the
-`*commands*' table, `open-database' or `open-database!' will return the
-value of the `*initialize*' command. Notice that arbitrary code can be
-run when the `*initialize*' procedure is automatically applied to the
-enhanced relational-database.
-
- Note also that if you wish to shadow or hide from the user
-relational-database methods described in *Note Relational Database
-Operations::, this can be done by a dispatch in the closure returned by
-the `*initialize*' expression rather than by entries in the
-`*commands*' table if it is desired that the underlying methods remain
-accessible to code in the `*commands*' table.
-
- - Function: make-command-server RDB TABLE-NAME
- Returns a procedure of 2 arguments, a (symbol) command and a
- call-back procedure. When this returned procedure is called, it
- looks up COMMAND in table TABLE-NAME and calls the call-back
- procedure with arguments:
- COMMAND
- The COMMAND
-
- COMMAND-VALUE
- The result of evaluating the expression in the PROCEDURE
- field of TABLE-NAME and calling it with RDB.
-
- PARAMETER-NAME
- A list of the "official" name of each parameter. Corresponds
- to the `name' field of the COMMAND's parameter-table.
-
- POSITIONS
- A list of the positive integer index of each parameter.
- Corresponds to the `index' field of the COMMAND's
- parameter-table.
-
- ARITIES
- A list of the arities of each parameter. Corresponds to the
- `arity' field of the COMMAND's parameter-table. For a
- description of `arity' see table above.
-
- DEFAULTS
- A list of the defaults for each parameter. Corresponds to
- the `defaults' field of the COMMAND's parameter-table.
-
- DOMAIN-INTEGRITY-RULES
- 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 `nary' arity parameters.
-
- ALIASES
- A list of lists of `(alias parameter-name)'. There can be
- more than one alias per PARAMETER-NAME.
-
- For information about parameters, *Note Parameter lists::. Here is an
-example of setting up a command with arguments and parsing those
-arguments from a `getopt' style argument list (*note Getopt::.).
-
- (require 'database-utilities)
- (require 'parameters)
- (require 'getopt)
-
- (define my-rdb (create-database #f 'alist-table))
-
- (define-tables my-rdb
- '(foo-params
- *parameter-columns*
- *parameter-columns*
- ((1 first-argument single string "hithere" "first argument")
- (2 flag boolean boolean #f "a flag")))
- '(foo-pnames
- ((name string))
- ((parameter-index uint))
- (("l" 1)
- ("a" 2)))
- '(my-commands
- ((name symbol))
- ((parameters parameter-list)
- (parameter-names parameter-name-translation)
- (procedure expression)
- (documentation string))
- ((foo
- foo-params
- foo-pnames
- (lambda (rdb) (lambda (foo aflag) (print foo aflag)))
- "test command arguments"))))
-
- (define (dbutil:serve-command-line rdb command-table
- command argc argv)
- (set! argv (if (vector? argv) (vector->list argv) argv))
- ((make-command-server rdb command-table)
- command
- (lambda (comname comval options positions
- arities types defaults dirs aliases)
- (apply comval (getopt->arglist argc argv options positions
- arities types defaults dirs aliases)))))
-
- (define (test)
- (set! *optind* 1)
- (dbutil:serve-command-line
- my-rdb 'my-commands 'foo 4 '("dummy" "-l" "foo" "-a")))
- (test)
- -|
- "foo" #t
-
- Some commands are defined in all extended relational-databases. The
-are called just like *Note Relational Database Operations::.
-
- - Function: add-domain DOMAIN-ROW
- Adds DOMAIN-ROW to the "domains" table if there is no row in the
- domains table associated with key `(car DOMAIN-ROW)' and returns
- `#t'. Otherwise returns `#f'.
-
- For the fields and layout of the domain table, *Note Catalog
- Representation::
-
- - Function: delete-domain DOMAIN-NAME
- Removes and returns the DOMAIN-NAME row from the "domains" table.
-
- - Function: domain-checker DOMAIN
- Returns a procedure to check an argument for conformance to domain
- DOMAIN.
-
-Defining Tables
----------------
-
- - Procedure: define-tables RDB SPEC-0 ...
- Adds tables as specified in SPEC-0 ... to the open
- relational-database RDB. Each SPEC has the form:
-
- (<name> <descriptor-name> <descriptor-name> <rows>)
- or
- (<name> <primary-key-fields> <other-fields> <rows>)
-
- 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.
-
- <primary-key-fields> and <other-fields> are lists of field
- descriptors of the form:
-
- (<column-name> <domain>)
- or
- (<column-name> <domain> <column-integrity-rule>)
-
- 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 (and returns non-`#f' to
- signal an error).
-
- If <domain> is not a defined domain name and it matches the name of
- this table or an already defined (in one of SPEC-0 ...) single key
- field table, a foriegn-key domain will be created for it.
-
- - Procedure: create-report RDB DESTINATION REPORT-NAME TABLE
- - Procedure: create-report RDB DESTINATION REPORT-NAME
- The symbol REPORT-NAME must be primary key in the table named
- `*reports*' in the relational database RDB. DESTINATION is a
- port, string, or symbol. If DESTINATION is a:
-
- port
- The table is created as ascii text and written to that port.
-
- string
- The table is created as ascii text and written to the file
- named by DESTINATION.
-
- symbol
- DESTINATION is the primary key for a row in the table named
- *printers*.
-
- Each row in the table *reports* has the fields:
-
- name
- The report name.
-
- default-table
- The table to report on if none is specified.
-
- header, footer
- A `format' string. At the beginning and end of each page
- respectively, `format' is called with this string and the
- (list of) column-names of this table.
-
- reporter
- A `format' string. For each row in the table, `format' is
- called with this string and the row.
-
- minimum-break
- The minimum number of lines into which the report lines for a
- row can be broken. Use `0' if a row's lines should not be
- broken over page boundaries.
-
- Each row in the table *printers* has the fields:
-
- name
- The printer name.
-
- print-procedure
- The procedure to call to actually print.
-
- The report is prepared as follows:
-
- `Format' (*note Format::.) is called with the `header' field
- and the (list of) `column-names' of the table.
-
- `Format' is called with the `reporter' field and (on
- successive calls) each record in the natural order for the
- table. A count is kept of the number of newlines output by
- format. When the number of newlines to be output exceeds the
- number of lines per page, the set of lines will be broken if
- there are more than `minimum-break' left on this page and the
- number of lines for this row is larger or equal to twice
- `minimum-break'.
-
- `Format' is called with the `footer' field and the (list of)
- `column-names' of the table. The footer field should not
- output a newline.
-
- A new page is output.
-
- This entire process repeats until all the rows are output.
-
-The following example shows a new database with the name of `foo.db'
-being created with tables describing processor families and
-processor/os/compiler combinations.
-
-The database command `define-tables' is defined to call `define-tables'
-with its arguments. The database is also configured to print `Welcome'
-when the database is opened. The database is then closed and reopened.
-
- (require 'database-utilities)
- (define my-rdb (create-database "foo.db" 'alist-table))
-
- (define-tables my-rdb
- '(*commands*
- ((name symbol))
- ((parameters parameter-list)
- (procedure expression)
- (documentation string))
- ((define-tables
- no-parameters
- no-parameter-names
- (lambda (rdb) (lambda specs (apply define-tables rdb specs)))
- "Create or Augment tables from list of specs")
- (*initialize*
- no-parameters
- no-parameter-names
- (lambda (rdb) (display "Welcome") (newline) rdb)
- "Print Welcome"))))
-
- ((my-rdb 'define-tables)
- '(processor-family
- ((family atom))
- ((also-ran processor-family))
- ((m68000 #f)
- (m68030 m68000)
- (i386 8086)
- (8086 #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 8086 ms-dos borland-c)
- (djgpp i386 ms-dos gcc)
- (linux i386 linux gcc)
- (microsoft-c 8086 ms-dos microsoft-c)
- (os/2-emx i386 os/2 gcc)
- (turbo-c-2 8086 ms-dos turbo-c)
- (watcom-9.0 i386 ms-dos watcom))))
-
- ((my-rdb 'close-database))
-
- (set! my-rdb (open-database "foo.db" 'alist-table))
- -|
- Welcome
-