Copyright ©2007 T. H. Merrett
Aldat Computations
Wikipedia categories: programming languages, databases
Motivation
The database world has been primarily concerned with query languages, the
dominant example being SQL. This is an unfortunate limitation, because querying
is only one possible activity which can be expressed by programming, and
programming languages have much more general capabilities than query languages.
The main concession to programming language in the database community has been
to combine query language with existing programming language, usually by an
ad-hoc interface which allows the query language to be used within the
programming language. This is often a clumsy solution, because of major
conceptual mismatches between the two languages, leading to extra learning
effort, and pain, on the part of the user.
A better approach is to unify programming and query language into a
general-purpose secondary-storage programming language. The way to do this is
to examine database and programming-language concepts in light of each other,
and see if one concept contains the other, or if both can be generalized and
each contained in the result.
Overview
The computation is a unification of database relations and
programming-language parametric abstraction. The archetype of parametric
abstraction in a programming language is the "function". Mathematically, a
function is the special case of a relation that is limited to many-to-one
mapping. Pursuing this idea gives a rule-based, potentially infinite relation
which contains one or more functions, typically a function and its inverse(s).
Examples
Consider the relationship among annual interest rate, I, monthly interest
rate, i, and p, the number of months in the year (p = 12).
This could be captured in a relation
IntIntPer ( | I | i | p | )
|
| 0.0 | 0.0 | 12
|
| 0.126825030131970 | 0.01 | 12
|
| 0.268241794562546 | 0.02 | 12
|
| : | : | :
|
| 0.269734648531915 | 0.01 | 24
|
| 0.608437249475226 | 0.02 | 24
|
| : | : | :
|
We see that such a relation is infinite.
So we represent it as rules instead: a compressed relation or
computation.
comp IntIntPer (I, i, p) is
{I <- (1 + i )**p - 1}
alt
{i <- (1 + I )**(1.0/p) - 1}
alt
{p <- round(log(1 + I )/ log(1 + i ))};
The alt keywords separate blocks of code, called "alt-blocks", which are
alternatives to be evaluated, depending on which of the attributes of the
compressed relation (i.e., parameters of the computation) are supplied and which
are to be calculated. In this example, any two of the three attributes may be
supplied and the third will be evaluated.
While defining the computation requires new syntax, invoking it does
not. Since a computation is just a relation, it can be evaluated by operators
already available for databases, for instance a T-selector in the case of
Aldat.
Per <- [p ] where I =0.12 and i =0.01 in
IntIntPer ;
gives
or
Int <- [I ] where i =0.01 and p =11 in
IntIntPer ;
gives
Int( | I | )
|
| 11.389438902016055
|
and so on.
In the first invocation, the third alt-block was executed. In the second
invocation, the first alt-block was executed. The implementation matches the
supplied attributes with the alt-block that needs them.
There is syntactic sugar for these very special T-selectors, whose selection
conditions are conjunctions of <attribute>=<constant>, which makes
them look just like function calls in conventional languages.
As well as T-selectors, natural joins with a normal relation may be used to
invoke a computation: the attributes shared between relation and computation
("common" attributes) are supplied, and the other attributes of the computation
are calculated.
IntPer ( | I | p | )
|
| 0.06 | 12
|
| 0.06 | 24
|
| 0.07 | 12
|
| 0.07 | 24
|
IIP <- IntIntPer natjoin IntPer;
IIP( | I | i | p | )
|
| 0.06 | 0.004867550565343 | 12
|
| 0.06 | 0.002430820837699 | 24
|
| 0.07 | 0.005654145387405 | 12
|
| 0.07 | 0.002823087781392 | 24
|
Discussion
The computation provides the basic mechanism for a number of other important
aspects of programming for both secondary storage and primary memory.
- Event programming is implemented by system invocations of user-written computations with special names which indicate the circumstances under which the computation ("event handler") is invoked. For database events in the form of updates, these special names include the name of the relation whose update invokes the event handler, the type of update (add, delete or change), and, in the case of change, the name of the attribute whose change invokes the event handler.
(For recent considerations, see
"Advanced Database programming".)
- Abstract data types are computations which output other computations ("public methods") for use by the programmer.
- Object classes are abstract data types with state. The state is instantiated for the tuples of a given relation by natural-joining the relation with the object class. This capability permits "object-oriented" programming to be entirely inherited from relational programming.
Further Reading
Links
Aldat,
Aldat Relational Algebra.