@code{(require 'databases)}
@ftindex databases

@noindent
This enhancement wraps a utility layer on @code{relational-database}
which provides:

@itemize @bullet
@item
Identification of open databases by filename.
@item
Automatic sharing of open (immutable) databases.
@item
Automatic loading of base-table package when creating a database.
@item
Detection and automatic loading of the appropriate base-table package
when opening a database.
@item
Table and data definition from Scheme lists.
@end itemize

@subsubheading Database Sharing

@noindent
@dfn{Auto-sharing} refers to a call to the procedure
@cindex Auto-sharing
@code{open-database} returning an already open database (procedure),
rather than opening the database file a second time.

@quotation
@emph{Note:} Databases returned by @code{open-database} do not include
wrappers applied by packages like @ref{Embedded Commands}.  But
wrapped databases do work as arguments to these functions.
@end quotation

@noindent
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.

@noindent
This next set of procedures mirror the whole-database methods in
@ref{Database Operations}.  Except for @code{create-database}, each
procedure will accept either a filename or database procedure for its
first argument.


@defun create-database filename base-table-type

Returns an open relational database (with base-table type
@var{base-table-type}) associated with @var{filename}.
@end defun
@noindent
Only @code{alist-table} and base-table modules which have been loaded
will dispatch correctly from the @code{open-database} procedures.
Therefore, either pass two arguments to @code{open-database}, or
require the base-table your database file uses before calling
@code{open-database} with one argument.


@defun open-database! rdb base-table-type

Returns @emph{mutable} open relational database or #f.
@end defun

@defun open-database rdb base-table-type

Returns an open relational database associated with @var{rdb}.  The
database will be opened with base-table type @var{base-table-type}).


@defunx open-database rdb
Returns an open relational database associated with @var{rdb}.
@code{open-database} will attempt to deduce the correct base-table-type.
@end defun

@defun write-database rdb filename

Writes the mutable relational-database @var{rdb} to @var{filename}.
@end defun

@defun sync-database rdb

Writes the mutable relational-database @var{rdb} to the filename it was
opened with.
@end defun

@defun solidify-database rdb

Syncs @var{rdb} and makes it immutable.
@end defun

@defun close-database rdb

@var{rdb} will only be closed when the count of @code{open-database} - @code{close-database}
calls for @var{rdb} (and its filename) is 0.  @code{close-database} returns #t if successful;
and #f otherwise.
@end defun

@defun mdbm:report

Prints a table of open database files.  The columns are the
base-table type, number of opens, @samp{!} for mutable, the
filename, and the lock certificate (if locked).
@end defun
@example
(mdbm:report)
@print{}
  alist-table 003   /usr/local/lib/slib/clrnamdb.scm
  alist-table 001 ! sdram.db jaffer@@aubrey.jaffer.3166:1038628199
@end example

@subsubheading Defining Tables


@defun define-tables rdb spec-0 @dots{}

Adds tables as specified in @var{spec-0} @dots{} to the open
relational-database @var{rdb}.  Each @var{spec} has the form:

@lisp
(@r{<name>} @r{<descriptor-name>} @r{<descriptor-name>} @r{<rows>})
@end lisp
or
@lisp
(@r{<name>} @r{<primary-key-fields>} @r{<other-fields>} @r{<rows>})
@end lisp

where @r{<name>} is the table name, @r{<descriptor-name>} is the symbol
name of a descriptor table, @r{<primary-key-fields>} and
@r{<other-fields>} describe the primary keys and other fields
respectively, and @r{<rows>} is a list of data rows to be added to the
table.

@r{<primary-key-fields>} and @r{<other-fields>} are lists of field
descriptors of the form:

@lisp
(@r{<column-name>} @r{<domain>})
@end lisp
or
@lisp
(@r{<column-name>} @r{<domain>} @r{<column-integrity-rule>})
@end lisp

where @r{<column-name>} is the column name, @r{<domain>} is the domain
of the column, and @r{<column-integrity-rule>} is an expression whose
value is a procedure of one argument (which returns @code{#f} to signal
an error).

If @r{<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} @dots{}) single
key field table, a foriegn-key domain will be created for it.
@end defun
@subsubheading Listing Tables


@defun list-table-definition rdb table-name

If symbol @var{table-name} exists in the open relational-database
@var{rdb}, 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.

The list returned by @code{list-table-definition}, when passed as an
argument to @code{define-tables}, will recreate the table.
@end defun
