=pod

=encoding utf8

=head1 NAME

Muldis::D::Ext::Relation -
Muldis D extension adding more generic relational operators

=head1 VERSION

This document is Muldis::D::Ext::Relation version 0.23.1.

=head1 PREFACE

This document is part of the Muldis D language specification, whose root
document is L<Muldis::D>; you should read that root document
before you read this one, which provides subservient details.

=head1 DESCRIPTION

Muldis D has a mandatory core set of system-defined (eternally available)
entities, which is referred to as the I<Muldis D core> or the I<core>; they
are the minimal entities that all Muldis D implementations need to provide;
they are mutually self-describing and are used to bootstrap the language;
any entities outside the core, called I<Muldis D extensions>, are
non-mandatory and are defined in terms of the core or each other, but the
reverse isn't true.

This current C<Relation> document describes the system-defined I<Muldis D
Relation Extension>, which consists of many generic relational operators
(for generic relations), adding to the minimum few defined in the language
core.

This current document does not describe the polymorphic operators that all
types, or some types including core types, have defined over them; said
operators are defined once for all types in L<Muldis::D::Core>.

I<This documentation is pending.>

=head1 SYSTEM-DEFINED GENERIC SINGLE INPUT RELATION FUNCTIONS

These functions are applicable to mainly relation types, but are generic in
that they typically work with any relation types.

=over

=item C<function sys.std.Relation.degree result UInt params {
topic(Relation) }>

This function results in the degree of its argument (that is, the count of
attributes it has).

=item C<function sys.std.Relation.is_empty result Bool params {
topic(Relation) }>

This function results in C<Bool:true> iff its argument has zero tuples, and
C<Bool:false> otherwise.  Note that if you are using a C<Maybe> to
represent a sparse data item, analagously to a SQL nullable context, then
testing the C<Maybe> with C<is_empty> is analagous to testing a SQL
nullable with C<is null>.

=item C<function sys.std.Relation.is_not_empty result Bool params {
topic(Relation) }>

This function is exactly the same as C<sys.std.Relation.is_empty> except
that it results in the opposite boolean value when given the same argument.
And following the analogy with C<is_empty>, C<is_not_empty> is analagous to
SQL's C<is not null>.

=item C<function sys.std.Relation.empty result Relation params {
topic(Relation) }>

This function results in the empty relation of the same heading of its
argument; it has zero tuples.

=item C<function sys.std.Relation.universal result Relation params {
topic(Relation) }>

This function results in the universal relation of the same heading of its
argument; that is, the relation having all the tuples that could ever exist
in a relation with that heading.  This function will fail if said universal
relation is impossible or impractically large to represent, such as when
any attributes are of infinite types.

=item C<function sys.std.Relation.power_set result set_of.Relation params {
topic(Relation) }>

This function results in the power set of its argument.  The result is a
C<Set> whose sole attribute is C<Relation>-typed (its type is nominally the
same as that of the argument) and which has a tuple for every distinct
subset of tuples in the argument.  The cardinality of the result is equal
to 2 raised to the power of the cardinality of the argument (which may
easily lead to a very large result, so use this function with care).  Note
that the N-ary relational union of the power set of some relation is that
relation; the N-ary intersection of any power set is the empty relation.

=item C<function sys.std.Relation.negation result Relation params {
topic(Relation) }>

This function results in the relational negation/not of its argument.  The
result relation has the same heading as its argument, and its body contains
all of the tuples that are in the universal relation of the same heading
and that are not in the argument; that is, the result is the relational
difference when the argument is subtracted from said universal relation.
This function will fail on any argument that C<sys.std.Relation.universal>
would fail on.

=item C<function sys.std.Relation.transitive_closure result Relation params
{ topic(Relation) }>

This function results in the transitive closure of its argument.  The
argument is a binary relation whose attributes are both of the same
declared type, and the result is a relation having the same heading and a
body which is a superset of the argument's tuples.  Assuming that the
argument represents all of the node pairs in a directed graph that have an
arc between them, and so each argument tuple represents an arc,
C<transitive_closure> will determine all of the node pairs in that graph
which have a path between them (a recursive operation), so each tuple of
the result represents a path.  The result is a superset since all arcs are
also complete paths.  The C<transitive_closure> function is intended to
support recursive queries, such as in connection with the "part explosion
problem" (the problem of finding all components, at all levels, of some
specified part).

=item C<function sys.std.Relation.reduction result Tuple params {
topic(Relation), func(Cat.NameChain), assuming(Tuple), identity(Tuple) }>

This function is a generic reduction operator that recursively takes each
pair of tuples in C<topic> and applies an argument-specified tuple
value-resulting function (which is both commutative and associative) to the
pair until just one input tuple is left, which is the result.  The function
to apply is named in the C<func> argument, and that function must have 3
arguments named C<v1>, C<v2>, C<assuming>; the last parameter is curried
with the same-named argument of C<reduction>, and the first 2 parameters
are the 2 input tuples for an invocation.  If C<topic> has zero tuples,
then C<reduction> results in the tuple given in C<identity>.  I<Note that
C<identity> may be changed to take a function name rather than a value, for
consistency with C<func>.>  This function will fail if the declared
headings of C<identity> and C<topic> aren't compatible.

=item C<function sys.std.Relation.maybe_reduction result maybe_of.Tuple
params { topic(Relation), func(Cat.NameChain), assuming(Tuple) }>

This function is exactly the same as C<sys.std.Relation.reduction> except
that it does not take an C<assuming> argument, and it results in a C<Maybe>
of what is otherwise the result type, and that result has zero elements if
the argument has zero elements.

=item C<function sys.std.Relation.map result Relation params {
topic(Relation), func(Cat.NameChain), assuming(Tuple) }>

This function provides a convenient one-place generalization of per-tuple
transformations that otherwise might require the chaining of up to a
half-dozen other operators like restriction, extension, and rename.  This
function results in a relation each of whose tuples is the result of
applying, to each of the tuples of its C<topic> argument, the
C<Tuple>-resulting function named in its C<func> argument when the latter
function is curried by its C<assuming> argument.  There is no restriction
on what attributes the result tuple of C<func> may have (except that all
tuples from C<func> must have compatible headings); this tuple from C<func>
would completely replace the original tuple from C<topic>.  The result
relation has a cardinality that is the same as that of C<topic>, unless the
result of C<func> was redundant tuples, in which case the result has
appropriately fewer tuples.  As a trivial case, if C<func> is defined to
unconditionally result in the same tuple as its own C<topic> argument, then
this function results simply in C<topic>; or, if C<func> is defined to have
a static result, then this function's result will have just 0..1 tuples.

=back

=head1 SYSTEM-DEFINED GENERIC MULTIPLE INPUT RELATION FUNCTIONS

These functions are applicable to mainly relation types, but are generic in
that they typically work with any relation types.

=over

=item C<function sys.std.Relation.is_proper_subset result Bool params {
look_in(Relation), look_for(Relation) }>

This function is exactly the same as C<sys.std.Core.Relation.is_subset>
except that it results in C<Bool:false> if its 2 arguments are equal.

=item C<function sys.std.Relation.is_not_proper_subset result Bool params {
look_in(Relation), look_for(Relation) }>

This function is exactly the same as C<sys.std.Relation.is_proper_subset>
except that it results in the opposite boolean value when given the same
arguments.

=item C<function sys.std.Relation.exclusion result Relation params {
topic(bag_of.Relation) }>

This function results in the relational exclusion/exclusive-or of the N
element values of its argument; it is a reduction operator that recursively
takes each pair of input values and relationally excludes (which is both
commutative and associative) them together until just one is left, which is
the result.  The result relation has the same heading as all of its inputs,
and its body contains every tuple that is in just an odd number of the
input relations.  If C<topic> has zero values, then C<exclusion> results in
the empty relation with the same heading, which is the per-distinct-heading
identity value for relational exclusion.  Note that this operation is also
legitimately known as I<symmetric difference>.

=item C<function sys.std.Relation.composition result Relation params {
r1(Relation), r2(Relation) }>

This function results in the relational composition of its 2 arguments.  It
is conceptually a short-hand for first doing an ordinary relational join
between its 2 arguments, and then performing a relational projection on all
of the attributes that only one of the arguments has; that is, the result
has all of and just the attributes that were not involved in matching the
tuples of the 2 arguments.  This function will fail any time that C<join>
would fail on the same 2 input relations.

=item C<function sys.std.Relation.join_with_group result Relation params {
primary(Relation), secondary(Relation), group_attr(Cat.Name) }>

This function is a short-hand for first taking a (natural inner) C<join> of
its C<primary> and C<secondary> arguments, and then taking a C<group> on
all of the attributes that only the C<secondary> argument had, such that
the attribute resulting from the group has the name C<group_attr>.  The
result has 1 tuple for every tuple of C<primary> where at least 1 matching
tuple exists in C<secondary>.  This function will fail if C<group_attr> is
the same name as any source attribute that wasn't grouped.  This function
is a convenient tool for gathering both parent and child records from a
database using a single query while avoiding duplication of the parent
record values.

=back

=head1 SYSTEM-DEFINED RELATIONAL RANKING AND QUOTA FUNCTIONS

These additional functions are specific to supporting ranking and quotas.

=over

=item C<function sys.std.Relation.rank result Relation params {
topic(Relation), name(Cat.Name), ord_func(Cat.NameChain),
ord_assuming(Tuple) }>

This function results in the relational extension of its C<topic> argument
by a single C<UInt>-typed attribute whose name is provided by the C<name>
argument, where the value of the new attribute for each tuple is the rank
of that tuple as determined by the (total) C<order_determination> function
named in the C<ord_func> argument when the latter function is curried by
the C<ord_assuming> argument.  The C<order_determination> function compares
tuples, with each invocation of it getting a C<topic> tuple as each its
C<topic> and C<other> arguments.  The new attribute of C<rank>'s result has
a value of zero for its ranked-first tuple, and each further consecutive
ranked tuple has the next larger integer value.  Note that C<rank> provides
the functionality of SQL's "RANK" feature but that the result of C<rank> is
always a total ordering (as per a (total) C<order_determination> function)
and so there is no "dense" / "not dense" distinction (however a partial
ordering can be implemented over it).  See also the
C<sys.std.Array.Array_from_wrap> function, which is the same as
C<sys.std.Relation.rank> but that it wraps the source tuples rather than
just adding an attribute to them.

=item C<function sys.std.Relation.limit result Relation params {
topic(Relation), ord_func(Cat.NameChain), ord_assuming(Tuple),
min_rank(UInt), max_rank(UInt) }>

This function results in the relational restriction of its C<topic>
argument as determined by first ranking its tuples as per C<rank> function
(using C<ord_func> and C<ord_assuming>) and then keeping just those tuples
whose rank is within the inclusive range specified by the C<min_rank> and
C<max_rank> arguments (C<rank>'s extra attribute is not kept).  The
C<limit> function implements a certain kind of quota query where all the
result tuples are consecutive in their ranks.  This function will fail if
C<max_rank> is before C<min_rank>.  It is valid for C<min_rank> or
C<max_rank> to be greater than the maximum rank of the source tuples; in
the first case, the result has zero tuples; in the second case, the result
has all remaining tuples starting at C<min_rank>.  If C<topic> has any
tuples and C<min_rank> matches the rank of a source tuple, then the result
will always have at least 1 tuple.  Note that C<limit> provides the
functionality of SQL's "LIMIT/OFFSET" feature in combination with "ORDER
BY" but that the result tuples of C<limit> do not remain ordered (but see
C<sys.std.Array.limit_of_Array_from_wrap> for an alternative).

=back

=head1 SYSTEM-DEFINED RELATIONAL SUBSTITUTION FUNCTIONS

These additional functions are specific to supporting substitutions.

=over

=item C<function sys.std.Relation.substitution result Relation params {
topic(Relation), func(Cat.NameChain), assuming(Tuple) }>

This function is similar to C<extension> except that it substitutes values
of existing relation attributes rather than adding new attributes.  The
result relation has the same heading as C<topic>.  The result tuple of the
function named in C<func> must have a heading that is a subset of the
heading of C<topic>; corresponding values resulting from the function named
in C<func> will replace the values of the tuples of C<topic>.  The result
relation has a cardinality that is the same as that of C<topic>, unless the
result of any substitutions was redundant tuples, in which case the result
has appropriately fewer tuples.  As a trivial case, if C<func> is defined
to unconditionally result in either the degree-zero tuple or in the same
tuple as its own C<topic> argument, then this function results simply in
C<topic>; or, if C<func> is defined to have a static result and it replaces
all attributes, then this function's result will have just 0..1 tuples.

=item C<function sys.std.Relation.static_substitution result Relation
params { topic(Relation), attrs(Tuple) }>

This function is a simpler-syntax alternative to
C<sys.std.Relation.substitution> in the typical scenario where every tuple
of a relation, given in the C<topic> argument, is updated with identical
values for the same attributes; the new attribute values are given in the
C<attrs> argument.

=item C<function sys.std.Relation.substitution_in_restriction result
Relation params { topic(Relation), restr_func(Cat.NameChain),
restr_assuming(Tuple), subst_func(Cat.NameChain), subst_assuming(Tuple) }>

This function is like C<substitution> except that it only transforms a
subset of the tuples of C<topic> rather than all of them.  It is a
short-hand for first separating the tuples of C<topic> into 2 groups where
those passed by a relational restriction (defined by C<restr_func> and
C<restr_assuming>) are then transformed (defined by C<subst_func> and
C<subst_assuming>), then the result of the substitution is unioned with the
un-transformed group.  See also the C<substitution_in_semijoin> function,
which is a simpler-syntax alternative for C<substitution_in_restriction> in
its typical usage where restrictions are composed simply of anded or ored
tests for attribute value equality.

=item C<function sys.std.Relation.static_substitution_in_restriction result
Relation params { topic(Relation), restr_func(Cat.NameChain),
restr_assuming(Tuple), subst(Tuple) }>

This function is to C<sys.std.Relation.substitution_in_restriction> what
C<sys.std.Relation.static_substitution> is to
C<sys.std.Relation.substitution>.  See also the
C<static_substitution_in_semijoin> function.

=item C<function sys.std.Relation.substitution_in_semijoin result Relation
params { topic(Relation), restr(Relation), subst_func(Cat.NameChain),
subst_assuming(Tuple) }>

This function is like C<substitution_in_restriction> except that the subset
of the tuples of C<topic> to be transformed is determined by those matched
by a semijoin with C<restr> rather than those that pass a generic
relational restriction.

=item C<function sys.std.Relation.static_substitution_in_semijoin result
Relation params { topic(Relation), restr(Relation), subst(Tuple) }>

This function is to C<sys.std.Relation.substitution_in_semijoin> what
C<sys.std.Relation.static_substitution> is to
C<sys.std.Relation.substitution>.

=back

=head1 SYSTEM-DEFINED RELATIONAL OUTER-JOIN FUNCTIONS

These additional functions are specific to supporting outer-joins.

=over

=item C<function sys.std.Relation.outer_join_with_group result Relation
params { primary(Relation), secondary(Relation), group_attr(Cat.Name) }>

This function is the same as C<sys.std.Relation.join_with_group> except
that it results in a half-outer natural join rather than an inner natural
join; every tuple of C<primary> has exactly 1 corresponding tuple in the
result, but where there were no matching C<secondary> tuples, the result
attribute named by C<group_attr> contains zero tuples rather than 1+.

=item C<function sys.std.Relation.outer_join_with_maybes result Relation
params { primary(Relation), secondary(Relation) }>

This function results in a plain half-outer natural join of its C<primary>
and C<secondary> arguments where all the result attributes that come from
just C<secondary> are C<Maybe>-typed; for result tuples from matched source
tuples, each C<secondary> attribute value is a C<Single>; for result tuples
from non-matched C<primary> tuples, each C<secondary> attribute value is a
C<Nothing>.  The C<outer_join_with_maybes> function is Muldis D's answer to
the SQL LEFT OUTER JOIN where SQL NULL is implicitly used in result rows
that were a non-match.

=item C<function sys.std.Relation.outer_join_with_defaults result Relation
params { primary(Relation), secondary(Relation) }>

This function is the same as C<sys.std.Relation.outer_join_with_maybes> but
that C<secondary>-sourced result attributes are not converted to C<Maybe>;
rather, for result tuples from non-matches, the declared types of the
C<secondary> attributes are considered, and the default values of those
types are used to fill in missing result values.

=item C<function sys.std.Relation.outer_join_with_product result Relation
params { primary(Relation), secondary(Relation), filler(Tuple) }>

This function is the same as C<sys.std.Relation.outer_join_with_defaults>
but that missing values are provided explicitly from the C<filler>
argument, which is a tuple whose heading matches the projection of
C<secondary>'s attributes that aren't in common with C<primary>, and whose
body is the literal values to use for those missing attribute values.  This
function gets its name in that conceptually the result tuples from
non-matches are the result of performing a relational cross-product between
the un-matched C<primary> tuples and the single C<filler> tuple.  This
function could alternately be named I<outer_join_with_static_extension>.

=item C<function sys.std.Relation.outer_join_with_extension result Relation
params { primary(Relation), secondary(Relation), exten_func(Cat.NameChain),
exten_assuming(Tuple) }>

This function is the same as C<sys.std.Relation.outer_join_with_product>
but that the result tuples from non-matches are the result of performing a
relational extension on the un-matched C<primary> tuples such that each
said result tuple is determined by applying the function named in
C<exten_func> to each said C<primary> tuple when the named function is
curried using the C<exten_assuming> argument.

=back

=head1 SEE ALSO

Go to L<Muldis::D> for the majority of distribution-internal
references, and L<Muldis::D::SeeAlso> for the majority of
distribution-external references.

=head1 AUTHOR

Darren Duncan (C<perl@DarrenDuncan.net>)

=head1 LICENSE AND COPYRIGHT

This file is part of the formal specification of the Muldis D language.

Muldis D is Copyright © 2002-2008, Darren Duncan.

See the LICENSE AND COPYRIGHT of L<Muldis::D> for details.

=head1 TRADEMARK POLICY

The TRADEMARK POLICY in L<Muldis::D> applies to this file too.

=head1 ACKNOWLEDGEMENTS

The ACKNOWLEDGEMENTS in L<Muldis::D> apply to this file too.

=cut
