Update of /cvsroot/monetdb/pathfinder/compiler/algebra/prop
In directory sc8-pr-cvs16.sourceforge.net:/tmp/cvs-serv13092/algebra/prop

Modified Files:
        Makefile.ag 
Added Files:
        prop_req_node.c 
Log Message:
-- Added node based properties that check (top-down) if ...

    ... the node may be used (indirectly) for serialization

    ... the node id may be used

    ... the node order may be used

    ... the node values may be accessed

    ... a downward axis is applied lateron
        (child, descendant, descendant-or-self)

    ... a side-way axis is applied lateron
        (following, following-sibling, preceding, preceding-sibling)

    ... an upward axis is applied lateron
        (parent, ancestor, ancestor-or-self)

    ... a self axis is applied lateron
        (self, ancestor-or-self, descendant-or-self)

    ... the node may be used as input to node construction

-- Exploited the node base property that checks for the downward axis
   property:
  
   For every content constructor whose input is not queried we can
   use the physical shallow content constructor that makes use of
   references instead of creating a subtree copy.

   (This sped up the execution time of XMark Q10 (scale factor 1)
    by 60% and the execution time of XMark Q15 by 150%.)


U Makefile.ag
Index: Makefile.ag
===================================================================
RCS file: /cvsroot/monetdb/pathfinder/compiler/algebra/prop/Makefile.ag,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- Makefile.ag 11 Jan 2008 10:46:59 -0000      1.14
+++ Makefile.ag 1 Apr 2008 16:37:15 -0000       1.15
@@ -45,6 +45,7 @@
                 prop_ocol.c \
                 prop_ori_names.c \
                 prop_rec_delta.c \
+                prop_req_node.c \
                 prop_reqval.c \
                 prop_set.c \
                 prop_trace_names.c \

--- NEW FILE: prop_req_node.c ---
/**
 * @file
 *
 * @brief Inference of required node value property of logical
 *        algebra expressions.
 *
 *
 * Copyright Notice:
 * -----------------
 *
 * The contents of this file are subject to the Pathfinder Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License.  You may obtain a copy of the License at
 * http://monetdb.cwi.nl/Legal/PathfinderLicense-1.1.html
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
 * the License for the specific language governing rights and limitations
 * under the License.
 *
 * The Original Code is the Pathfinder system.
 *
 * The Original Code has initially been developed by the Database &
 * Information Systems Group at the University of Konstanz, Germany and
 * is now maintained by the Database Systems Group at the Technische
 * Universitaet Muenchen, Germany.  Portions created by the University of
 * Konstanz and the Technische Universitaet Muenchen are Copyright (C)
 * 2000-2005 University of Konstanz and (C) 2005-2008 Technische
 * Universitaet Muenchen, respectively.  All Rights Reserved.
 *
 * $Id: prop_req_node.c,v 1.1 2008/04/01 16:37:16 tsheyar Exp $
 */

/* always include pathfinder.h first! */
#include "pathfinder.h"

#include <assert.h>
#include <stdio.h>

#include "properties.h"

#include "alg_dag.h"
#include "oops.h"
#include "mem.h"

/* Easily access subtree-parts */
#include "child_mnemonic.h"

#define SEEN(p) ((p)->bit_dag)

/* store the number of incoming edges for each operator
   in the refctr field */
#define EDGE(n) ((n)->refctr)

#define type_of(n,a) PFprop_type_of ((n), (a))

/* required node property list */
struct req_node_t {
    PFalg_att_t col;       /* column name ... */
    
    /* ... and the corresponding property that tests if ... */

    bool        serialize; /* ... the node may be used (indirectly) for
                              serialization */
    bool        id;        /* ... the node id may be used */
    bool        order;     /* ... the node order may be used */
    bool        access;    /* ... the node values may be accessed */
    bool        axis_down; /* ... a downward axis is applied lateron */
    bool        axis_side; /* ... a side-way axis is applied lateron */
    bool        axis_up;   /* ... an upward axis is applied lateron */
    bool        axis_self; /* ... a *self axis is applied lateron */
    bool        constr;    /* ... the node may be used as input to
                              node construction */
};
typedef struct req_node_t req_node_t;

#define MAP_LIST(n)       ((n)->prop->req_node_vals)
#define ADD(l,p)          (*((req_node_t *) PFarray_add ((l))) = (p))
#define MAP_AT(n,i)       (*((req_node_t *) PFarray_at ((n), (i))))

#define COL_AT(n,i)       (((req_node_t *) PFarray_at ((n), (i)))->col)
#define SERIALIZE_AT(n,i) (((req_node_t *) PFarray_at ((n), (i)))->serialize)
#define ID_AT(n,i)        (((req_node_t *) PFarray_at ((n), (i)))->id)
#define ORDER_AT(n,i)     (((req_node_t *) PFarray_at ((n), (i)))->order)
#define ACCESS_AT(n,i)    (((req_node_t *) PFarray_at ((n), (i)))->access)
#define AXIS_DOWN_AT(n,i) (((req_node_t *) PFarray_at ((n), (i)))->axis_down)
#define AXIS_SIDE_AT(n,i) (((req_node_t *) PFarray_at ((n), (i)))->axis_side)
#define AXIS_UP_AT(n,i)   (((req_node_t *) PFarray_at ((n), (i)))->axis_up)
#define AXIS_SELF_AT(n,i) (((req_node_t *) PFarray_at ((n), (i)))->axis_self)
#define CONSTR_AT(n,i)    (((req_node_t *) PFarray_at ((n), (i)))->constr)
    
/**
 * @brief look up the property mapping (in @a l) for a given column @a attr.
 */
static req_node_t *
find_map (PFarray_t *l, PFalg_att_t attr)
{
    if (!l)
        return NULL;

    for (unsigned int i = 0; i < PFarray_last (l); i++) {
        if (attr == COL_AT(l, i))
            return (req_node_t *) PFarray_at (l, i);
    }
    return NULL;
}

/**
 * @brief look up the property mapping (in @a l) for a given column @a attr.
 */
static void
add_map_ (PFla_op_t *n, PFalg_att_t attr,
          bool serialize, bool id, bool order,
          bool access, bool axis_down, bool axis_side,
          bool axis_up, bool axis_self, bool constr)
{
    req_node_t *map;
    assert (n);

    /* lookup the mapping (if present) */
    map = find_map (MAP_LIST(n), attr);
    
    /* add a new mapping */
    if (!map) {
        /* create a new mapping list if not already available */
        if (!MAP_LIST(n))
            MAP_LIST(n) = PFarray (sizeof (req_node_t), 3);
    
        *((req_node_t *) PFarray_add (MAP_LIST(n)))
            = (req_node_t) { .col       = attr,
                             .serialize = serialize,
                             .id        = id,
                             .order     = order,
                             .access    = access,
                             .axis_down = axis_down,
                             .axis_side = axis_side,
                             .axis_up   = axis_up,
                             .axis_self = axis_self,
                             .constr    = constr };
    }
    /* modify already existing mapping */
    else {
        map->serialize |= serialize;
        map->id        |= id;
        map->order     |= order;
        map->access    |= access;
        map->axis_down |= axis_down;
        map->axis_side |= axis_side;
        map->axis_up   |= axis_up;
        map->axis_self |= axis_self;
        map->constr    |= constr;
    }
}

#define add_map(n,attr) add_map_ ((n),(attr), \
                                  false, false, false \
                                  false, false, false \
                                  false, false, false)
#define add_serialize_map(n,attr) \
        add_map_ ((n),(attr), true , false, false, \
                  false, false, false, false, false, false)
#define add_id_map(n,attr) \
        add_map_ ((n),(attr), false, true , false, \
                  false, false, false, false, false, false)
#define add_order_map(n,attr) \
        add_map_ ((n),(attr), false, false, true , \
                  false, false, false, false, false, false)
#define add_access_map(n,attr) \
        add_map_ ((n),(attr), false, false, false, \
                  true , false, false, false, false, false)
#define add_axis_down_map(n,attr) \
        add_map_ ((n),(attr), false, false, false, \
                  false, true , false, false, false, false)
#define add_axis_side_map(n,attr) \
        add_map_ ((n),(attr), false, false, false, \
                  false, false, true , false, false, false)
#define add_axis_up_map(n,attr) \
        add_map_ ((n),(attr), false, false, false, \
                  false, false, false, true , false, false)
#define add_axis_self_map(n,attr) \
        add_map_ ((n),(attr), false, false, false, \
                  false, false, false, false, true , false)
#define add_constr_map(n,attr) \
        add_map_ ((n),(attr), false, false, false, \
                  false, false, false, false, false, true)


/**
 * @brief Test if column @a attr is linked to any node properties.
 */
bool
PFprop_node_property (const PFprop_t *prop, PFalg_att_t attr)
{
    return (find_map (prop->req_node_vals, attr) != NULL);
}

/**
 * @brief Test if the subtree of column @a attr is queried.
 */
bool
PFprop_node_content_queried (const PFprop_t *prop, PFalg_att_t attr)
{
    req_node_t *map = find_map (prop->req_node_vals, attr);

    if (!map)
        return true;
    else
        return map->axis_down;
}

/**
 * @brief Test if the nodes of column @a attr are serialized.
 */
bool
PFprop_node_serialize (const PFprop_t *prop, PFalg_att_t attr)
{
    req_node_t *map = find_map (prop->req_node_vals, attr);

    if (!map)
        return true;
    else
        return map->serialize;
}

/**
 * worker for PFprop_infer_req_node
 * infers the required node properties during the second run
 * (uses edge counter from the first run)
 */
static void
prop_infer_req_node_vals (PFla_op_t *n, PFarray_t *req_node_vals)
{
    req_node_t *map;
    
    assert (n);

    /* initialize the mapping list if we need it
       and haven't got one already */
    if (!MAP_LIST(n) && req_node_vals && PFarray_last (req_node_vals) > 0)
        MAP_LIST(n) = PFarray (sizeof (req_node_t),
                               PFarray_last (req_node_vals) + 3);

    if (req_node_vals) {
        /* merge all mappings */
        for (unsigned int i = 0; i < PFarray_last (req_node_vals); i++) {
            /* Only try to merge nodes visible at that node.
               (Non-matching columns may result from binary
                operators as e.g., the cross product.) */
            if (!PFprop_ocol (n, COL_AT(req_node_vals, i)) &&
                /* special case for constructors */
                n->kind != la_fcns &&
                n->kind != la_docnode &&
                n->kind != la_element &&
                n->kind != la_textnode &&
                n->kind != la_comment &&
                n->kind != la_attribute &&
                n->kind != la_processi &&
                n->kind != la_content)
                continue;

            /* lookup the mapping in the already existing mapping list */
            map = find_map (MAP_LIST(n), COL_AT(req_node_vals, i));

            /* modify the mapping */
            if (map) {
                map->serialize |= SERIALIZE_AT(req_node_vals, i);
                map->id        |= ID_AT(req_node_vals, i);
                map->order     |= ORDER_AT(req_node_vals, i);
                map->access    |= ACCESS_AT(req_node_vals, i);
                map->axis_down |= AXIS_DOWN_AT(req_node_vals, i);
                map->axis_side |= AXIS_SIDE_AT(req_node_vals, i);
                map->axis_up   |= AXIS_UP_AT(req_node_vals, i);
                map->axis_self |= AXIS_SELF_AT(req_node_vals, i);
                map->constr    |= CONSTR_AT(req_node_vals, i);
            }
            else
                ADD(MAP_LIST(n), MAP_AT(req_node_vals, i));
        }
    }
                
    /* nothing to do if we haven't collected
       all incoming required node property lists of that node */
    if (EDGE(n) > 1) {
        EDGE(n)--;
        return;
    }

    switch (n->kind) {
        case la_serialize_seq:
            if (type_of (n, n->sem.ser_seq.item) & aat_node)
                add_serialize_map (n, n->sem.ser_seq.item);

            if (type_of (n, n->sem.ser_seq.pos) & aat_node)
                add_order_map (n, n->sem.ser_seq.pos);
                
            prop_infer_req_node_vals (L(n), NULL); /* fragments */
            prop_infer_req_node_vals (R(n), MAP_LIST(n));
            return; /* only infer once */

        case la_serialize_rel:
            if (type_of (n, n->sem.ser_rel.pos) & aat_node)
                add_order_map (n, n->sem.ser_rel.pos);
            
            for (unsigned int i = 0; i < n->sem.ser_rel.items.count; i++)
                if (type_of (n, n->sem.ser_rel.items.atts[i]) & aat_node)
                    add_serialize_map (n, n->sem.ser_rel.items.atts[i]);
            break;

        case la_lit_tbl:
        case la_empty_tbl:
        case la_ref_tbl:
        case la_empty_frag:
        case la_nil:
            /* leafs */
            break;

        case la_attach:
            assert ((type_of (n, n->sem.attach.res) & aat_node) == 0);
            break;

        case la_cross:
            break;

        case la_eqjoin:
        case la_semijoin:
            if (type_of (n, n->sem.eqjoin.att1) & aat_node) {
                add_id_map (n, n->sem.eqjoin.att1);
                add_id_map (n, n->sem.eqjoin.att2);
            }
            break;

        case la_thetajoin:
            /* add all join columns to the inferred icols */
            for (unsigned int i = 0; i < n->sem.thetajoin.count; i++)
                if (type_of (n, n->sem.thetajoin.pred[i].left) & aat_node) {
                    add_id_map (n, n->sem.thetajoin.pred[i].left);
                    add_id_map (n, n->sem.thetajoin.pred[i].right);
                }
            break;

        case la_project:
            if (MAP_LIST(n) != NULL && PFarray_last (MAP_LIST(n)) > 0) {
                PFarray_t *new_map = PFarray (sizeof (req_node_t),
                                              PFarray_last (MAP_LIST(n)));

                for (unsigned int i = 0; i < n->sem.proj.count; i++) {
                    map = find_map (MAP_LIST(n), n->sem.proj.items[i].new);
                    if (map) {
                        req_node_t map_item = *map;
                        map_item.col = n->sem.proj.items[i].old;
                        ADD(new_map, map_item);
                    }
                }

                prop_infer_req_node_vals (L(n), new_map);
                return; /* only infer once */
            }
            break;

        case la_select:
            break;

        case la_pos_select:
        {
            PFord_ordering_t sortby = n->sem.pos_sel.sortby;
            for (unsigned int i = 0; i < PFord_count (sortby); i++)
                if (type_of (n, PFord_order_col_at (sortby, i)) & aat_node)
                    add_order_map (n, PFord_order_col_at (sortby, i));
            
            if (n->sem.pos_sel.part &&
                type_of (n, n->sem.pos_sel.part) & aat_node)
                add_id_map (n, n->sem.pos_sel.part);
        }   break;

        case la_disjunion:
            break;
            
        case la_intersect:
        case la_difference:
        case la_distinct:
            for (unsigned int i = 0; i < n->schema.count; i++)
                if (n->schema.items[i].type & aat_node)
                    add_id_map (n, n->schema.items[i].name);
            break;
            
        case la_fun_1to1:
            /* mark the input columns as access columns */
            for (unsigned int i = 0; i < n->sem.fun_1to1.refs.count; i++)
                if (type_of (n, n->sem.fun_1to1.refs.atts[i]) & aat_node)
                    add_access_map (n, n->sem.fun_1to1.refs.atts[i]);
            break;

        case la_num_eq:
        case la_num_gt:
            if (type_of (n, n->sem.binary.att1) & aat_node) {
                add_id_map (n, n->sem.binary.att1);
                add_id_map (n, n->sem.binary.att2);
            }
            break;
            
        case la_to:
        case la_bool_or:
        case la_bool_and:
            /* the output cannot be of type node */
            assert ((type_of (n, n->sem.binary.att1) & aat_node) == 0);
            break;

        case la_bool_not:
            /* the output cannot be of type node */
            assert ((type_of (n, n->sem.unary.att) & aat_node) == 0);
            break;

        case la_avg:
        case la_max:
        case la_min:
        case la_sum:
        case la_count:
        case la_seqty1:
        case la_all:
            /* the output cannot be of type node */
            if (!n->sem.aggr.part) {
                prop_infer_req_node_vals (L(n), NULL);
            }
            break;

        case la_rownum:
        case la_rowrank:
        case la_rank:
        {
            PFord_ordering_t sortby = n->sem.sort.sortby;
            for (unsigned int i = 0; i < PFord_count (sortby); i++)
                if (type_of (n, PFord_order_col_at (sortby, i)) & aat_node)
                    add_order_map (n, PFord_order_col_at (sortby, i));
            
            if (n->sem.sort.part &&
                type_of (n, n->sem.sort.part) & aat_node)
                add_id_map (n, n->sem.sort.part);
        }   break;
            
        case la_rowid:
            /* the output cannot be of type node */
            break;
            
        case la_cast:
        case la_type:
            assert ((type_of (n, n->sem.type.res) & aat_node) == 0);
            assert ((type_of (n, n->sem.type.att) & aat_node) == 0);
            break;

        case la_type_assert:
            break;

        case la_step:
        case la_guide_step:
            assert ((type_of (n, n->sem.step.iter) & aat_node) == 0);
        {
            PFarray_t *new_map = PFarray (sizeof (req_node_t), 1),
                      *old_map;
            
            map = find_map (MAP_LIST(n), n->sem.step.item_res);

            /* inherit the properties of the output */
            if (map) {
                req_node_t map_item = *map;
                map_item.col = n->sem.step.item;
                ADD(new_map, map_item);
            }
            
            /* replace current map by new_map and store the current */
            old_map = MAP_LIST(n);
            MAP_LIST(n) = new_map;
            
            switch (n->sem.step.spec.axis) {
                case alg_anc_s:
                    add_axis_self_map (n, n->sem.step.item);
                case alg_anc:
                case alg_par:
                    add_axis_up_map (n, n->sem.step.item);
                    break;

                case alg_desc_s:
                    add_axis_self_map (n, n->sem.step.item);
                case alg_attr:
                case alg_chld:
                case alg_desc:
                    add_axis_down_map (n, n->sem.step.item);
                    break;
                    
                case alg_fol:
                case alg_fol_s:
                case alg_prec:
                case alg_prec_s:
                    add_axis_side_map (n, n->sem.step.item);
                    break;
                                 
                case alg_self:
                    add_axis_self_map (n, n->sem.step.item);
                    break;
            }
            
            /* switch back */
            MAP_LIST(n) = old_map;
            
            prop_infer_req_node_vals (L(n), NULL); /* fragments */
            prop_infer_req_node_vals (R(n), new_map);
        }   return; /* only infer once */

        case la_step_join:
        case la_guide_step_join:
            map = find_map (MAP_LIST(n), n->sem.step.item_res);

            /* inherit the properties of the output */
            if (map) {
                req_node_t map_item = *map;
                map_item.col = n->sem.step.item;
                ADD(MAP_LIST(n), map_item);
            }
            
            switch (n->sem.step.spec.axis) {
                case alg_anc_s:
                    add_axis_self_map (n, n->sem.step.item);
                case alg_anc:
                case alg_par:
                    add_axis_up_map (n, n->sem.step.item);
                    break;

                case alg_desc_s:
                    add_axis_self_map (n, n->sem.step.item);
                case alg_attr:
                case alg_chld:
                case alg_desc:
                    add_axis_down_map (n, n->sem.step.item);
                    break;
                    
                case alg_fol:
                case alg_fol_s:
                case alg_prec:
                case alg_prec_s:
                    add_axis_side_map (n, n->sem.step.item);
                    break;
                                 
                case alg_self:
                    add_axis_self_map (n, n->sem.step.item);
                    break;
            }
            
            prop_infer_req_node_vals (L(n), NULL); /* fragments */
            prop_infer_req_node_vals (R(n), MAP_LIST(n));
            return; /* only infer once */

        case la_doc_index_join:
            map = find_map (MAP_LIST(n), n->sem.step.item_res);

            /* inherit the properties of the output */
            if (map) {
                req_node_t map_item = *map;
                map_item.col = n->sem.step.item;
                ADD(MAP_LIST(n), map_item);
            }
            
            /* we need to look up the ids in a special relation */
            add_id_map (n, n->sem.step.item);
            
            prop_infer_req_node_vals (L(n), NULL); /* fragments */
            prop_infer_req_node_vals (R(n), MAP_LIST(n));
            return; /* only infer once */

        case la_doc_tbl:
            if (MAP_LIST(n) != NULL && PFarray_last (MAP_LIST(n)) > 0) {
                PFarray_t *new_map = PFarray (sizeof (req_node_t),
                                              PFarray_last (MAP_LIST(n)));
                for (unsigned int i = 0; i < PFarray_last (MAP_LIST(n)); i++)
                    if (COL_AT(MAP_LIST(n), i) != n->sem.doc_tbl.res)
                        ADD(new_map, MAP_AT(MAP_LIST(n), i));

                prop_infer_req_node_vals (L(n), new_map);
                return; /* only infer once */
            }
            break;

        case la_doc_access:
            assert ((type_of (n, n->sem.doc_access.res) & aat_node) == 0);
            add_access_map (n, n->sem.doc_access.att);
            
            prop_infer_req_node_vals (L(n), NULL); /* fragments */
            prop_infer_req_node_vals (R(n), MAP_LIST(n));
            return; /* only infer once */

        case la_twig:
            if (MAP_LIST(n) != NULL && PFarray_last (MAP_LIST(n)) > 0) {
                PFarray_t *new_map = PFarray (sizeof (req_node_t), 2);
                
                map = find_map (MAP_LIST(n), n->sem.iter_item.iter);

                /* inherit the properties of the iter column */
                if (map) {
                    req_node_t map_item = *map;
                    map_item.col = att_iter;
                    ADD(new_map, map_item);
                }
                
                map = find_map (MAP_LIST(n), n->sem.iter_item.item);

                /* inherit the properties of the item column */
                if (map) {
                    req_node_t map_item = *map;
                    map_item.col = att_item;
                    /* if no downward axis step is applied
                       to the constructed fragment the id,
                       order, and access properties of the
                       content are not needed. */
                    if (map_item.axis_down == false) {
                        map_item.id     = false;
                        map_item.order  = false;
                        map_item.access = false;
                    }
                    
                    ADD(new_map, map_item);
                }
                
                prop_infer_req_node_vals (L(n), new_map);
                return; /* only infer once */
            }
            break;
            
        case la_fcns:
            break;

        case la_docnode:
            if (MAP_LIST(n) != NULL && PFarray_last (MAP_LIST(n)) > 0) {
                PFarray_t *new_map = PFarray (sizeof (req_node_t), 1);
                
                map = find_map (MAP_LIST(n), att_iter);

                /* inherit the properties of the iter column */
                if (map) {
                    req_node_t map_item = *map;
                    map_item.col = n->sem.docnode.iter;
                    ADD(new_map, map_item);
                }
                
                prop_infer_req_node_vals (L(n), new_map);
                return; /* only infer once */
            }
            break;

        case la_element:
            if (MAP_LIST(n) != NULL && PFarray_last (MAP_LIST(n)) > 0) {
                PFarray_t *new_map = PFarray (sizeof (req_node_t), 1);
                
                map = find_map (MAP_LIST(n), att_iter);

                /* inherit the properties of the iter column */
                if (map) {
                    req_node_t map_item = *map;
                    map_item.col = n->sem.iter_item.iter;
                    ADD(new_map, map_item);
                }
                
                prop_infer_req_node_vals (L(n), new_map);
                prop_infer_req_node_vals (R(n), MAP_LIST(n));
                return; /* only infer once */
            }
            break;

        case la_textnode:
        case la_comment:
            if (MAP_LIST(n) != NULL && PFarray_last (MAP_LIST(n)) > 0) {
                PFarray_t *new_map = PFarray (sizeof (req_node_t), 1);
                
                map = find_map (MAP_LIST(n), att_iter);

                /* inherit the properties of the iter column */
                if (map) {
                    req_node_t map_item = *map;
                    map_item.col = n->sem.iter_item.iter;
                    ADD(new_map, map_item);
                }
                
                prop_infer_req_node_vals (L(n), new_map);
                return; /* only infer once */
            }
            break;

        case la_attribute:
        case la_processi:
            if (MAP_LIST(n) != NULL && PFarray_last (MAP_LIST(n)) > 0) {
                PFarray_t *new_map = PFarray (sizeof (req_node_t), 2);
                
                map = find_map (MAP_LIST(n), att_iter);

                /* inherit the properties of the iter column */
                if (map) {
                    req_node_t map_item = *map;
                    map_item.col = n->sem.iter_item1_item2.iter;
                    ADD(new_map, map_item);
                }
                
                prop_infer_req_node_vals (L(n), new_map);
                return; /* only infer once */
            }
            break;

        case la_content:
        {
            PFarray_t *new_map = PFarray (sizeof (req_node_t), 2),
                      *old_map;
            
            map = find_map (MAP_LIST(n), att_iter);

            /* inherit the properties of the iter column */
            if (map) {
                req_node_t map_item = *map;
                map_item.col = n->sem.iter_pos_item.iter;
                ADD(new_map, map_item);
            }
            
            map = find_map (MAP_LIST(n), att_item);

            /* inherit the properties of the iter column */
            if (map) {
                req_node_t map_item = *map;
                map_item.col = n->sem.iter_pos_item.item;
                ADD(new_map, map_item);
            }

            /* replace current map by new_map and store the current */
            old_map = MAP_LIST(n);
            MAP_LIST(n) = new_map;
            
            add_constr_map (n, n->sem.iter_pos_item.item);
            
            /* switch back */
            MAP_LIST(n) = old_map;
            
            prop_infer_req_node_vals (L(n), NULL); /* fragments */
            prop_infer_req_node_vals (R(n), new_map);
            return; /* only infer once */
        }

        case la_merge_adjacent:
            add_constr_map (n, n->sem.merge_adjacent.item_in);
            
            prop_infer_req_node_vals (L(n), NULL); /* fragments */
            prop_infer_req_node_vals (R(n), MAP_LIST(n));
            return; /* only infer once */

        case la_roots:
        case la_proxy:
        case la_proxy_base:
        case la_dummy:
        case la_error:
            /* propagate required property list to left subtree */
            break;
            
        case la_fragment:
        case la_frag_extract:
            prop_infer_req_node_vals (L(n), NULL); /* fragments */
            return; /* only infer once */

        case la_frag_union:
            prop_infer_req_node_vals (L(n), NULL); /* fragments */
            prop_infer_req_node_vals (R(n), NULL); /* fragments */
            return; /* only infer once */

        case la_cond_err:
            assert ((type_of (R(n), n->sem.err.att) & aat_node) == 0);
            prop_infer_req_node_vals (L(n), MAP_LIST(n));
            prop_infer_req_node_vals (R(n), NULL);
            return; /* only infer once */

        case la_trace:
            if (type_of (n, n->sem.iter_pos_item.item) & aat_node)
                add_serialize_map (n, n->sem.iter_pos_item.item);
            
            prop_infer_req_node_vals (L(n), MAP_LIST(n));
            prop_infer_req_node_vals (R(n), NULL); /* trace */
            return; /* only infer once */

        case la_trace_msg:
            assert ((type_of (n, n->sem.iter_item.item) & aat_node) == 0);
            prop_infer_req_node_vals (L(n), MAP_LIST(n));
            prop_infer_req_node_vals (R(n), NULL); /* trace */
            return; /* only infer once */

        case la_trace_map:
            assert ((type_of (n, n->sem.trace_map.inner) & aat_node) == 0);
            assert ((type_of (n, n->sem.trace_map.outer) & aat_node) == 0);
            prop_infer_req_node_vals (L(n), MAP_LIST(n));
            prop_infer_req_node_vals (R(n), NULL); /* trace */
            return; /* only infer once */

        case la_rec_fix:
        {
            PFarray_t *new_map = PFarray (sizeof (req_node_t),
                                          n->schema.count);
            
            for (unsigned int i = 0; i < n->schema.count; i++)
                if (n->schema.items[i].type & aat_node) {
                    req_node_t map_item;
                    map_item.col       = n->schema.items[i].name; 
                    map_item.serialize = true; 
                    map_item.id        = true; 
                    map_item.order     = true; 
                    map_item.access    = true; 
                    map_item.axis_down = true; 
                    map_item.axis_side = true; 
                    map_item.axis_up   = true; 
                    map_item.axis_self = true; 
                    map_item.constr    = true; 

                    ADD(new_map, map_item);
                }

            prop_infer_req_node_vals (L(n), NULL); /* recursion param */
            prop_infer_req_node_vals (R(n), new_map);
        }   return; /* only infer once */

        case la_rec_param:
            prop_infer_req_node_vals (L(n), NULL); /* recursion arg */
            prop_infer_req_node_vals (R(n), NULL); /* recursion param */
            return; /* only infer once */

        case la_rec_arg:
        {
            PFarray_t *new_map = PFarray (sizeof (req_node_t),
                                          n->schema.count);
            
            for (unsigned int i = 0; i < n->schema.count; i++)
                if (n->schema.items[i].type & aat_node) {
                    req_node_t map_item;
                    map_item.col       = n->schema.items[i].name; 
                    map_item.serialize = true; 
                    map_item.id        = true; 
                    map_item.order     = true; 
                    map_item.access    = true; 
                    map_item.axis_down = true; 
                    map_item.axis_side = true; 
                    map_item.axis_up   = true; 
                    map_item.axis_self = true; 
                    map_item.constr    = true; 

                    ADD(new_map, map_item);
                }

            prop_infer_req_node_vals (L(n), new_map);
            prop_infer_req_node_vals (R(n), new_map);
        }   return; /* only infer once */

        case la_rec_base:
            break;
            
        case la_fun_call:
            assert ((type_of (n, n->sem.fun_call.iter) & aat_node) == 0);
            prop_infer_req_node_vals (L(n), NULL);
            prop_infer_req_node_vals (R(n), NULL); /* function param */
            return; /* only infer once */
            
        case la_fun_param:
        {
            PFarray_t *new_map = PFarray (sizeof (req_node_t),
                                          n->schema.count);
            
            for (unsigned int i = 0; i < n->schema.count; i++)
                if (n->schema.items[i].type & aat_node) {
                    req_node_t map_item;
                    map_item.col       = n->schema.items[i].name; 
                    map_item.serialize = true; 
                    map_item.id        = true; 
                    map_item.order     = true; 
                    map_item.access    = true; 
                    map_item.axis_down = true; 
                    map_item.axis_side = true; 
                    map_item.axis_up   = true; 
                    map_item.axis_self = true; 
                    map_item.constr    = true; 

                    ADD(new_map, map_item);
                }

            prop_infer_req_node_vals (L(n), new_map);
            prop_infer_req_node_vals (R(n), NULL); /* function param */
        }   return; /* only infer once */
            
        case la_fun_frag_param:
            prop_infer_req_node_vals (L(n), NULL); /* fragments */
            prop_infer_req_node_vals (R(n), NULL); /* function param */
            return; /* only infer once */

        case la_cross_mvd:
            PFoops (OOPS_FATAL,
                    "clone column aware cross product operator is "
                    "only allowed inside mvd optimization!");

        case la_eqjoin_unq:
            PFoops (OOPS_FATAL,
                    "clone column aware equi-join operator is "
                    "only allowed with unique attribute names!");
            
        case la_string_join:
            if (MAP_LIST(n) != NULL && PFarray_last (MAP_LIST(n)) > 0) {
                PFarray_t *new_map = PFarray (sizeof (req_node_t), 1);
                
                map = find_map (MAP_LIST(n), n->sem.string_join.iter_res);

                /* inherit the properties of the iter column */
                if (map) {
                    req_node_t map_item = *map;
                    map_item.col = n->sem.string_join.iter;
                    ADD(new_map, map_item);
                }
                
                prop_infer_req_node_vals (L(n), new_map);

                PFarray_last (new_map) = 0;
                
                /* inherit the properties of the iter column */
                if (map) {
                    req_node_t map_item = *map;
                    map_item.col = n->sem.string_join.iter_sep;
                    ADD(new_map, map_item);
                }
                
                prop_infer_req_node_vals (R(n), new_map);
                return; /* only infer once */
            }
            break;
    }

    if (L(n)) prop_infer_req_node_vals (L(n), MAP_LIST(n));
    if (R(n)) prop_infer_req_node_vals (R(n), MAP_LIST(n));
}

/* worker for PFprop_infer_reqval */
static void
prop_infer (PFla_op_t *n)
{
    assert (n);

    /* count number of incoming edges
       (during first run) */
    EDGE(n)++;

    /* nothing to do if we already visited that node */
    if (SEEN(n))
        return;
    /* otherwise initialize edge counter (first occurrence) */
    else
        EDGE(n) = 1;

    /* infer properties for children */
    for (unsigned int i = 0; i < PFLA_OP_MAXCHILD && n->child[i]; i++)
        prop_infer (n->child[i]);

    SEEN(n) = true;

    /* reset required node property list
       (reuse already existing lists if already available
        as this increases the performance of the compiler a lot) */
    if (MAP_LIST(n))
        PFarray_last (MAP_LIST(n)) = 0;
}

/**
 * Infer required node properties for a DAG rooted in @a root
 */
void
PFprop_infer_req_node (PFla_op_t *root) {
    /* initial empty list of required node properties */
    PFarray_t *init = PFarray (sizeof (req_node_t), 0);

    /* collect number of incoming edges (parents) */
    prop_infer (root);
    PFla_dag_reset (root);

    /* second run infers required node properties */
    prop_infer_req_node_vals (root, init);
    PFla_dag_reset (root);
}

/* vim:set shiftwidth=4 expandtab: */


-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
_______________________________________________
Monetdb-pf-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/monetdb-pf-checkins

Reply via email to