Operations for Niagara


Introduction

     Operations  are actions which are performed on individ-
ual tuples or data items.  They are the building block  used
to  construct  operators.   An implementation of an operator
may use several operations;  for  example  a  join  operator
would  typically  use the predicate evaluation operation and
the project operation.

     Operations know nothing about streams, they  just  know
about data, and how to manipulate it.

Operations

     To  a  certain  extent  all of the operations below are
expression evaluation.  They might even be implemented  that
way with a common expression tree which generates the proper
result.  However, it is still useful to think about the dif-
ferent  operations  seperately,  for  that  is  how they are
reflected in operator usage and other DB operations.


Predicate Evaluation

     This operation is presented with a predicate expression
     to  be  evaluated,  and  a  set of tuples upon which to
     evaluate that expression.   The  output  is  a  boolean
     True/False predicate.  The inputs remain unchanged.


Function Evaluation

     This operation is presented with the same inputs as the
     Predicate Evaluator.  The input could also be  a  value
     or set of values.  However the result is a new value of
     whatever type the expression builds.


Project

     The inputs to this operation are a projection list  and
     a  set of input tuples.  The output is a new tuple with
     values copied from the appropriate parts of  the  input
     tuples.


Aggregate Function










                             -2-


     The  setup to this operation is an aggregate specifica-
     tion, which can consist of one or many aggregate opera-
     tions.   The  input  to  this  operation is a tuple, or
     rather a set of tuples which are fed  in  one  by  one.
     After  all inputs are accumulated, the output generated
     by the function is a new tuple which  consists  of  the
     aggregated data.


Structural Aggregate Function

     The  input  to  structural  aggregation  is a tuple, or
     rather a set of tuples introduced one at a  time.   The
     output  of structural aggregation may either be a docu-
     ment, in which case one of the inputs will also be a o




















Search Engine

     Here is a brief list  and  explanation  of  the  Search
Engine  operators  which generating execution plans from our
query corpus has discovered.  These operations can  be  per-
formed on any appropriate Posting field in a tuple.

All of these SE operators are expressed as full-blown opera-
tors.  In execution it may often be possible  to  plumb  the
functionality onto an existing operator.  There may be limi-
tations on how that plumbing may occur,  however,  so  there
still may be a need for a full-fledged version of the opera-
tors.

Contains
     This has been there all along.  The L input is an  Ele-
     ment or an Attribute, something which contain something
     else.  The R input for Elements can be  Elements,  Pay-
     load  Words,  Attributes,  or  Attribute  Words.  The R









                             -3-


     input for Attributes can be Attribute Words.  It  finds
     all  occurences of a R input which is nested within the
     structure of the L input.

It is possible to negate the condition of a contains  opera-
tor, which converts it to not-contains.  For both normal and
not contains, the semantics of containment  of  null  values
must  be  considered; given the variability in null handling
between queries, it seems best to leave that decision to the
optimizer  and  allow  the  operator  to produce all variant
results.

There is an orthogonal component  to  contain  operators;  a
contain  may  be executed by any join.  Choice of join algo-
rithm is possible based upon input streams,  expected  data,
statistics,  and  other  such criteria.  An appropriate con-
tains expression, in the guise of a predicate, can  be  sup-
plied  and  performed.   With  this methodology, contains is
nothing but an ordinary join, and not a dedicated  operator.

Direct-Contains
     Again,  this  operators is already present.  The inputs
     are the same as the contains operator.   It  finds  all
     occurences of a R input which is directly nested within
     the structure of the L input.

Only-Contains
     This is a variant of Direct-Contains.  I  believe  it's
     current  name in the system is is, however it really is
     a form of contains.  Inputs are the same  as  contains.
     It  returns  all occurences of a R input being the only
     thing directly nested within the L input.

Exists-Contains
     This is another variant of Contains, though it can be a
     variant  on  any  contains variant.  The above contains
     operators return a complete  list  of  matching  pairs.
     However,  there  can be cases where that information is
     not needed by the rest of the query; it  qualifies  the
     node for other purposes.  One example of this is unnest
     for other values.  This singleton variant provides  the
     L input if the qualifying condition is true.  As in all
     the other operators, the R input may  be  projected  if
     needed.   Note  that Exists-contains is the behavior of
     the current contains code, as it qualifies a  node  for
     just  the first instance of a match, allowing unnest to
     do the bulk of the work.  In the new IM  and  SE,  con-
     tains  does  much  of  the work which unnest previously
     performed.

Range
     It is often necessary to extract an arbitrary range  of
     matches  on  a input stream.  Ordering of the stream is
     not the responsibility of the  range  operator,  it  is









                             -4-


     repsonsible for selecting a subset of whatever ordering
     the stream has.  For example range  use,  all  combina-
     tions of the first match, or the first several matches,
     or a particular match, or a range of  matches,  or  all
     matches after N are possibilities.  Rank, Top and Range
     can all be represented by a two-argument range  expres-
     sion  which  takes  a  begin and end specification of a
     range.   Begin values include start-of-document (other-
     wise  known  as rank 1), and end values include end-of-
     document.  When end-of-document is specified, the start
     argument  may  be negative to specify distance from the
     end.  Translations of common requests are shown here:

               +----------------------------------+
               |Top(5)            Range(Start, 5) |
               |Rank(3)           Range(3,3)      |
               |Between(10,15)    Range(10,15)    |
               |Between(9, End)   Range(9, End)   |
               |Last(5)           Range(-5, End)  |
               +----------------------------------+

The last form need not be implemented, I mention  it  to  be
complete.   It  is the only form which requires the operator
to store an arbitrary,  but  known  in  advance,  number  of
tuples  before it generates its result.  As such it is also,
of necessity, a blocking operator.

Range is trivial to implement since it  has  nothing  to  do
with ordering.  When performing multi-document queries it is
necessary to combine  range  with  grouping  or  aggregation
operators  to  provide  per-document  results in the typical
case.  As long as the input stream obeys the  assumed  docu-
ment_id-order  model  this  is trivial to implement in range
itself.  If an  non-document_id-order  stream  is  used,  it
probably  best to use the grouping operator and provide rank
as an aggregation predicate to it.  Note that we may need to
upgrade  the  contents  of  the  IDREF table to provide type
information of destination nodes to allow for  proper  indi-
rection  based  queries,  as the destination may be an arbi-
trary element.

Deref
     The drefer operator is used to provide  access  to  the
     refid  to  id table.  In other words it is a probe-join
     used to provide dreference information for IDREF infor-
     mation.   It  is  innapropriate to use a normal join in
     this case as IDREFs  do  not  have  any  order  in  the
     requesting  document.  Information returned by deref is
     not in sorted order.  IDREFs do not  reference  IDs  in
     document  order.   If an order is desired on that field
     it must be applied via an operator.

Ref-By
     The ref-by operator is something we are considering for









                             -5-


     inclusion  to  aid  queries which require such informa-
     tion.  It finds IDREFs which correspond to an ID.   One
     implementation  of  this  operator is to perform a full
     join, instead of a probe join, of the input against the
     IDREF  index.   Another  possible  implementation is to
     provide  both   forward   (IDREFs->ID)   and   backward
     (ID->IDREFs)  indices  on  the IDREF table.  Most notes
     about deref apply equally to refby.

Is it possible to use a  multi-dimensional  index  for  such
mapping?

Reinject
     Experimental  The intent of the reinject operator is to
     allow a query stream to re-enter the SE  after  leaving
     it.  I thought I had good reason for its existence, but
     perhaps it is too complex to implement.  It seems  that
     it  is  necessary for executing correlated sub-queries.
     For example, the reinject operator contains a simple QE
     expression, into which it can insert values or Postings
     from the input tuple.  The simple SE query may then  be
     executed with those parameters, the results output, and
     the next tuple processed.  If the expression is complex
     it  is  better  to try to integrate it into the overall
     query plan.  However some plans, with the right statis-
     tics,  could  use this to great advantage to reduce the
     work needed for some queries.  We weed to find  a  good
     exaple of why this is important, to decide if it should
     be tossed or not.

Merge
     The merge operator takes two streams  of  postings  and
     merges  them.  If the streams are in document and docu-
     ment_id order the output will have the same order.  For
     example, using an earlier query:

                (A contains B) or (A contains C)

     One plan is to query

                     A contains (B merge C)

     It may be desireable for merge to project an additional
     field into the output which reflects which input stream
     the  merged  value originated from.  This would be used
     for later select  predicates  to  discriminate  between
     different matches.

Except
     The  except  operator  outputs  all Postings from the L
     input, except those which exist  in  the  R  input.   I
     believe  this operator may also be known as difference.











                             -6-


Project
     For all intents and purposes, we can consider  all  the
     SE  operators  to always add more fields to the tuples.
     However, some of those values will no longer be  needed
     for  further query processing and should be eliminated.
     The project operator takes a single  input  stream  and
     projects  desired fields from that stream to the output
     stream.  It is interesting to observe that project  can
     be  considered a special case of a generic sorted merge
     operator with project capabilities ..  a  single  input
     merge.

Query Engine

     The  following  are  the Query Engine operators we have
found a need for while  creating  execution  plans  for  our
query corpus.  As noted in the Search Engine section, it may
be possible to plumb together operators directly for  execu-
tion,  so that individual operators are not required at run-
time.  The purpose of each operators is mentioned by itself,
as  it  stands on its own and can be optimized the same way.
For example, an operator which adds fields to a tuple has an
implicit project functionality built into it.

Simple-Unnest
     To  one point of view, Unnest is the translator between
     the SE stream and the QE stream.  To another  point  of
     view,  unnest just adds values to a tuple.  In the cur-
     rent Niagara,  unnest  always  performs  an  exhaustive
     search,  using the DM, to unnest the path expression in
     question.  This can be an  expensive  operation.   How-
     ever,  the  new  Niagara  can reduce the amount of work
     required by unnest,  as  it  provides  the  exact  ele-
     ment_ids  of elements to be unnested.  With this infor-
     mation unnest need only  extract  the  required  values
     from  the  document  and  add  them to the tuple.  If a
     expression to be unnested is found to be large,  or  to
     be  a XML subtree, the value is not added to the tuple.
     Instead a flag is placed in the extracted  value  field
     of  the  tuple  which indicates that the value is large
     and that an expensive evaluation must be performed upon
     demand.   Note: This implies that the XNode correspond-
     ing to that value is always kept in the  tuple  by  the
     execution plan generator.  If the expected atomic value
     is a small subtree, it can be converted  to  a  textual
     representation  and  used  for  further  queries, if it
     falls below some size threshold.  Note  that  the  con-
     trolling  XNode  will always be used for node identity,
     as unnested values are just that --  anonymous  values.
     If  something to be unnested is not found, there may be
     either an error or the value treated as a  null  value.
     Such decision should be made by the plan generator, not
     the runtime.   The  runtime  will  either  generate  an
     error,  or put a flag in the value slot indicating that









                             -7-


     the value is null.

Unnest
     This version of  unnest  is  the  full-blown  expensive
     unnest  that  is  currently  available  in  the system.
     There are some cases where results can not be  supplied
     from the SE to allow use of Simple-unnest; in that case
     the exhaustive search of the document in the DM must be
     performed.   Other than that detail, Unnest does every-
     thing which is mentiond for simple-unnest.

Merge
     The merge operator takes multiple streams of tuples and
     merges  them  together.   It  is be possible to specify
     predicates of how the tuples should be merged, though I
     don't know how useful that may ultimately be.

Contruct
     Construct  is  a family of operators which are directly
     related to the algebra.  Given input tuples  new  docu-
     ments  or  document  fragments are constructed from the
     values available in the tuple.

Filter-Construct
     The filter-construct operator is a special construction
     operator  which  implements  the  filter  semantics  of
     XQuery.  The input to filter-construct is a  stream  of
     candidate  Postings  or XNodes.  A state stack is main-
     tained to connect  the  XNodes  together,  using  their
     start  and  end  numbers to determine the closest match
     document structure as mentioned in  the  XQuery  paper.
     The resulting document may be a a single cohesive docu-
     ment or an ordered forrest.

Rank See the rank operator in the Search Engine section  for
     details.

Sort Yup  ...  Sorting  ..   we  all know what it is.  'Nuff
     said.

Group-By
     Strictly speaking, group-by in  XQuery  and  XML  means
     structural  aggregation.   Due  to that necessary evil,
     the grouping subsystem must be capable of grouping both
     a  large  number of groups as well as a large amount of
     data in individual groups.  This is  considerably  dif-
     ferent  from  standard  relational  grouping which only
     requires a large group count and storage for the aggre-
     gate  result  and  temporary space used to develop that
     result.

Note this only discusses grouping and aggregation at a  con-
ceptual  level; see the vignette on grouping and aggregation
for the details.  Conceptually the group-by operator takes a









                             -8-


stream  as  an input and has an known or potentially unknown
number of streams as an output.  Each of the output  streams
corresponds  to a unique grouping value.  Given this, group-
by is a simple switch which routes packets to an appropriate
output stream.  It has nothing to do with aggregation, stor-
age, or any other issues.

To extract the output of this conceptual

Aggregation
     Aggregate operations can be used both with the group-by
     operator  and as a standalone operator.  With the above
     mentioned group-by  operator,  aggregate  handling  is,
     conceptually  performed by simple, stream based, aggre-
     gate operators for either case.  Almost anything can be
     implemented  as  an  aggregate function, and it will be
     possible to perform multiple  aggregate  operations  as
     well  as  filter (aka select operator) aggregates which
     are processed.  I'll mention some  aggregate  operators
     here  as  an  example,  but again, the framework allows
     most anything to be  implemented.   See  the  aggregate
     vignette for details.